blob: 56b8931657ec9e14d7aab51c2fe3f473e90f4122 [file] [log] [blame]
Jeff Thompson745026e2012-10-13 12:49:20 -07001/* This file is created by running make-ndn-js.jsm.sh in this directory.
2 * It concatenates ndn-js-header.txt with all the ndn-js source files to
3 * make ndn-js.jsm .
4 * author: ucla-cs
5 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07006 */
7
8var EXPORTED_SYMBOLS = ["NDN", "DataUtils", "readAllFromSocket"];
9
10Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
11Components.utils.import("resource://gre/modules/NetUtil.jsm");
12
13// LOG is used by some of the NDN code.
14var LOG = 0;
15
16// jsbn.js needs the navigator object which isn't defined in XPCOM, so make a local hack.
17var navigator = {
18 appName: "Netscape"
19};
20
21// Some code calls console.log without checking LOG>0. Until this is cleaned up, make a local hack console.
22var console = {
23 log: function(message) {
24 dump(message + "\n");
25 }
26};
27
Jeff Thompson745026e2012-10-13 12:49:20 -070028/*
29 * @author: ucla-cs
30 * See COPYING for copyright and distribution information.
31 * This class represents the top-level object for communicating with an NDN host.
32 */
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070033
34/**
35 * host is default '127.0.0.1'.
36 * port is default 9695.
37 */
38var NDN = function NDN(host, port){
39 this.host = (host || '127.0.0.1');
40 this.port = (port || 9695);
41};
42
43NDN.prototype.createRoute = function(host,port){
44 this.host=host;
45 this.port=port;
46}
47
48NDN.prototype.get = function(message){
49 if(this.host!=null && this.port!=null){
50 var output ='';
51 message = message.trim();
52 if(message==null || message =="" ){
53 console.log('INVALID INPUT TO GET');
54 return null;
55 }
56
57
58 //var array = Name.createNameArray(message);
59
60 int = new Interest(new Name(message));
61
62 int.InterestLifetime = 4200;
63
64 var hex = encodeToHexInterest(int);
65
66 //var result = get_java_socket_bridge().connectAndStart(ndnurl,ndnport,hex);
67
68 var result = get(this.host,this.port, hex);
69
70
71 if(LOG>0)console.log('BINARY RESPONSE IS ' +result);
72
73 if(result==null || result==undefined || result =="" ){
74 /*if(result[0] != '0'||result[1]!='4') {
75 if(LOG>2)console.log('INVALID ANSWER');
76 }*/
77 return null;
78 }
79
80 else{
81
82 co = decodeHexContentObject(result);
83
84 if(LOG>2) {
85 console.log('DECODED CONTENT OBJECT');
86 console.log(co);
87 }
88 return co;
89 }
90 }
91 else{
92
93 console.log('ERROR URL OR PORT NOT SET');
94
95 return null;
96
97 }
98
99
100}
101
102
103NDN.prototype.put = function(name,content){
104 if(this.host!=null && this.port!=null){
105
106 var co = this.get("/%C1.M.S.localhost/%C1.M.SRV/ccnd");
107
108 if(!co || !co.signedInfo || !co.signedInfo.publisher || !co.signedInfo.publisher.publisherPublicKeyDigest){
109 alert("Cannot contact router");
110
111 return null;
112 }
113
114 var ccnxnodename = co.signedInfo.publisher.publisherPublicKeyDigest;
115
116 name = name.trim();
117
118 var fe = new ForwardingEntry('selfreg',new Name(name),null, null, 3,2147483647);
119
120 var bytes = encodeForwardingEntry(fe);
121
122
123 var si = new SignedInfo();
124 si.setFields();
125
126 var co = new ContentObject(new Name(),si,bytes,new Signature());
127 co.sign();
128
129 var coBinary = encodeToBinaryContentObject(co);
130
131 //var ccnxnodename = unescape('%E0%A0%1E%099h%F9t%0C%E7%F46%1B%AB%F5%BB%05%A4%E5Z%AC%A5%E5%8Fs%ED%DE%B8%E0%13%AA%8F');
132
133 var interestName = new Name(['ccnx',ccnxnodename,'selfreg',coBinary]);
134
135 int = new Interest(interestName);
136 int.scope = 1;
137
138 var hex = encodeToHexInterest(int);
139
140 console.log('GOING TO PUT INTEREST OBJECT');
141
142 console.log(hex);
143
144 //var result = put(this.host,this.port, hex,name);
145
146
147 //if(LOG>3)console.log('received interest'); //from host'+ host +':'+port+' with name '+name);
148
149 //if(LOG>3)console.log('DATA ');
150
151 //if(LOG>3)console.log(result);
152
153 //interest = decodeHexInterest(result);
154
155 //console.log('SUCCESSFULLY PARSED INTEREST');
156
157 console.log('CREATING ANSWER');
158 var si = new SignedInfo();
159 si.setFields();
160
161 var answer = DataUtils.toNumbersFromString(content);
162
163 var co = new ContentObject(new Name(name),si,answer,new Signature());
164 co.sign();
165
166
167 var outputHex = encodeToHexContentObject(co);
168
169 //console.log('SENDING ANSWER');
170
171 //return get_java_socket_bridge().putAnswer(outputHex,name);
172
173 var result = put(this.host,this.port, hex,name,outputHex);
174
175
176 return result;
177 }
178 else{
179
180
181 console.log('ERROR URL OR PORT NOT SET');
182
183 return null;
184
185 }
186
187
188}
Jeff Thompson745026e2012-10-13 12:49:20 -0700189/*
190 * @author: ucla-cs
191 * See COPYING for copyright and distribution information.
192 * Implement getAsync and putAsync used by NDN using nsISocketTransportService.
193 * This is used inside Firefox XPCOM modules.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700194 */
195
196// Assume already imported the following:
197// Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
198// Components.utils.import("resource://gre/modules/NetUtil.jsm");
199
200/** Convert outputHex to binary, send to host:port and call hexListener.onReceivedHexData(hexData).
201 */
202function getAsync(host, port, outputHex, hexListener) {
203 var binaryListener = {
204 onReceivedData : function(data) {
205 hexListener.onReceivedHexData(DataUtils.stringToHex(data));
206 }
207 }
208
209 readAllFromSocket(host, port, DataUtils.hexToRawString(outputHex), binaryListener);
210}
211
212/** Send outputData to host:port, read the entire response and call listener.onReceivedData(data).
213 Code derived from http://stackoverflow.com/questions/7816386/why-nsiscriptableinputstream-is-not-working .
214 */
215function readAllFromSocket(host, port, outputData, listener) {
216 var transportService = Components.classes["@mozilla.org/network/socket-transport-service;1"].getService
217 (Components.interfaces.nsISocketTransportService);
218 var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].createInstance
219 (Components.interfaces.nsIInputStreamPump);
220 var transport = transportService.createTransport(null, 0, host, port, null);
221 var outStream = transport.openOutputStream(1, 0, 0);
222 outStream.write(outputData, outputData.length);
223 outStream.flush();
224 var inStream = transport.openInputStream(0, 0, 0);
225 var dataListener = {
226 data: "",
227 calledOnReceivedData: false,
228
229 onStartRequest: function (request, context) {
230 },
231 onStopRequest: function (request, context, status) {
232 inStream.close();
233 outStream.close();
234 if (!this.calledOnReceivedData) {
235 this.calledOnReceivedData = true;
236 listener.onReceivedData(this.data);
237 }
238 },
239 onDataAvailable: function (request, context, _inputStream, offset, count) {
240 try {
241 // Ignore _inputStream and use inStream.
242 // Use readInputStreamToString to handle binary data.
243 this.data += NetUtil.readInputStreamToString(inStream, count);
244
Jeff Thompson744d28e2012-10-09 23:19:04 -0700245 // TODO: Need to parse the input to check if a whole ccnb object has been read, as in
246 // CcnbObjectReader class: https://github.com/NDN-Routing/NDNLP/blob/master/ndnld.h#L256 .
247 // For now as a hack, try to fully decode this.data as a ContentObject.
248 try {
249 decodeHexContentObject(DataUtils.stringToHex(this.data));
250 } catch (ex) {
251 // Assume the exception is because the decoder only got partial data, so read moe.
252 return;
253 }
254 // We were able to parse the ContentObject, so finish.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700255 this.onStopRequest();
256 } catch (ex) {
257 dump("onDataAvailable exception: " + ex + "\n");
258 }
259 }
260 };
261
262 pump.init(inStream, -1, -1, 0, 0, true);
263 pump.asyncRead(dataListener, null);
264}
265
266
267// TODO: This should be moved to the main NDN.js when we agree on how to do non-blocking get.
268// For now, assume this is included after NDN.js and modify it.
269/** Encode message as an Interest, send it to host:port, read the entire response and call
270 listener.onReceivedContentObject(contentObject).
271 */
272NDN.prototype.getAsync = function(message, listener) {
273 if (this.host != null && this.port != null) {
274 var output ='';
275 message = message.trim();
276 if(message==null || message =="" ){
277 dump('INVALID INPUT TO GET\n');
278 return null;
279 }
280
281 int = new Interest(new Name(message));
282 int.InterestLifetime = 4200;
283 var outputHex = encodeToHexInterest(int);
284
285 var hexListener = {
286 onReceivedHexData : function(result) {
287 if (LOG>0) dump('BINARY RESPONSE IS ' + result + '\n');
288
289 if (result == null || result == undefined || result =="" )
290 listener.onReceivedContentObject(null);
291 else {
Jeff Thompson744d28e2012-10-09 23:19:04 -0700292 var co = decodeHexContentObject(result);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700293
294 if(LOG>2) {
295 dump('DECODED CONTENT OBJECT\n');
296 dump(co);
297 dump('\n');
298 }
299
300 listener.onReceivedContentObject(co);
301 }
302 }
303 }
304 return getAsync(this.host, this.port, outputHex, hexListener);
305 }
306 else {
307 dump('ERROR host OR port NOT SET\n');
308 }
309}
310
311
312/*
313 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -0700314 * See COPYING for copyright and distribution information.
315 * This class contains all CCNx tags
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700316 */
317
318
319var CCNProtocolDTags = {
320
321 /**
322 * Note if you add one of these, add it to the reverse string map as well.
323 * Emphasize getting the work done at compile time over trying to make something
324 * flexible and developer error-proof.
325 */
326
327 Any : 13,
328 Name : 14,
329 Component : 15,
330 Certificate : 16,
331 Collection : 17,
332 CompleteName : 18,
333 Content : 19,
334 SignedInfo : 20,
335 ContentDigest : 21,
336 ContentHash : 22,
337 Count : 24,
338 Header : 25,
339 Interest : 26, /* 20090915 */
340 Key : 27,
341 KeyLocator : 28,
342 KeyName : 29,
343 Length : 30,
344 Link : 31,
345 LinkAuthenticator : 32,
346 NameComponentCount : 33, /* DeprecatedInInterest */
347 RootDigest : 36,
348 Signature : 37,
349 Start : 38,
350 Timestamp : 39,
351 Type : 40,
352 Nonce : 41,
353 Scope : 42,
354 Exclude : 43,
355 Bloom : 44,
356 BloomSeed : 45,
357 AnswerOriginKind : 47,
358 InterestLifetime : 48,
359 Witness : 53,
360 SignatureBits : 54,
361 DigestAlgorithm : 55,
362 BlockSize : 56,
363 FreshnessSeconds : 58,
364 FinalBlockID : 59,
365 PublisherPublicKeyDigest : 60,
366 PublisherCertificateDigest : 61,
367 PublisherIssuerKeyDigest : 62,
368 PublisherIssuerCertificateDigest : 63,
369 ContentObject : 64, /* 20090915 */
370 WrappedKey : 65,
371 WrappingKeyIdentifier : 66,
372 WrapAlgorithm : 67,
373 KeyAlgorithm : 68,
374 Label : 69,
375 EncryptedKey : 70,
376 EncryptedNonceKey : 71,
377 WrappingKeyName : 72,
378 Action : 73,
379 FaceID : 74,
380 IPProto : 75,
381 Host : 76,
382 Port : 77,
383 MulticastInterface : 78,
384 ForwardingFlags : 79,
385 FaceInstance : 80,
386 ForwardingEntry : 81,
387 MulticastTTL : 82,
388 MinSuffixComponents : 83,
389 MaxSuffixComponents : 84,
390 ChildSelector : 85,
391 RepositoryInfo : 86,
392 Version : 87,
393 RepositoryVersion : 88,
394 GlobalPrefix : 89,
395 LocalName : 90,
396 Policy : 91,
397 Namespace : 92,
398 GlobalPrefixName : 93,
399 PolicyVersion : 94,
400 KeyValueSet : 95,
401 KeyValuePair : 96,
402 IntegerValue : 97,
403 DecimalValue : 98,
404 StringValue : 99,
405 BinaryValue : 100,
406 NameValue : 101,
407 Entry : 102,
408 ACL : 103,
409 ParameterizedName : 104,
410 Prefix : 105,
411 Suffix : 106,
412 Root : 107,
413 ProfileName : 108,
414 Parameters : 109,
415 InfoString : 110,
416 // 111 unallocated
417 StatusResponse : 112,
418 StatusCode : 113,
419 StatusText : 114,
420
421 // Sync protocol
422 SyncNode : 115,
423 SyncNodeKind : 116,
424 SyncNodeElement : 117,
425 SyncVersion : 118,
426 SyncNodeElements : 119,
427 SyncContentHash : 120,
428 SyncLeafCount : 121,
429 SyncTreeDepth : 122,
430 SyncByteCount : 123,
431 ConfigSlice : 124,
432 ConfigSliceList : 125,
433 ConfigSliceOp : 126,
434
435 // Remember to keep in sync with schema/tagnames.csvsdict
436 CCNProtocolDataUnit : 17702112,
437 CCNPROTOCOL_DATA_UNIT : "CCNProtocolDataUnit"
438};
439
440var CCNProtocolDTagsStrings = [
441 null, null, null, null, null, null, null, null, null, null, null,
442 null, null,
443 "Any", "Name", "Component", "Certificate", "Collection", "CompleteName",
444 "Content", "SignedInfo", "ContentDigest", "ContentHash", null, "Count", "Header",
445 "Interest", "Key", "KeyLocator", "KeyName", "Length", "Link", "LinkAuthenticator",
446 "NameComponentCount", null, null, "RootDigest", "Signature", "Start", "Timestamp", "Type",
447 "Nonce", "Scope", "Exclude", "Bloom", "BloomSeed", null, "AnswerOriginKind",
448 "InterestLifetime", null, null, null, null, "Witness", "SignatureBits", "DigestAlgorithm", "BlockSize",
449 null, "FreshnessSeconds", "FinalBlockID", "PublisherPublicKeyDigest", "PublisherCertificateDigest",
450 "PublisherIssuerKeyDigest", "PublisherIssuerCertificateDigest", "ContentObject",
451 "WrappedKey", "WrappingKeyIdentifier", "WrapAlgorithm", "KeyAlgorithm", "Label",
452 "EncryptedKey", "EncryptedNonceKey", "WrappingKeyName", "Action", "FaceID", "IPProto",
453 "Host", "Port", "MulticastInterface", "ForwardingFlags", "FaceInstance",
454 "ForwardingEntry", "MulticastTTL", "MinSuffixComponents", "MaxSuffixComponents", "ChildSelector",
455 "RepositoryInfo", "Version", "RepositoryVersion", "GlobalPrefix", "LocalName",
456 "Policy", "Namespace", "GlobalPrefixName", "PolicyVersion", "KeyValueSet", "KeyValuePair",
457 "IntegerValue", "DecimalValue", "StringValue", "BinaryValue", "NameValue", "Entry",
458 "ACL", "ParameterizedName", "Prefix", "Suffix", "Root", "ProfileName", "Parameters",
459 "InfoString", null,
460 "StatusResponse", "StatusCode", "StatusText", "SyncNode", "SyncNodeKind", "SyncNodeElement",
461 "SyncVersion", "SyncNodeElements", "SyncContentHash", "SyncLeafCount", "SyncTreeDepth", "SyncByteCount",
462 "ConfigSlice", "ConfigSliceList", "ConfigSliceOp" ];
463
464
465//TESTING
466//console.log(exports.CCNProtocolDTagsStrings[17]);
467
468
469/*
470 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -0700471 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700472 * This class represents CCNTime Objects
473 */
474
475var CCNTime = function CCNTime(
476
477 input) {
478
479
480
481
482 this.NANOS_MAX = 999877929;
483
484 /*if(typeof input =='object'){
485 this.longDate = DataUtils.byteArrayToUnsignedLong(input);
486 this.binaryDate = input;
487 }*/
488 if(typeof input =='number'){
489 this.msec = input;
490 //this.binaryDate = DataUtils.unsignedLongToByteArray(input);
491
492 }
493 else{
494 if(LOG>1) console.log('UNRECOGNIZED TYPE FOR TIME');
495 }
496};
497
498
499CCNTime.prototype.getJavascriptDate = function(){
500 var d = new Date();
501 d.setTime( this.msec );
502 return d
503};
504
505 /**
506 * Create a CCNTime
507 * @param timestamp source timestamp to initialize from, some precision will be lost
508 */
509
510
511 /**
512 * Create a CCNTime from its binary encoding
513 * @param binaryTime12 the binary representation of a CCNTime
514 */
515/*CCNTime.prototype.setDateBinary = function(
516 //byte []
517 binaryTime12) {
518
519
520 if ((null == binaryTime12) || (binaryTime12.length == 0)) {
521 throw new IllegalArgumentException("Invalid binary time!");
522 }
523
524
525 value = 0;
526 for(i = 0; i < binaryTime12.length; i++) {
527 value = value << 8;
528 b = (binaryTime12[i]) & 0xFF;
529 value |= b;
530 }
531
532 //this.date = new Date(value);
533
534};
535
536//byte[]
537CCNTime.prototype.toBinaryTime = function() {
538
539 return this.msec; //unsignedLongToByteArray(this.date.getTime());
540
541}*/
542/*
543unsignedLongToByteArray= function( value) {
544 if( 0 == value )
545 return [0];
546
547 if( 0 <= value && value <= 0x00FF ) {
548 //byte []
549 bb = new Array[1];
550 bb[0] = (value & 0x00FF);
551 return bb;
552 }
553
554
555 //byte []
556 out = null;
557 //int
558 offset = -1;
559 for(var i = 7; i >=0; --i) {
560 //byte
561 b = ((value >> (i * 8)) & 0xFF);
562 if( out == null && b != 0 ) {
563 out = new Array(i+1);//byte[i+1];
564 offset = i;
565 }
566 if( out != null )
567 out[ offset - i ] = b;
568 }
569 return out;
570}*/
571
572
573/*
574 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -0700575 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700576 * This class represents a Name
577 */
578
579
580var Name = function Name(_components){
581
582 if( typeof _components == 'string') {
583
584 if(LOG>3)console.log('Content Name String '+_components);
585 this.components = Name.makeBlob(Name.createNameArray(_components));
586 }
587 else if(typeof _components === 'object' && _components instanceof Array ){
588
589 if(LOG>4)console.log('Content Name Array '+_components);
590 this.components = Name.makeBlob(_components);
591
592 }
593 else if(_components==null){
594 this.components =[];
595 }
596 else{
597
598 if(LOG>1)console.log("NO CONTENT NAME GIVEN");
599
600 }
601};
602
603Name.prototype.getName=function(){
604
605 var output = "";
606
607 for(var i=0;i<this.components.length;i++){
608 output+= "/"+ DataUtils.toString(this.components[i]);
609 }
610
611 return output;
612
613};
614
615Name.makeBlob=function(name){
616
617 var blobArrays = new Array(name.length);
618
619 for(var i=0;i<name.length;i++){
620 if(typeof name[i] == 'string')
621 blobArrays[i]= DataUtils.toNumbersFromString( name[i] );
622 else if(typeof name[i] == 'object')
623 blobArrays[i]= name[i] ;
624 else
625 if(LOG>4)console.log('NAME COMPONENT INVALID');
626 }
627
628 return blobArrays;
629};
630
631Name.createNameArray=function(name){
632
633
634 name = unescape(name);
635
636 var array = name.split('/');
637
638
639 if(name[0]=="/")
640 array=array.slice(1,array.length);
641
642 if(name[name.length-1]=="/")
643 array=array.slice(0,array.length-1);
644
645 return array;
646}
647
648
649Name.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
650 decoder.readStartElement(this.getElementLabel());
651
652
653 this.components = new Array(); //new ArrayList<byte []>();
654
655 while (decoder.peekStartElement(CCNProtocolDTags.Component)) {
656 this.add(decoder.readBinaryElement(CCNProtocolDTags.Component));
657 }
658
659 decoder.readEndElement();
660};
661
662Name.prototype.to_ccnb = function(/*XMLEncoder*/ encoder) {
663
664 if( this.components ==null )
665 throw new Error("CANNOT ENCODE EMPTY CONTENT NAME");
666
667 encoder.writeStartElement(this.getElementLabel());
668 var count = this.components.length;
669 for (var i=0; i < count; i++) {
670 encoder.writeElement(CCNProtocolDTags.Component, this.components[i]);
671 }
672 encoder.writeEndElement();
673};
674
675Name.prototype.getElementLabel = function(){
676 return CCNProtocolDTags.Name;
677};
678
679Name.prototype.add = function(param){
680 return this.components.push(param);
681};
682
683
684/*
685 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -0700686 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700687 * This class represents ContentObject Objects
688 */
689var ContentObject = function ContentObject(_name,_signedInfo,_content,_signature){
690
691
692 if (typeof _name === 'string'){
693 this.name = new Name(_name);
694 }
695 else{
696 //TODO Check the class of _name
697 this.name = _name;
698 }
699 this.signedInfo = _signedInfo;
700 this.content=_content;
701 this.signature = _signature;
702
703
704 this.startSIG = null;
705 this.endSIG = null;
706
707 this.startSignedInfo = null;
708 this.endContent = null;
709
710 this.rawSignatureData = null;
711};
712
713ContentObject.prototype.sign = function(){
714
715 var n1 = this.encodeObject(this.name);
716 var n2 = this.encodeObject(this.signedInfo);
717 var n3 = this.encodeContent();
718
719 var n = n1.concat(n2,n3);
720
721 if(LOG>2)console.log('Signature Data is (binary) '+n);
722
723 if(LOG>2)console.log('Signature Data is (RawString)');
724
725 if(LOG>2)console.log( DataUtils.toString(n) );
726
727 var sig = DataUtils.toString(n);
728
729
730 var rsa = new RSAKey();
731
732 rsa.readPrivateKeyFromPEMString(globalKeyManager.privateKey);
733
734 //var hSig = rsa.signString(sig, "sha256");
735
736 var hSig = rsa.signByteArrayWithSHA256(n);
737
738
739 if(LOG>2)console.log('SIGNATURE SAVED IS');
740
741 if(LOG>2)console.log(hSig);
742
743 if(LOG>2)console.log( DataUtils.toNumbers(hSig.trim()));
744
745 this.signature.signature = DataUtils.toNumbers(hSig.trim());
746
747
748};
749
750ContentObject.prototype.encodeObject = function encodeObject(obj){
751 var enc = new BinaryXMLEncoder();
752
753 obj.to_ccnb(enc);
754
755 var num = enc.getReducedOstream();
756
757 return num;
758
759
760};
761
762ContentObject.prototype.encodeContent = function encodeContent(obj){
763 var enc = new BinaryXMLEncoder();
764
765 enc.writeElement(CCNProtocolDTags.Content, this.content);
766
767 var num = enc.getReducedOstream();
768
769 return num;
770
771
772};
773
774ContentObject.prototype.saveRawData = function(bytes){
775
776 var sigBits = bytes.slice(this.startSIG, this.endSIG );
777
778 this.rawSignatureData = sigBits;
779};
780
781ContentObject.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
782
783 // TODO VALIDATE THAT ALL FIELDS EXCEPT SIGNATURE ARE PRESENT
784
785 decoder.readStartElement(this.getElementLabel());
786
787
788 if( decoder.peekStartElement(CCNProtocolDTags.Signature) ){
789 this.signature = new Signature();
790 this.signature.from_ccnb(decoder);
791 }
792
793 //this.endSIG = decoder.offset;
794
795 this.startSIG = decoder.offset;
796
797 this.name = new Name();
798 this.name.from_ccnb(decoder);
799
800 //this.startSignedInfo = decoder.offset;
801
802
803 if( decoder.peekStartElement(CCNProtocolDTags.SignedInfo) ){
804 this.signedInfo = new SignedInfo();
805 this.signedInfo.from_ccnb(decoder);
806 }
807
808 this.content = decoder.readBinaryElement(CCNProtocolDTags.Content);
809
810
811 //this.endContent = decoder.offset;
812 this.endSIG = decoder.offset;
813
814
815 decoder.readEndElement();
816
817 this.saveRawData(decoder.istream);
818};
819
820ContentObject.prototype.to_ccnb = function(/*XMLEncoder*/ encoder) {
821
822 //TODO verify name, SignedInfo and Signature is present
823
824
825 encoder.writeStartElement(this.getElementLabel());
826
827
828
829
830 if(null!=this.signature) this.signature.to_ccnb(encoder);
831
832
833 this.startSIG = encoder.offset;
834
835
836 if(null!=this.name) this.name.to_ccnb(encoder);
837
838 //this.endSIG = encoder.offset;
839 //this.startSignedInfo = encoder.offset;
840
841
842 if(null!=this.signedInfo) this.signedInfo.to_ccnb(encoder);
843
844 encoder.writeElement(CCNProtocolDTags.Content, this.content);
845
846
847 this.endSIG = encoder.offset;
848
849 //this.endContent = encoder.offset;
850
851
852 encoder.writeEndElement();
853
854 this.saveRawData(encoder.ostream);
855
856};
857
858ContentObject.prototype.getElementLabel= function(){return CCNProtocolDTags.ContentObject;};
859
860/**
861 * Signature
862 */
863var Signature = function Signature(_witness,_signature,_digestAlgorithm) {
864
865 this.Witness = _witness;//byte [] _witness;
866 this.signature = _signature;//byte [] _signature;
867 this.digestAlgorithm = _digestAlgorithm//String _digestAlgorithm;
868};
869
870var generateSignature = function(contentName,content,signedinfo){
871
872 var enc = new BinaryXMLEncoder();
873 contentName.to_ccnb(enc);
874 var hex1 = toHex(enc.getReducedOstream());
875
876 var enc = new BinaryXMLEncoder();
877 content.to_ccnb(enc);
878 var hex2 = toHex(enc.getReducedOstream());
879
880 var enc = new BinaryXMLEncoder();
881 signedinfo.to_ccnb(enc);
882 var hex3 = toHex(enc.getReducedOstream());
883
884 var hex = hex1+hex2+hex3;
885
886 //globalKeyManager.sig
887
888};
889
890Signature.prototype.from_ccnb =function( decoder) {
891 decoder.readStartElement(this.getElementLabel());
892
893 if(LOG>4)console.log('STARTED DECODING SIGNATURE ');
894
895 if (decoder.peekStartElement(CCNProtocolDTags.DigestAlgorithm)) {
896
897 if(LOG>4)console.log('DIGIEST ALGORITHM FOUND');
898 this.digestAlgorithm = decoder.readUTF8Element(CCNProtocolDTags.DigestAlgorithm);
899 }
900 if (decoder.peekStartElement(CCNProtocolDTags.Witness)) {
901 if(LOG>4)console.log('WITNESS FOUND FOUND');
902 this.Witness = decoder.readBinaryElement(CCNProtocolDTags.Witness);
903 }
904
905 //FORCE TO READ A SIGNATURE
906
907 //if(LOG>4)console.log('SIGNATURE FOUND ');
908 this.signature = decoder.readBinaryElement(CCNProtocolDTags.SignatureBits);
909 if(LOG>4)console.log('READ SIGNATURE ');
910
911 decoder.readEndElement();
912
913};
914
915
916Signature.prototype.to_ccnb= function( encoder){
917
918 if (!this.validate()) {
919 throw new Error("Cannot encode: field values missing.");
920 }
921
922 encoder.writeStartElement(this.getElementLabel());
923
924 if ((null != this.digestAlgorithm) && (!this.digestAlgorithm.equals(CCNDigestHelper.DEFAULT_DIGEST_ALGORITHM))) {
925 encoder.writeElement(CCNProtocolDTags.DigestAlgorithm, OIDLookup.getDigestOID(this.DigestAlgorithm));
926 }
927
928 if (null != this.Witness) {
929 // needs to handle null witness
930 encoder.writeElement(CCNProtocolDTags.Witness, this.Witness);
931 }
932
933 encoder.writeElement(CCNProtocolDTags.SignatureBits, this.signature);
934
935 encoder.writeEndElement();
936};
937
938Signature.prototype.getElementLabel = function() { return CCNProtocolDTags.Signature; };
939
940
941Signature.prototype.validate = function() {
942 return null != this.signature;
943};
944
945
946/**
947 * SignedInfo
948 */
949var ContentType = {DATA:0, ENCR:1, GONE:2, KEY:3, LINK:4, NACK:5};
950var ContentTypeValue = {0:0x0C04C0, 1:0x10D091,2:0x18E344,3:0x28463F,4:0x2C834A,5:0x34008A};
951var ContentTypeValueReverse = {0x0C04C0:0, 0x10D091:1,0x18E344:2,0x28463F:3,0x2C834A:4,0x34008A:5};
952
953var SignedInfo = function SignedInfo(_publisher,_timestamp,_type,_locator,_freshnessSeconds,_finalBlockID){
954
955 //TODO, Check types
956
957 this.publisher = _publisher; //publisherPublicKeyDigest
958 this.timestamp=_timestamp; // CCN Time
959 this.type=_type; // ContentType
960 this.locator =_locator;//KeyLocator
961 this.freshnessSeconds =_freshnessSeconds; // Integer
962 this.finalBlockID=_finalBlockID; //byte array
963
964};
965
966SignedInfo.prototype.setFields = function(){
967 //BASE64 -> RAW STRING
968
969 //this.locator = new KeyLocator( DataUtils.toNumbersFromString(stringCertificate) ,KeyLocatorType.CERTIFICATE );
970
971 var publicKeyHex = globalKeyManager.publicKey;
972
973 console.log('PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ');
974 console.log(publicKeyHex);
975
976 var publicKeyBytes = DataUtils.toNumbers(globalKeyManager.publicKey) ;
977
978
979
980 //var stringCertificate = DataUtils.base64toString(globalKeyManager.certificate);
981
982 //if(LOG>3)console.log('string Certificate is '+stringCertificate);
983
984 //HEX -> BYTE ARRAY
985 //var publisherkey = DataUtils.toNumbers(hex_sha256(stringCertificate));
986
987 //if(LOG>3)console.log('publisher key is ');
988 //if(LOG>3)console.log(publisherkey);
989
990 var publisherKeyDigest = hex_sha256_from_bytes(publicKeyBytes);
991
992 this.publisher = new PublisherPublicKeyDigest( DataUtils.toNumbers( publisherKeyDigest ) );
993
994 //this.publisher = new PublisherPublicKeyDigest(publisherkey);
995
996 var d = new Date();
997
998 var time = d.getTime();
999
1000
1001 this.timestamp = new CCNTime( time );
1002
1003 if(LOG>4)console.log('TIME msec is');
1004
1005 if(LOG>4)console.log(this.timestamp.msec);
1006
1007 //DATA
1008 this.type = 0;//0x0C04C0;//ContentTypeValue[ContentType.DATA];
1009
1010 //if(LOG>4)console.log('toNumbersFromString(stringCertificate) '+DataUtils.toNumbersFromString(stringCertificate));
1011
1012 console.log('PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ');
1013 console.log(publicKeyBytes);
1014
1015 this.locator = new KeyLocator( publicKeyBytes ,KeyLocatorType.KEY );
1016
1017 //this.locator = new KeyLocator( DataUtils.toNumbersFromString(stringCertificate) ,KeyLocatorType.CERTIFICATE );
1018
1019};
1020
1021SignedInfo.prototype.from_ccnb = function( decoder){
1022
1023 decoder.readStartElement( this.getElementLabel() );
1024
1025 if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
1026 if(LOG>3) console.log('DECODING PUBLISHER KEY');
1027 this.publisher = new PublisherPublicKeyDigest();
1028 this.publisher.from_ccnb(decoder);
1029 }
1030
1031 if (decoder.peekStartElement(CCNProtocolDTags.Timestamp)) {
1032 this.timestamp = decoder.readDateTime(CCNProtocolDTags.Timestamp);
1033 if(LOG>4)console.log('TIMESTAMP FOUND IS '+this.timestamp);
1034
1035 }
1036
1037 if (decoder.peekStartElement(CCNProtocolDTags.Type)) {
1038 binType = decoder.readBinaryElement(CCNProtocolDTags.Type);//byte []
1039
1040
1041 //TODO Implement type of Key Reading
1042
1043 if(LOG>4)console.log('Binary Type of of Signed Info is '+binType);
1044
1045 this.type = binType;
1046
1047
1048 //TODO Implement type of Key Reading
1049
1050
1051 if (null == this.type) {
1052 throw new Error("Cannot parse signedInfo type: bytes.");
1053 }
1054
1055 } else {
1056 this.type = ContentType.DATA; // default
1057 }
1058
1059 if (decoder.peekStartElement(CCNProtocolDTags.FreshnessSeconds)) {
1060 this.freshnessSeconds = decoder.readIntegerElement(CCNProtocolDTags.FreshnessSeconds);
1061 if(LOG>4) console.log('FRESHNESS IN SECONDS IS '+ this.freshnessSeconds);
1062 }
1063
1064 if (decoder.peekStartElement(CCNProtocolDTags.FinalBlockID)) {
1065 this.finalBlockID = decoder.readBinaryElement(CCNProtocolDTags.FinalBlockID);
1066 }
1067
1068 if (decoder.peekStartElement(CCNProtocolDTags.KeyLocator)) {
1069 this.locator = new KeyLocator();
1070 this.locator.from_ccnb(decoder);
1071 }
1072
1073 decoder.readEndElement();
1074};
1075
1076SignedInfo.prototype.to_ccnb = function( encoder) {
1077 if (!this.validate()) {
1078 throw new Error("Cannot encode : field values missing.");
1079 }
1080 encoder.writeStartElement(this.getElementLabel());
1081
1082 if (null!=this.publisher) {
1083 if(LOG>3) console.log('ENCODING PUBLISHER KEY' + this.publisher.publisherPublicKeyDigest);
1084
1085 this.publisher.to_ccnb(encoder);
1086 }
1087
1088 if (null!=this.timestamp) {
1089 encoder.writeDateTime(CCNProtocolDTags.Timestamp, this.timestamp );
1090 }
1091
1092 if (null!=this.type && this.type !=0) {
1093
1094 encoder.writeElement(CCNProtocolDTags.type, this.type);
1095 }
1096
1097 if (null!=this.freshnessSeconds) {
1098 encoder.writeElement(CCNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
1099 }
1100
1101 if (null!=this.finalBlockID) {
1102 encoder.writeElement(CCNProtocolDTags.FinalBlockID, this.finalBlockID);
1103 }
1104
1105 if (null!=this.locator) {
1106 this.locator.to_ccnb(encoder);
1107 }
1108
1109 encoder.writeEndElement();
1110};
1111
1112SignedInfo.prototype.valueToType = function(){
1113 //for (Entry<byte [], ContentType> entry : ContentValueTypes.entrySet()) {
1114 //if (Arrays.equals(value, entry.getKey()))
1115 //return entry.getValue();
1116 //}
1117 return null;
1118
1119};
1120
1121SignedInfo.prototype.getElementLabel = function() {
1122 return CCNProtocolDTags.SignedInfo;
1123};
1124
1125SignedInfo.prototype.validate = function() {
1126 // We don't do partial matches any more, even though encoder/decoder
1127 // is still pretty generous.
1128 if (null ==this.publisher || null==this.timestamp ||null== this.locator)
1129 return false;
1130 return true;
1131};
1132
1133/*
1134 * Date Format 1.2.3
1135 * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
1136 * MIT license
1137 *
1138 * Includes enhancements by Scott Trenda <scott.trenda.net>
1139 * and Kris Kowal <cixar.com/~kris.kowal/>
1140 *
1141 * Accepts a date, a mask, or a date and a mask.
1142 * Returns a formatted version of the given date.
1143 * The date defaults to the current date/time.
1144 * The mask defaults to dateFormat.masks.default.
1145 */
1146
1147var DateFormat = function () {
1148 var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
1149 timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
1150 timezoneClip = /[^-+\dA-Z]/g,
1151 pad = function (val, len) {
1152 val = String(val);
1153 len = len || 2;
1154 while (val.length < len) val = "0" + val;
1155 return val;
1156 };
1157
1158 // Regexes and supporting functions are cached through closure
1159 return function (date, mask, utc) {
1160 var dF = dateFormat;
1161
1162 // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
1163 if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
1164 mask = date;
1165 date = undefined;
1166 }
1167
1168 // Passing date through Date applies Date.parse, if necessary
1169 date = date ? new Date(date) : new Date;
1170 if (isNaN(date)) throw SyntaxError("invalid date");
1171
1172 mask = String(dF.masks[mask] || mask || dF.masks["default"]);
1173
1174 // Allow setting the utc argument via the mask
1175 if (mask.slice(0, 4) == "UTC:") {
1176 mask = mask.slice(4);
1177 utc = true;
1178 }
1179
1180 var _ = utc ? "getUTC" : "get",
1181 d = date[_ + "Date"](),
1182 D = date[_ + "Day"](),
1183 m = date[_ + "Month"](),
1184 y = date[_ + "FullYear"](),
1185 H = date[_ + "Hours"](),
1186 M = date[_ + "Minutes"](),
1187 s = date[_ + "Seconds"](),
1188 L = date[_ + "Milliseconds"](),
1189 o = utc ? 0 : date.getTimezoneOffset(),
1190 flags = {
1191 d: d,
1192 dd: pad(d),
1193 ddd: dF.i18n.dayNames[D],
1194 dddd: dF.i18n.dayNames[D + 7],
1195 m: m + 1,
1196 mm: pad(m + 1),
1197 mmm: dF.i18n.monthNames[m],
1198 mmmm: dF.i18n.monthNames[m + 12],
1199 yy: String(y).slice(2),
1200 yyyy: y,
1201 h: H % 12 || 12,
1202 hh: pad(H % 12 || 12),
1203 H: H,
1204 HH: pad(H),
1205 M: M,
1206 MM: pad(M),
1207 s: s,
1208 ss: pad(s),
1209 l: pad(L, 3),
1210 L: pad(L > 99 ? Math.round(L / 10) : L),
1211 t: H < 12 ? "a" : "p",
1212 tt: H < 12 ? "am" : "pm",
1213 T: H < 12 ? "A" : "P",
1214 TT: H < 12 ? "AM" : "PM",
1215 Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
1216 o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
1217 S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
1218 };
1219
1220 return mask.replace(token, function ($0) {
1221 return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
1222 });
1223 };
1224}();
1225
1226// Some common format strings
1227DateFormat.masks = {
1228 "default": "ddd mmm dd yyyy HH:MM:ss",
1229 shortDate: "m/d/yy",
1230 mediumDate: "mmm d, yyyy",
1231 longDate: "mmmm d, yyyy",
1232 fullDate: "dddd, mmmm d, yyyy",
1233 shortTime: "h:MM TT",
1234 mediumTime: "h:MM:ss TT",
1235 longTime: "h:MM:ss TT Z",
1236 isoDate: "yyyy-mm-dd",
1237 isoTime: "HH:MM:ss",
1238 isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
1239 isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
1240};
1241
1242// Internationalization strings
1243DateFormat.i18n = {
1244 dayNames: [
1245 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
1246 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
1247 ],
1248 monthNames: [
1249 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
1250 "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
1251 ]
1252};
1253
1254// For convenience...
1255Date.prototype.format = function (mask, utc) {
1256 return dateFormat(this, mask, utc);
1257};
1258
1259 /*
1260 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07001261 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07001262 * This class represents Interest Objects
1263 */
1264
1265var Interest = function Interest(_name,_faceInstance,_minSuffixComponents,_maxSuffixComponents,_publisherPublicKeyDigest, _exclude, _childSelector,_answerOriginKind,_scope,_interestLifetime,_nonce){
1266
1267 this.name = _name;
1268 this.faceInstance = _faceInstance;
1269 this.maxSuffixComponents = _maxSuffixComponents;
1270 this.minSuffixComponents = _minSuffixComponents;
1271
1272 this.publisherPublicKeyDigest = _publisherPublicKeyDigest;
1273 this.exclude = _exclude;
1274 this.childSelector = _childSelector;
1275 this.answerOriginKind = _answerOriginKind;
1276 this.scope = _scope;
1277 this.interestLifetime = null; // For now we don't have the ability to set an interest lifetime
1278 this.nonce = _nonce;
1279
1280
1281 this.RECURSIVE_POSTFIX = "*";
1282
1283 this.CHILD_SELECTOR_LEFT = 0;
1284 this.CHILD_SELECTOR_RIGHT = 1;
1285 this.ANSWER_CONTENT_STORE = 1;
1286 this.ANSWER_GENERATED = 2;
1287 this.ANSWER_STALE = 4; // Stale answer OK
1288 this.MARK_STALE = 16; // Must have scope 0. Michael calls this a "hack"
1289
1290 this.DEFAULT_ANSWER_ORIGIN_KIND = this.ANSWER_CONTENT_STORE | this.ANSWER_GENERATED;
1291
1292};
1293
1294Interest.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
1295
1296 decoder.readStartElement(CCNProtocolDTags.Interest);
1297
1298 this.name = new Name();
1299 this.name.from_ccnb(decoder);
1300
1301 if (decoder.peekStartElement(CCNProtocolDTags.MinSuffixComponents)) {
1302 this.minSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MinSuffixComponents);
1303 }
1304
1305 if (decoder.peekStartElement(CCNProtocolDTags.MaxSuffixComponents)) {
1306 this.maxSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MaxSuffixComponents);
1307 }
1308
1309 if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
1310 this.publisherPublicKeyDigest = new publisherPublicKeyDigest();
1311 this.publisherPublicKeyDigest.from_ccnb(decoder);
1312 }
1313
1314 if (decoder.peekStartElement(CCNProtocolDTags.Exclude)) {
1315 this.exclude = new Exclude();
1316 this.exclude.from_ccnb(decoder);
1317 }
1318
1319 if (decoder.peekStartElement(CCNProtocolDTags.ChildSelector)) {
1320 this.childSelector = decoder.readIntegerElement(CCNProtocolDTags.ChildSelector);
1321 }
1322
1323 if (decoder.peekStartElement(CCNProtocolDTags.AnswerOriginKind)) {
1324 // call setter to handle defaulting
1325 this.answerOriginKind = decoder.readIntegerElement(CCNProtocolDTags.AnswerOriginKind);
1326 }
1327
1328 if (decoder.peekStartElement(CCNProtocolDTags.Scope)) {
1329 this.scope = decoder.readIntegerElement(CCNProtocolDTags.Scope);
1330 }
1331
1332 if (decoder.peekStartElement(CCNProtocolDTags.InterestLifetime)) {
1333 this.interestLifetime = decoder.readBinaryElement(CCNProtocolDTags.InterestLifetime);
1334 }
1335
1336 if (decoder.peekStartElement(CCNProtocolDTags.Nonce)) {
1337 this.nonce = decoder.readBinaryElement(CCNProtocolDTags.Nonce);
1338 }
1339
1340 decoder.readEndElement();
1341};
1342
1343Interest.prototype.to_ccnb = function(/*XMLEncoder*/ encoder){
1344 //Could check if name is present
1345
1346 encoder.writeStartElement(CCNProtocolDTags.Interest);
1347
1348 this.name.to_ccnb(encoder);
1349
1350 if (null != this.minSuffixComponents)
1351 encoder.writeElement(CCNProtocolDTags.MinSuffixComponents, this.minSuffixComponents);
1352
1353 if (null != this.maxSuffixComponents)
1354 encoder.writeElement(CCNProtocolDTags.MaxSuffixComponents, this.maxSuffixComponents);
1355
1356 if (null != this.publisherPublicKeyDigest)
1357 this.publisherPublicKeyDigest.to_ccnb(encoder);
1358
1359 if (null != this.exclude)
1360 this.exclude.to_ccnb(encoder);
1361
1362 if (null != this.childSelector)
1363 encoder.writeElement(CCNProtocolDTags.ChildSelector, this.childSelector);
1364
1365 //TODO Encode OriginKind
1366 if (this.DEFAULT_ANSWER_ORIGIN_KIND != this.answerOriginKind && this.answerOriginKind!=null)
1367 encoder.writeElement(CCNProtocolDTags.AnswerOriginKind, this.answerOriginKind);
1368
1369 if (null != this.scope)
1370 encoder.writeElement(CCNProtocolDTags.Scope, this.scope);
1371
1372 if (null != this.nonce)
1373 encoder.writeElement(CCNProtocolDTags.Nonce, this.nonce);
1374
1375 encoder.writeEndElement();
1376
1377};
1378
1379Interest.prototype.matches_name = function(/*Name*/ name){
1380 var i_name = this.name.components;
1381 var o_name = name.components;
1382
1383 // The intrest name is longer than the name we are checking it against.
1384 if (i_name.length > o_name.length)
1385 return false;
1386
1387 // Check if at least one of given components doesn't match.
1388 for (var i = 0; i < i_name.length; ++i) {
1389 if (!DataUtils.arraysEqual(i_name[i], o_name[i]))
1390 return false;
1391 }
1392
1393 return true;
1394}
1395
1396/**
1397 * Exclude
1398 */
1399var Exclude = function Exclude(_values){
1400
1401 this.OPTIMUM_FILTER_SIZE = 100;
1402
1403
1404 this.values = _values; //array of elements
1405
1406}
1407
1408Exclude.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
1409
1410
1411
1412 decoder.readStartElement(this.getElementLabel());
1413
1414 //TODO APPLY FILTERS/EXCLUDE
1415
1416 //TODO
1417 /*var component;
1418 var any = false;
1419 while ((component = decoder.peekStartElement(CCNProtocolDTags.Component)) ||
1420 (any = decoder.peekStartElement(CCNProtocolDTags.Any)) ||
1421 decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
1422 var ee = component?new ExcludeComponent(): any ? new ExcludeAny() : new BloomFilter();
1423 ee.decode(decoder);
1424 _values.add(ee);
1425 }*/
1426
1427 decoder.readEndElement();
1428
1429};
1430
1431Exclude.prototype.to_ccnb=function(/*XMLEncoder*/ encoder) {
1432 if (!validate()) {
1433 throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
1434 }
1435
1436 if (empty())
1437 return;
1438
1439 encoder.writeStartElement(getElementLabel());
1440
1441 encoder.writeEndElement();
1442
1443 };
1444
1445Exclude.prototype.getElementLabel = function() { return CCNProtocolDTags.Exclude; };
1446
1447
1448/**
1449 * ExcludeAny
1450 */
1451var ExcludeAny = function ExcludeAny() {
1452
1453};
1454
1455ExcludeAny.prototype.from_ccnb = function(decoder) {
1456 decoder.readStartElement(this.getElementLabel());
1457 decoder.readEndElement();
1458};
1459
1460
1461ExcludeAny.prototype.to_ccnb = function( encoder) {
1462 encoder.writeStartElement(this.getElementLabel());
1463 encoder.writeEndElement();
1464};
1465
1466ExcludeAny.prototype.getElementLabel=function() { return CCNProtocolDTags.Any; };
1467
1468
1469/**
1470 * ExcludeComponent
1471 */
1472var ExcludeComponent = function ExcludeComponent(_body) {
1473
1474 //TODO Check BODY is an Array of componenets.
1475
1476 this.body = _body
1477};
1478
1479ExcludeComponent.prototype.from_ccnb = function( decoder) {
1480 this.body = decoder.readBinaryElement(this.getElementLabel());
1481};
1482
1483ExcludeComponent.prototype.to_ccnb = function(encoder) {
1484 encoder.writeElement(this.getElementLabel(), this.body);
1485};
1486
1487ExcludeComponent.prototype.getElementLabel = function() { return CCNProtocolDTags.Component; };
1488
1489/*
1490 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07001491 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07001492 * This class represents Key Objects
1493 */
1494
1495var Key = function Key(){
1496 /* TODO: Port from PyCCN:
1497 generateRSA()
1498 privateToDER()
1499 publicToDER()
1500 privateToPEM()
1501 publicToPEM()
1502 fromDER()
1503 fromPEM()
1504 */
1505}
1506
1507/**
1508 * KeyLocator
1509 */
1510var KeyLocatorType = {
1511 NAME:1,
1512 KEY:2,
1513 CERTIFICATE:3
1514};
1515
1516var KeyLocator = function KeyLocator(_input,_type){
1517
1518 this.type=_type;
1519
1520 if (_type==KeyLocatorType.NAME){
1521 this.keyName = _input;
1522 }
1523 else if(_type==KeyLocatorType.KEY){
1524 console.log('SET KEY');
1525 this.publicKey = _input;
1526 }
1527 else if(_type==KeyLocatorType.CERTIFICATE){
1528 this.certificate = _input;
1529 }
1530
1531};
1532
1533KeyLocator.prototype.from_ccnb = function(decoder) {
1534
1535 decoder.readStartElement(this.getElementLabel());
1536
1537 if (decoder.peekStartElement(CCNProtocolDTags.Key)) {
1538 try {
1539 encodedKey = decoder.readBinaryElement(CCNProtocolDTags.Key);
1540 // This is a DER-encoded SubjectPublicKeyInfo.
1541
1542 //TODO FIX THIS, This should create a Key Object instead of keeping bytes
1543
1544 this.publicKey = encodedKey;//CryptoUtil.getPublicKey(encodedKey);
1545 this.type = 2;
1546
1547
1548 if(LOG>4) console.log('PUBLIC KEY FOUND: '+ this.publicKey);
1549 //this.publicKey = encodedKey;
1550
1551
1552 } catch (e) {
1553 throw new Error("Cannot parse key: ", e);
1554 }
1555
1556 if (null == this.publicKey) {
1557 throw new Error("Cannot parse key: ");
1558 }
1559
1560 } else if ( decoder.peekStartElement(CCNProtocolDTags.Certificate)) {
1561 try {
1562 encodedCert = decoder.readBinaryElement(CCNProtocolDTags.Certificate);
1563
1564 /*
1565 * Certificates not yet working
1566 */
1567
1568 //CertificateFactory factory = CertificateFactory.getInstance("X.509");
1569 //this.certificate = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(encodedCert));
1570
1571
1572 this.certificate = encodedCert;
1573 this.type = 3;
1574
1575 if(LOG>4) console.log('CERTIFICATE FOUND: '+ this.certificate);
1576
1577 } catch ( e) {
1578 throw new Error("Cannot decode certificate: " + e);
1579 }
1580 if (null == this.certificate) {
1581 throw new Error("Cannot parse certificate! ");
1582 }
1583 } else {
1584 this.type = 1;
1585
1586
1587 this.keyName = new KeyName();
1588 this.keyName.from_ccnb(decoder);
1589 }
1590 decoder.readEndElement();
1591 }
1592
1593
1594 KeyLocator.prototype.to_ccnb = function( encoder) {
1595
1596 if(LOG>2) console.log('type is is ' + this.type);
1597 //TODO Check if Name is missing
1598 if (!this.validate()) {
1599 throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
1600 }
1601
1602
1603 //TODO FIX THIS TOO
1604 encoder.writeStartElement(this.getElementLabel());
1605
1606 if (this.type == KeyLocatorType.KEY) {
1607 if(LOG>5)console.log('About to encode a public key' +this.publicKey);
1608 encoder.writeElement(CCNProtocolDTags.Key, this.publicKey);
1609
1610 } else if (this.type == KeyLocatorType.CERTIFICATE) {
1611
1612 try {
1613 encoder.writeElement(CCNProtocolDTags.Certificate, this.certificate);
1614 } catch ( e) {
1615 throw new Error("CertificateEncodingException attempting to write key locator: " + e);
1616 }
1617
1618 } else if (this.type == KeyLocatorType.NAME) {
1619
1620 this.keyName.to_ccnb(encoder);
1621 }
1622 encoder.writeEndElement();
1623
1624};
1625
1626KeyLocator.prototype.getElementLabel = function() {
1627 return CCNProtocolDTags.KeyLocator;
1628};
1629
1630KeyLocator.prototype.validate = function() {
1631 return ( (null != this.keyName) || (null != this.publicKey) || (null != this.certificate) );
1632};
1633
1634/**
1635 * KeyName is only used by KeyLocator.
1636 */
1637var KeyName = function KeyName() {
1638
1639
1640 this.contentName = this.contentName;//contentName
1641 this.publisherID =this.publisherID;//publisherID
1642
1643};
1644
1645KeyName.prototype.from_ccnb=function( decoder){
1646
1647
1648 decoder.readStartElement(this.getElementLabel());
1649
1650 this.contentName = new Name();
1651 this.contentName.from_ccnb(decoder);
1652
1653 if(LOG>4) console.log('KEY NAME FOUND: ');
1654
1655 if ( PublisherID.peek(decoder) ) {
1656 this.publisherID = new PublisherID();
1657 this.publisherID.from_ccnb(decoder);
1658 }
1659
1660 decoder.readEndElement();
1661};
1662
1663KeyName.prototype.to_ccnb = function( encoder) {
1664 if (!this.validate()) {
1665 throw new Error("Cannot encode : field values missing.");
1666 }
1667
1668 encoder.writeStartElement(this.getElementLabel());
1669
1670 this.contentName.to_ccnb(encoder);
1671 if (null != this.publisherID)
1672 this.publisherID.to_ccnb(encoder);
1673
1674 encoder.writeEndElement();
1675};
1676
1677KeyName.prototype.getElementLabel = function() { return CCNProtocolDTags.KeyName; };
1678
1679KeyName.prototype.validate = function() {
1680 // DKS -- do we do recursive validation?
1681 // null signedInfo ok
1682 return (null != this.contentName);
1683};
1684
1685/*
1686 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07001687 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07001688 * This class represents Publisher and PublisherType Objects
1689 */
1690
1691
1692var PublisherType = function PublisherType(_tag){
1693 this.KEY =(CCNProtocolDTags.PublisherPublicKeyDigest);
1694 this.CERTIFICATE= (CCNProtocolDTags.PublisherCertificateDigest);
1695 this.ISSUER_KEY= (CCNProtocolDTags.PublisherIssuerKeyDigest);
1696 this.ISSUER_CERTIFICATE =(CCNProtocolDTags.PublisherIssuerCertificateDigest);
1697
1698 this.Tag = _tag;
1699};
1700
1701var isTypeTagVal = function(tagVal) {
1702 if ((tagVal == CCNProtocolDTags.PublisherPublicKeyDigest) ||
1703 (tagVal == CCNProtocolDTags.PublisherCertificateDigest) ||
1704 (tagVal == CCNProtocolDTags.PublisherIssuerKeyDigest) ||
1705 (tagVal == CCNProtocolDTags.PublisherIssuerCertificateDigest)) {
1706 return true;
1707 }
1708 return false;
1709};
1710
1711
1712
1713
1714var PublisherID = function PublisherID() {
1715
1716 this.PUBLISHER_ID_DIGEST_ALGORITHM = "SHA-256";
1717 this.PUBLISHER_ID_LEN = 256/8;
1718
1719 //TODO, implement publisherID creation and key creation
1720
1721 //TODO implement generatePublicKeyDigest
1722 this.publisherID =null;//= generatePublicKeyDigest(key);//ByteArray
1723
1724 //TODO implement generate key
1725 //CryptoUtil.generateKeyID(PUBLISHER_ID_DIGEST_ALGORITHM, key);
1726 this.publisherType = null;//isIssuer ? PublisherType.ISSUER_KEY : PublisherType.KEY;//publisher Type
1727
1728};
1729
1730
1731PublisherID.prototype.from_ccnb = function(decoder) {
1732
1733 // We have a choice here of one of 4 binary element types.
1734 var nextTag = decoder.peekStartElementAsLong();
1735
1736 if (null == nextTag) {
1737 throw new Error("Cannot parse publisher ID.");
1738 }
1739
1740 this.publisherType = new PublisherType(nextTag);
1741
1742 if (!isTypeTagVal(nextTag)) {
1743 throw new Error("Invalid publisher ID, got unexpected type: " + nextTag);
1744 }
1745 this.publisherID = decoder.readBinaryElement(nextTag);
1746 if (null == this.publisherID) {
Jeff Thompson744d28e2012-10-09 23:19:04 -07001747 throw new ContentDecodingException("Cannot parse publisher ID of type : " + nextTag + ".");
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07001748 }
1749};
1750
1751PublisherID.prototype.to_ccnb = function(encoder) {
1752 if (!this.validate()) {
1753 throw new Error("Cannot encode " + this.getClass().getName() + ": field values missing.");
1754 }
1755
1756 encoder.writeElement(this.getElementLabel(), this.publisherID);
1757};
1758
1759PublisherID.peek = function(/* XMLDecoder */ decoder) {
1760
1761 //Long
1762 nextTag = decoder.peekStartElementAsLong();
1763
1764 if (null == nextTag) {
1765 // on end element
1766 return false;
1767 }
1768 return (isTypeTagVal(nextTag));
1769 };
1770
1771PublisherID.prototype.getElementLabel = function() {
1772 return this.publisherType.Tag;
1773};
1774
1775PublisherID.prototype.validate = function(){
1776 return ((null != id() && (null != type())));
1777};
1778
1779
1780
1781
1782/*
1783 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07001784 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07001785 * This class represents PublisherPublicKeyDigest Objects
1786 */
1787var PublisherPublicKeyDigest = function PublisherPublicKeyDigest(_pkd){
1788
1789 //this.PUBLISHER_ID_LEN = 256/8;
1790 this.PUBLISHER_ID_LEN = 512/8;
1791
1792
1793 this.publisherPublicKeyDigest = _pkd;
1794 //if( typeof _pkd == "object") this.publisherPublicKeyDigest = _pkd; // Byte Array
1795 //else if( typeof _pkd == "PublicKey") ;//TODO...
1796
1797};
1798
1799PublisherPublicKeyDigest.prototype.from_ccnb = function( decoder) {
1800
1801 this.publisherPublicKeyDigest = decoder.readBinaryElement(this.getElementLabel());
1802
1803 if(LOG>4)console.log('Publisher public key digest is ' + this.publisherPublicKeyDigest);
1804
1805 if (null == this.publisherPublicKeyDigest) {
1806 throw new Error("Cannot parse publisher key digest.");
1807 }
1808
1809 //TODO check if the length of the PublisherPublicKeyDigest is correct ( Security reason)
1810
1811 if (this.publisherPublicKeyDigest.length != this.PUBLISHER_ID_LEN) {
1812
1813 console.log('LENGTH OF PUBLISHER ID IS WRONG! Expected ' + this.PUBLISHER_ID_LEN + ", got " + this.publisherPublicKeyDigest.length);
1814
1815 //this.publisherPublicKeyDigest = new PublisherPublicKeyDigest(this.PublisherPublicKeyDigest).PublisherKeyDigest;
1816
1817 }
1818 };
1819
1820PublisherPublicKeyDigest.prototype.to_ccnb= function( encoder) {
1821 //TODO Check that the ByteArray for the key is present
1822 if (!this.validate()) {
1823 throw new Error("Cannot encode : field values missing.");
1824 }
1825 if(LOG>3) console.log('PUBLISHER KEY DIGEST IS'+this.publisherPublicKeyDigest);
1826 encoder.writeElement(this.getElementLabel(), this.publisherPublicKeyDigest);
1827};
1828
1829PublisherPublicKeyDigest.prototype.getElementLabel = function() { return CCNProtocolDTags.PublisherPublicKeyDigest; };
1830
1831PublisherPublicKeyDigest.prototype.validate =function() {
1832 return (null != this.publisherPublicKeyDigest);
1833};
1834
1835/*
1836 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07001837 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07001838 * This class represents Face Instances
1839 */
1840
1841var NetworkProtocol = { TCP:6, UDP:17};
1842
1843var FaceInstance = function FaceInstance(
1844 _action,
1845 _publisherPublicKeyDigest,
1846 _faceID,
1847 _ipProto,
1848 _host,
1849 _port,
1850 _multicastInterface,
1851 _multicastTTL,
1852 _freshnessSeconds){
1853
1854
1855 this.action = _action;
1856 this.publisherPublicKeyDigest = _publisherPublicKeyDigest;
1857 this.faceID = _faceID;
1858 this.ipProto = _ipProto;
1859 this.host = _host;
1860 this.Port = _port;
1861 this.multicastInterface =_multicastInterface;
1862 this.multicastTTL =_multicastTTL;
1863 this.freshnessSeconds = _freshnessSeconds;
1864
1865 //action ::= ("newface" | "destroyface" | "queryface")
1866 //publisherPublicKeyDigest ::= SHA-256 digest
1867 //faceID ::= nonNegativeInteger
1868 //ipProto ::= nonNegativeInteger [IANA protocol number, 6=TCP, 17=UDP]
1869 //Host ::= textual representation of numeric IPv4 or IPv6 address
1870 //Port ::= nonNegativeInteger [1..65535]
1871 //MulticastInterface ::= textual representation of numeric IPv4 or IPv6 address
1872 //MulticastTTL ::= nonNegativeInteger [1..255]
1873 //freshnessSeconds ::= nonNegativeInteger
1874
1875};
1876
1877/**
1878 * Used by NetworkObject to decode the object from a network stream.
1879 * @see org.ccnx.ccn.impl.encoding.XMLEncodable
1880 */
1881FaceInstance.prototype.from_ccnb = function(//XMLDecoder
1882 decoder) {
1883
1884 decoder.readStartElement(this.getElementLabel());
1885
1886 if (decoder.peekStartElement(CCNProtocolDTags.Action)) {
1887
1888 this.action = decoder.readUTF8Element(CCNProtocolDTags.Action);
1889
1890 }
1891 if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
1892
1893 this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
1894 this.publisherPublicKeyDigest.from_ccnb(decoder);
1895
1896 }
1897 if (decoder.peekStartElement(CCNProtocolDTags.FaceID)) {
1898
1899 this.faceID = decoder.readIntegerElement(CCNProtocolDTags.FaceID);
1900
1901 }
1902 if (decoder.peekStartElement(CCNProtocolDTags.IPProto)) {
1903
1904 //int
1905 var pI = decoder.readIntegerElement(CCNProtocolDTags.IPProto);
1906
1907 this.ipProto = null;
1908
1909 if (NetworkProtocol.TCP == pI) {
1910
1911 this.ipProto = NetworkProtocol.TCP;
1912
1913 } else if (NetworkProtocol.UDP == pI) {
1914
1915 this.ipProto = NetworkProtocol.UDP;
1916
1917 } else {
1918
1919 throw new Error("FaceInstance.decoder. Invalid " +
1920 CCNProtocolDTags.tagToString(CCNProtocolDTags.IPProto) + " field: " + pI);
1921
1922 }
1923 }
1924
1925 if (decoder.peekStartElement(CCNProtocolDTags.Host)) {
1926
1927 this.host = decoder.readUTF8Element(CCNProtocolDTags.Host);
1928
1929 }
1930
1931 if (decoder.peekStartElement(CCNProtocolDTags.Port)) {
1932 this.Port = decoder.readIntegerElement(CCNProtocolDTags.Port);
1933 }
1934
1935 if (decoder.peekStartElement(CCNProtocolDTags.MulticastInterface)) {
1936 this.multicastInterface = decoder.readUTF8Element(CCNProtocolDTags.MulticastInterface);
1937 }
1938
1939 if (decoder.peekStartElement(CCNProtocolDTags.MulticastTTL)) {
1940 this.multicastTTL = decoder.readIntegerElement(CCNProtocolDTags.MulticastTTL);
1941 }
1942
1943 if (decoder.peekStartElement(CCNProtocolDTags.FreshnessSeconds)) {
1944 this.freshnessSeconds = decoder.readIntegerElement(CCNProtocolDTags.FreshnessSeconds);
1945 }
1946 decoder.readEndElement();
1947}
1948
1949/**
1950 * Used by NetworkObject to encode the object to a network stream.
1951 * @see org.ccnx.ccn.impl.encoding.XMLEncodable
1952 */
1953FaceInstance.prototype.to_ccnb = function(//XMLEncoder
1954 encoder){
1955
1956 //if (!this.validate()) {
1957 //throw new Error("Cannot encode : field values missing.");
1958 //throw new Error("")
1959 //}
1960 encoder.writeStartElement(this.getElementLabel());
1961
1962 if (null != this.action && this.action.length != 0)
1963 encoder.writeElement(CCNProtocolDTags.Action, this.action);
1964
1965 if (null != this.publisherPublicKeyDigest) {
1966 this.publisherPublicKeyDigest.to_ccnb(encoder);
1967 }
1968 if (null != this.faceID) {
1969 encoder.writeElement(CCNProtocolDTags.FaceID, this.faceID);
1970 }
1971 if (null != this.ipProto) {
1972 //encoder.writeElement(CCNProtocolDTags.IPProto, this.IpProto.value());
1973 encoder.writeElement(CCNProtocolDTags.IPProto, this.ipProto);
1974 }
1975 if (null != this.host && this.host.length != 0) {
1976 encoder.writeElement(CCNProtocolDTags.Host, this.host);
1977 }
1978 if (null != this.Port) {
1979 encoder.writeElement(CCNProtocolDTags.Port, this.Port);
1980 }
1981 if (null != this.multicastInterface && this.multicastInterface.length != 0) {
1982 encoder.writeElement(CCNProtocolDTags.MulticastInterface, this.multicastInterface);
1983 }
1984 if (null != this.multicastTTL) {
1985 encoder.writeElement(CCNProtocolDTags.MulticastTTL, this.multicastTTL);
1986 }
1987 if (null != this.freshnessSeconds) {
1988 encoder.writeElement(CCNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
1989 }
1990 encoder.writeEndElement();
1991}
1992
1993
1994FaceInstance.prototype.getElementLabel= function(){return CCNProtocolDTags.FaceInstance;};
1995
1996
1997/*
1998 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07001999 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002000 * This class represents Forwarding Entries
2001 */
2002
2003var ForwardingEntry = function ForwardingEntry(
2004 //ActionType
2005 _action,
2006 //Name
2007 _prefixName,
2008 //PublisherPublicKeyDigest
2009 _ccndId,
2010 //Integer
2011 _faceID,
2012 //Integer
2013 _flags,
2014 //Integer
2015 _lifetime){
2016
2017
2018
2019 //String
2020 this.action = _action;
2021 //Name\
2022 this.prefixName = _prefixName;
2023 //PublisherPublicKeyDigest
2024 this.ccndID = _ccndId;
2025 //Integer
2026 this.faceID = _faceID;
2027 //Integer
2028 this.flags = _flags;
2029 //Integer
2030 this.lifetime = _lifetime; // in seconds
2031
2032};
2033
2034ForwardingEntry.prototype.from_ccnb =function(
2035 //XMLDecoder
2036 decoder)
Jeff Thompson744d28e2012-10-09 23:19:04 -07002037 //throws ContentDecodingException
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002038 {
2039 decoder.readStartElement(this.getElementLabel());
2040 if (decoder.peekStartElement(CCNProtocolDTags.Action)) {
2041 this.action = decoder.readUTF8Element(CCNProtocolDTags.Action);
2042 }
2043 if (decoder.peekStartElement(CCNProtocolDTags.Name)) {
2044 this.prefixName = new Name();
2045 this.prefixName.from_ccnb(decoder) ;
2046 }
2047 if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
2048 this.CcndId = new PublisherPublicKeyDigest();
2049 this.CcndId.from_ccnb(decoder);
2050 }
2051 if (decoder.peekStartElement(CCNProtocolDTags.FaceID)) {
2052 this.faceID = decoder.readIntegerElement(CCNProtocolDTags.FaceID);
2053 }
2054 if (decoder.peekStartElement(CCNProtocolDTags.ForwardingFlags)) {
2055 this.flags = decoder.readIntegerElement(CCNProtocolDTags.ForwardingFlags);
2056 }
2057 if (decoder.peekStartElement(CCNProtocolDTags.FreshnessSeconds)) {
2058 this.lifetime = decoder.readIntegerElement(CCNProtocolDTags.FreshnessSeconds);
2059 }
2060 decoder.readEndElement();
2061 };
2062
2063 /**
2064 * Used by NetworkObject to encode the object to a network stream.
2065 * @see org.ccnx.ccn.impl.encoding.XMLEncodable
2066 */
2067ForwardingEntry.prototype.to_ccnb =function(
2068 //XMLEncoder
2069encoder)
2070{
2071
2072
2073 //if (!validate()) {
2074 //throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
2075 //}
2076 encoder.writeStartElement(this.getElementLabel());
2077 if (null != this.action && this.action.length != 0)
2078 encoder.writeElement(CCNProtocolDTags.Action, this.action);
2079 if (null != this.prefixName) {
2080 this.prefixName.to_ccnb(encoder);
2081 }
2082 if (null != this.CcndId) {
2083 this.CcndId.to_ccnb(encoder);
2084 }
2085 if (null != this.faceID) {
2086 encoder.writeElement(CCNProtocolDTags.FaceID, this.faceID);
2087 }
2088 if (null != this.flags) {
2089 encoder.writeElement(CCNProtocolDTags.ForwardingFlags, this.flags);
2090 }
2091 if (null != this.lifetime) {
2092 encoder.writeElement(CCNProtocolDTags.FreshnessSeconds, this.lifetime);
2093 }
2094 encoder.writeEndElement();
2095 };
2096
2097ForwardingEntry.prototype.getElementLabel = function() { return CCNProtocolDTags.ForwardingEntry; }
2098
2099/*
2100 * This class is used to encode and decode binary elements ( blog, type/value pairs)
2101 *
2102 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07002103 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002104 */
2105
2106var XML_EXT = 0x00;
2107
2108var XML_TAG = 0x01;
2109
2110var XML_DTAG = 0x02;
2111
2112var XML_ATTR = 0x03;
2113
2114var XML_DATTR = 0x04;
2115
2116var XML_BLOB = 0x05;
2117
2118var XML_UDATA = 0x06;
2119
2120var XML_CLOSE = 0x0;
2121
2122var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16;
2123
2124
2125var XML_TT_BITS = 3;
2126var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
2127var XML_TT_VAL_BITS = XML_TT_BITS + 1;
2128var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
2129var XML_REG_VAL_BITS = 7;
2130var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
2131var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
2132var BYTE_MASK = 0xFF;
2133var LONG_BYTES = 8;
2134var LONG_BITS = 64;
2135
2136var bits_11 = 0x0000007FF;
2137var bits_18 = 0x00003FFFF;
2138var bits_32 = 0x0FFFFFFFF;
2139
2140
2141var BinaryXMLEncoder = function BinaryXMLEncoder(){
2142
2143 this.ostream = new Array(10000);
2144
2145
2146 this.offset =0;
2147
2148 this.CODEC_NAME = "Binary";
2149
2150};
2151
2152BinaryXMLEncoder.prototype.writeUString = function(/*String*/ utf8Content){
2153 this.encodeUString(this.ostream, utf8Content, XML_UDATA);
2154};
2155
2156BinaryXMLEncoder.prototype.writeBlob = function(/*byte []*/ binaryContent
2157 //, /*int*/ offset, /*int*/ length
2158 ) {
2159
2160 if(LOG >3) console.log(binaryContent);
2161
2162 this.encodeBlob(this.ostream, binaryContent, this.offset, binaryContent.length);
2163};
2164
2165BinaryXMLEncoder.prototype.writeStartElement = function(/*String*/ tag, /*TreeMap<String,String>*/ attributes){
2166
2167 /*Long*/ dictionaryVal = tag;//stringToTag(tag);
2168
2169 if (null == dictionaryVal) {
2170
2171 this.encodeUString(this.ostream, tag, XML_TAG);
2172
2173 } else {
2174 this.encodeTypeAndVal(XML_DTAG, dictionaryVal, this.ostream);
2175 }
2176
2177 if (null != attributes) {
2178 this.writeAttributes(attributes);
2179 }
2180};
2181
2182
2183BinaryXMLEncoder.prototype.writeEndElement = function(){
2184
2185 this.ostream[this.offset] = XML_CLOSE;
2186 this.offset+= 1;
2187}
2188
2189BinaryXMLEncoder.prototype.writeAttributes = function(/*TreeMap<String,String>*/ attributes) {
2190
2191 if (null == attributes) {
2192 return;
2193 }
2194
2195 // the keySet of a TreeMap is sorted.
2196
2197 for(var i=0; i<attributes.length;i++){
2198 var strAttr = attributes[i].k;
2199 var strValue = attributes[i].v;
2200
2201 var dictionaryAttr = stringToTag(strAttr);
2202 if (null == dictionaryAttr) {
2203 // not in dictionary, encode as attr
2204 // compressed format wants length of tag represented as length-1
2205 // to save that extra bit, as tag cannot be 0 length.
2206 // encodeUString knows to do that.
2207 this.encodeUString(this.ostream, strAttr, XML_ATTR);
2208 } else {
2209 this.encodeTypeAndVal(XML_DATTR, dictionaryAttr, this.ostream);
2210 }
2211 // Write value
2212 this.encodeUString(this.ostream, strValue);
2213
2214 }
2215
2216
2217}
2218
2219//returns a string
2220stringToTag = function(/*long*/ tagVal) {
2221 if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
2222 return CCNProtocolDTagsStrings[tagVal];
2223 } else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
2224 return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
2225 }
2226 return null;
2227};
2228
2229//returns a Long
2230tagToString = function(/*String*/ tagName) {
2231 // the slow way, but right now we don't care.... want a static lookup for the forward direction
2232 for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
2233 if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
2234 return i;
2235 }
2236 }
2237 if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
2238 return CCNProtocolDTags.CCNProtocolDataUnit;
2239 }
2240 return null;
2241};
2242
2243
2244BinaryXMLEncoder.prototype.writeElement = function(
2245 //long
2246 tag,
2247 //byte[]
2248 Content,
2249 //TreeMap<String, String>
2250 attributes) {
2251
2252 this.writeStartElement(tag, attributes);
2253 // Will omit if 0-length
2254
2255 if(typeof Content === 'number') {
2256 if(LOG>4) console.log('GOING TO WRITE THE NUMBER .charCodeAt(0) ' +Content.toString().charCodeAt(0) );
2257 if(LOG>4) console.log('GOING TO WRITE THE NUMBER ' +Content.toString() );
2258 if(LOG>4) console.log('type of number is ' +typeof Content.toString() );
2259
2260
2261
2262 this.writeUString(Content.toString());
2263 //whatever
2264
2265 }
2266
2267 else if(typeof Content === 'string'){
2268 if(LOG>4) console.log('GOING TO WRITE THE STRING ' +Content );
2269 if(LOG>4) console.log('type of STRING is ' +typeof Content );
2270
2271 this.writeUString(Content);
2272 }
2273
2274 else{
2275 //else if(typeof Content === 'string'){
2276 //console.log('went here');
2277 //this.writeBlob(Content);
2278 //}
2279 if(LOG>4) console.log('GOING TO WRITE A BLOB ' +Content );
2280 //else if(typeof Content === 'object'){
2281 this.writeBlob(Content);
2282 //}
2283 }
2284
2285 this.writeEndElement();
2286}
2287
2288//TODO
2289
2290var TypeAndVal = function TypeAndVal(_type,_val) {
2291 this.type = _type;
2292 this.val = _val;
2293
2294};
2295
2296BinaryXMLEncoder.prototype.encodeTypeAndVal = function(
2297 //int
2298 type,
2299 //long
2300 val,
2301 //byte []
2302 buf) {
2303
2304 if(LOG>4)console.log('Encoding type '+ type+ ' and value '+ val);
2305
2306 if(LOG>4) console.log('OFFSET IS ' + this.offset );
2307
2308 if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
2309 throw new Error("Tag and value must be positive, and tag valid.");
2310 }
2311
2312 // Encode backwards. Calculate how many bytes we need:
2313 var numEncodingBytes = this.numEncodingBytes(val);
2314
2315 if ((this.offset + numEncodingBytes) > buf.length) {
2316 throw new Error("Buffer space of " + (buf.length-this.offset) +
2317 " bytes insufficient to hold " +
2318 numEncodingBytes + " of encoded type and value.");
2319 }
2320
2321 // Bottom 4 bits of val go in last byte with tag.
2322 buf[this.offset + numEncodingBytes - 1] =
2323 //(byte)
2324 (BYTE_MASK &
2325 (((XML_TT_MASK & type) |
2326 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
2327 XML_TT_NO_MORE); // set top bit for last byte
2328 val = val >>> XML_TT_VAL_BITS;;
2329
2330 // Rest of val goes into preceding bytes, 7 bits per byte, top bit
2331 // is "more" flag.
2332 var i = this.offset + numEncodingBytes - 2;
2333 while ((0 != val) && (i >= this.offset)) {
2334 buf[i] = //(byte)
2335 (BYTE_MASK &
2336 (val & XML_REG_VAL_MASK)); // leave top bit unset
2337 val = val >>> XML_REG_VAL_BITS;
2338 --i;
2339 }
2340 if (val != 0) {
2341 throw new Error( "This should not happen: miscalculated encoding");
2342 //Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
2343 }
2344 this.offset+= numEncodingBytes;
2345
2346 return numEncodingBytes;
2347};
2348
2349BinaryXMLEncoder.prototype.encodeUString = function(
2350 //OutputStream
2351 ostream,
2352 //String
2353 ustring,
2354 //byte
2355 type) {
2356
2357 if ((null == ustring) || (ustring.length == 0)) {
2358 return;
2359 }
2360
2361
2362 //byte [] data utils
2363 /*custom*/
2364 //byte[]
2365
2366 if(LOG>3) console.log("The string to write is ");
2367
2368 if(LOG>3) console.log(ustring);
2369
2370 //COPY THE STRING TO AVOID PROBLEMS
2371 strBytes = new Array(ustring.length);
2372
2373 var i = 0;
2374
2375 for( ; i<ustring.length; i++) //in InStr.ToCharArray())
2376 {
2377 if(LOG>3)console.log("ustring[" + i + '] = ' + ustring[i]);
2378 strBytes[i] = ustring.charCodeAt(i);
2379 }
2380
2381 //strBytes = DataUtils.getBytesFromUTF8String(ustring);
2382
2383 this.encodeTypeAndVal(type,
2384 (((type == XML_TAG) || (type == XML_ATTR)) ?
2385 (strBytes.length-1) :
2386 strBytes.length), ostream);
2387
2388 if(LOG>3) console.log("THE string to write is ");
2389
2390 if(LOG>3) console.log(strBytes);
2391
2392 this.writeString(strBytes,this.offset);
2393
2394 this.offset+= strBytes.length;
2395
2396};
2397
2398
2399
2400BinaryXMLEncoder.prototype.encodeBlob = function(
2401 //OutputStream
2402 ostream,
2403 //byte []
2404 blob,
2405 //int
2406 offset,
2407 //int
2408 length) {
2409
2410
2411 if ((null == blob) || (length == 0)) {
2412
2413 return;
2414 }
2415
2416 if(LOG>4) console.log('LENGTH OF XML_BLOB IS '+length);
2417
2418
2419 blobCopy = new Array(blob.Length);
2420 var i = 0;
2421 for( ;i<blob.length;i++) //in InStr.ToCharArray())
2422 {
2423 blobCopy[i] = blob[i];
2424 }
2425
2426 this.encodeTypeAndVal(XML_BLOB, length, ostream,offset);
2427
2428 if (null != blob) {
2429
2430 this.writeBlobArray(blobCopy,this.offset);
2431 this.offset += length;
2432 }
2433};
2434
2435var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
2436var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
2437var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
2438
2439BinaryXMLEncoder.prototype.numEncodingBytes = function(
2440 //long
2441 x) {
2442 if (x <= ENCODING_LIMIT_1_BYTE) return (1);
2443 if (x <= ENCODING_LIMIT_2_BYTES) return (2);
2444 if (x <= ENCODING_LIMIT_3_BYTES) return (3);
2445
2446 var numbytes = 1;
2447
2448 // Last byte gives you XML_TT_VAL_BITS
2449 // Remainder each give you XML_REG_VAL_BITS
2450 x = x >>> XML_TT_VAL_BITS;
2451 while (x != 0) {
2452 numbytes++;
2453 x = x >>> XML_REG_VAL_BITS;
2454 }
2455 return (numbytes);
2456};
2457
2458BinaryXMLEncoder.prototype.writeDateTime = function(
2459 //String
2460 tag,
2461 //CCNTime
2462 dateTime) {
2463
2464 if(LOG>4)console.log('ENCODING DATE with LONG VALUE');
2465 if(LOG>4)console.log(dateTime.msec);
2466
2467 //var binarydate = DataUtils.unsignedLongToByteArray( Math.round((dateTime.msec/1000) * 4096) );
2468
2469
2470 //parse to hex
2471 var binarydate = Math.round((dateTime.msec/1000) * 4096).toString(16) ;
2472
2473 //HACK
2474 var binarydate = DataUtils.toNumbers( '0'.concat(binarydate,'0')) ;
2475
2476
2477 if(LOG>4)console.log('ENCODING DATE with BINARY VALUE');
2478 if(LOG>4)console.log(binarydate);
2479
2480 if(LOG>4)console.log('ENCODING DATE with BINARY VALUE(HEX)');
2481 if(LOG>4)console.log(DataUtils.toHex(binarydate));
2482
2483
2484 this.writeElement(tag, binarydate);
2485
2486};
2487
2488BinaryXMLEncoder.prototype.writeString = function(
2489 //String
2490 input,
2491 //CCNTime
2492 offset) {
2493
2494 if(typeof input === 'string'){
2495 //console.log('went here');
2496 if(LOG>4) console.log('GOING TO WRITE A STRING');
2497 if(LOG>4) console.log(input);
2498
2499 for (var i = 0; i < input.length; i++) {
2500 if(LOG>4) console.log('input.charCodeAt(i)=' + input.charCodeAt(i));
2501 this.ostream[this.offset+i] = (input.charCodeAt(i));
2502 }
2503 }
2504
2505 else{
2506
2507 if(LOG>4) console.log('GOING TO WRITE A STRING IN BINARY FORM');
2508 if(LOG>4) console.log(input);
2509
2510 this.writeBlobArray(input);
2511
2512 }
2513 /*
2514 else if(typeof input === 'object'){
2515
2516 }
2517 */
2518};
2519
2520BinaryXMLEncoder.prototype.writeBlobArray = function(
2521 //String
2522 Blob,
2523 //CCNTime
2524 offset) {
2525
2526 if(LOG>4) console.log('GOING TO WRITE A BLOB');
2527
2528 for (var i = 0; i < Blob.length; i++) {
2529 this.ostream[this.offset+i] = Blob[i];
2530 }
2531
2532};
2533
2534
2535
2536BinaryXMLEncoder.prototype.getReducedOstream = function() {
2537
2538 return this.ostream.slice(0,this.offset);
2539
2540};
2541
2542
2543/*
2544 * This class is used to encode and decode binary elements ( blog, type/value pairs)
2545 *
2546 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07002547 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002548 */
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002549
2550var XML_EXT = 0x00;
2551
2552var XML_TAG = 0x01;
2553
2554var XML_DTAG = 0x02;
2555
2556var XML_ATTR = 0x03;
2557
2558var XML_DATTR = 0x04;
2559
2560var XML_BLOB = 0x05;
2561
2562var XML_UDATA = 0x06;
2563
2564var XML_CLOSE = 0x0;
2565
2566var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16;
2567
2568
2569var XML_TT_BITS = 3;
2570var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
2571var XML_TT_VAL_BITS = XML_TT_BITS + 1;
2572var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
2573var XML_REG_VAL_BITS = 7;
2574var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
2575var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
2576var BYTE_MASK = 0xFF;
2577var LONG_BYTES = 8;
2578var LONG_BITS = 64;
2579
2580var bits_11 = 0x0000007FF;
2581var bits_18 = 0x00003FFFF;
2582var bits_32 = 0x0FFFFFFFF;
2583
2584
2585
2586//returns a string
2587tagToString = function(/*long*/ tagVal) {
2588 if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
2589 return CCNProtocolDTagsStrings[tagVal];
2590 } else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
2591 return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
2592 }
2593 return null;
2594};
2595
2596//returns a Long
2597stringToTag = function(/*String*/ tagName) {
2598 // the slow way, but right now we don't care.... want a static lookup for the forward direction
2599 for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
2600 if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
2601 return i;
2602 }
2603 }
2604 if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
2605 return CCNProtocolDTags.CCNProtocolDataUnit;
2606 }
2607 return null;
2608};
2609
2610//console.log(stringToTag(64));
2611var BinaryXMLDecoder = function BinaryXMLDecoder(istream){
2612 var MARK_LEN=512;
2613 var DEBUG_MAX_LEN = 32768;
2614
2615 this.istream = istream;
2616 //console.log('istream is '+ this.istream);
2617 this.offset = 0;
2618};
2619
2620
2621BinaryXMLDecoder.prototype.readStartElement =function(
2622 //String
2623 startTag,
2624 //TreeMap<String, String>
2625 attributes) {
2626
2627 try {
2628 //this.TypeAndVal
2629 tv = this.decodeTypeAndVal(this.istream);
2630
2631 if (null == tv) {
2632 throw new Error("Expected start element: " + startTag + " got something not a tag.");
2633 }
2634
2635 //String
2636 decodedTag = null;
2637
2638 if (tv.type() == XML_TAG) {
2639
2640 decodedTag = this.decodeUString(this.Istream, tv.val()+1);
2641
2642 } else if (tv.type() == XML_DTAG) {
2643 decodedTag = tagToString(tv.val());
2644 }
2645
2646 if ((null == decodedTag) || decodedTag != startTag) {
2647 throw new Error("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")");
2648 }
2649
2650 if (null != attributes) {
2651 readAttributes(attributes);
2652 }
2653
2654 } catch (e) {
2655 throw new Error("readStartElement", e);
2656 }
2657};
2658
2659BinaryXMLDecoder.prototype.readAttributes = function(
2660 //TreeMap<String,String>
2661 attributes){
2662
2663 if (null == attributes) {
2664 return;
2665 }
2666
2667 try {
2668
2669 //this.TypeAndVal
2670 nextTV = this.peekTypeAndVal(this.istream);
2671
2672 while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
2673 (XML_DATTR == nextTV.type()))) {
2674
2675 //this.TypeAndVal
2676 thisTV = this.decodeTypeAndVal(this.Istream);
2677
2678 var attributeName = null;
2679 if (XML_ATTR == thisTV.type()) {
2680
2681 attributeName = this.decodeUString(this.istream, thisTV.val()+1);
2682
2683 } else if (XML_DATTR == thisTV.type()) {
2684 // DKS TODO are attributes same or different dictionary?
2685 attributeName = tagToString(thisTV.val());
2686 if (null == attributeName) {
Jeff Thompson744d28e2012-10-09 23:19:04 -07002687 throw new ContentDecodingException("Unknown DATTR value" + thisTV.val());
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002688 }
2689 }
2690
2691 var attributeValue = this.decodeUString(this.istream);
2692
2693 attributes.put(attributeName, attributeValue);
2694
2695 nextTV = this.peekTypeAndVal(this.istream);
2696 }
2697
2698 } catch ( e) {
2699
Jeff Thompson744d28e2012-10-09 23:19:04 -07002700 throw new ContentDecodingException("readStartElement", e);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002701 }
2702};
2703
2704
2705BinaryXMLDecoder.prototype.initializeDecoding = function() {
2706 //if (!this.istream.markSupported()) {
2707 //throw new IllegalArgumentException(this.getClass().getName() + ": input stream must support marking!");
2708 //}
2709}
2710
2711BinaryXMLDecoder.prototype.readStartDocument = function(){
2712 // Currently no start document in binary encoding.
2713 }
2714
2715BinaryXMLDecoder.prototype.readEndDocument = function() {
2716 // Currently no end document in binary encoding.
2717 };
2718
2719BinaryXMLDecoder.prototype.readStartElement = function(
2720 //String
2721 startTag,
2722 //TreeMap<String, String>
2723 attributes) {
2724
2725
2726 //NOT SURE
2727 //if(typeof startTag == 'number')
2728 //startTag = tagToString(startTag);
2729
2730 //try {
2731 //TypeAndVal
2732 tv = this.decodeTypeAndVal(this.istream);
2733
2734 if (null == tv) {
2735 throw new Error("Expected start element: " + startTag + " got something not a tag.");
2736 }
2737
2738 //String
2739 decodedTag = null;
2740 //console.log(tv);
2741 //console.log(typeof tv);
2742
2743 //console.log(XML_TAG);
2744 if (tv.type() == XML_TAG) {
2745 //console.log('got here');
2746 //Log.info(Log.FAC_ENCODING, "Unexpected: got tag in readStartElement; looking for tag " + startTag + " got length: " + (int)tv.val()+1);
2747 // Tag value represents length-1 as tags can never be empty.
2748 var valval ;
2749 if(typeof tv.val() == 'string'){
2750 valval = (parseInt(tv.val())) + 1;
2751 }
2752 else
2753 valval = (tv.val())+ 1;
2754
2755 //console.log('valval is ' +valval);
2756
2757 decodedTag = this.decodeUString(this.istream, valval);
2758
2759 } else if (tv.type() == XML_DTAG) {
2760 //console.log('gothere');
2761 //console.log(tv.val());
2762 //decodedTag = tagToString(tv.val());
2763 //console.log()
2764 decodedTag = tv.val();
2765 }
2766
2767 //console.log(decodedTag);
2768 //console.log('startTag is '+startTag);
2769
2770
2771 if ((null == decodedTag) || decodedTag != startTag ) {
2772 console.log('expecting '+ startag + ' but got '+ decodedTag);
2773 throw new Error("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")");
2774 }
2775
2776 // DKS: does not read attributes out of stream if caller doesn't
2777 // ask for them. Should possibly peek and skip over them regardless.
2778 // TODO: fix this
2779 if (null != attributes) {
2780 readAttributes(attributes);
2781 }
2782
2783 //} catch ( e) {
2784 //console.log(e);
2785 //throw new Error("readStartElement", e);
2786 //}
2787 }
2788
2789
2790BinaryXMLDecoder.prototype.readAttributes = function(
2791 //TreeMap<String,String>
2792 attributes) {
2793
2794 if (null == attributes) {
2795 return;
2796 }
2797
2798 try {
2799 // Now need to get attributes.
2800 //TypeAndVal
2801 nextTV = this.peekTypeAndVal(this.istream);
2802
2803 while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
2804 (XML_DATTR == nextTV.type()))) {
2805
2806 // Decode this attribute. First, really read the type and value.
2807 //this.TypeAndVal
2808 thisTV = this.decodeTypeAndVal(this.istream);
2809
2810 //String
2811 attributeName = null;
2812 if (XML_ATTR == thisTV.type()) {
2813 // Tag value represents length-1 as attribute names cannot be empty.
2814 var valval ;
2815 if(typeof tv.val() == 'string'){
2816 valval = (parseInt(tv.val())) + 1;
2817 }
2818 else
2819 valval = (tv.val())+ 1;
2820
2821 attributeName = this.decodeUString(this.istream,valval);
2822
2823 } else if (XML_DATTR == thisTV.type()) {
2824 // DKS TODO are attributes same or different dictionary?
2825 attributeName = tagToString(thisTV.val());
2826 if (null == attributeName) {
2827 throw new Error("Unknown DATTR value" + thisTV.val());
2828 }
2829 }
2830 // Attribute values are always UDATA
2831 //String
2832 attributeValue = this.decodeUString(this.istream);
2833
2834 //
2835 attributes.push([attributeName, attributeValue]);
2836
2837 nextTV = this.peekTypeAndVal(this.istream);
2838 }
2839
2840 } catch ( e) {
2841 Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
2842 throw new Error("readStartElement", e);
2843 }
2844};
2845
2846//returns a string
2847BinaryXMLDecoder.prototype.peekStartElementAsString = function() {
2848 //this.istream.mark(MARK_LEN);
2849
2850 //String
2851 decodedTag = null;
2852 var previousOffset = this.offset;
2853 try {
2854 // Have to distinguish genuine errors from wrong tags. Could either use
2855 // a special exception subtype, or redo the work here.
2856 //this.TypeAndVal
2857 tv = this.decodeTypeAndVal(this.istream);
2858
2859 if (null != tv) {
2860
2861 if (tv.type() == XML_TAG) {
2862 /*if (tv.val()+1 > DEBUG_MAX_LEN) {
Jeff Thompson744d28e2012-10-09 23:19:04 -07002863 throw new ContentDecodingException("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!");
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002864 }*/
2865
2866 // Tag value represents length-1 as tags can never be empty.
2867 var valval ;
2868 if(typeof tv.val() == 'string'){
2869 valval = (parseInt(tv.val())) + 1;
2870 }
2871 else
2872 valval = (tv.val())+ 1;
2873
2874 decodedTag = this.decodeUString(this.istream, valval);
2875
2876 //Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
2877
2878 } else if (tv.type() == XML_DTAG) {
2879 decodedTag = tagToString(tv.val());
2880 }
2881
2882 } // else, not a type and val, probably an end element. rewind and return false.
2883
2884 } catch ( e) {
2885
2886 } finally {
2887 try {
2888 this.offset = previousOffset;
2889 } catch ( e) {
2890 Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
Jeff Thompson744d28e2012-10-09 23:19:04 -07002891 throw new ContentDecodingException("Cannot reset stream! " + e.getMessage(), e);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002892 }
2893 }
2894 return decodedTag;
2895};
2896
2897BinaryXMLDecoder.prototype.peekStartElement = function(
2898 //String
2899 startTag) {
2900 //String
2901 if(typeof startTag == 'string'){
2902 decodedTag = this.peekStartElementAsString();
2903
2904 if ((null != decodedTag) && decodedTag == startTag) {
2905 return true;
2906 }
2907 return false;
2908 }
2909 else if(typeof startTag == 'number'){
2910 decodedTag = this.peekStartElementAsLong();
2911 if ((null != decodedTag) && decodedTag == startTag) {
2912 return true;
2913 }
2914 return false;
2915 }
2916 else{
2917 throw new Error("SHOULD BE STRING OR NUMBER");
2918 }
2919}
2920//returns Long
2921BinaryXMLDecoder.prototype.peekStartElementAsLong = function() {
2922 //this.istream.mark(MARK_LEN);
2923
2924 //Long
2925 decodedTag = null;
2926
2927 var previousOffset = this.offset;
2928
2929 try {
2930 // Have to distinguish genuine errors from wrong tags. Could either use
2931 // a special exception subtype, or redo the work here.
2932 //this.TypeAndVal
2933 tv = this.decodeTypeAndVal(this.istream);
2934
2935 if (null != tv) {
2936
2937 if (tv.type() == XML_TAG) {
2938 if (tv.val()+1 > DEBUG_MAX_LEN) {
Jeff Thompson744d28e2012-10-09 23:19:04 -07002939 throw new ContentDecodingException("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!");
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002940 }
2941
2942 var valval ;
2943 if(typeof tv.val() == 'string'){
2944 valval = (parseInt(tv.val())) + 1;
2945 }
2946 else
2947 valval = (tv.val())+ 1;
2948
2949 // Tag value represents length-1 as tags can never be empty.
2950 //String
2951 strTag = this.decodeUString(this.istream, valval);
2952
2953 decodedTag = stringToTag(strTag);
2954
2955 //Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
2956
2957 } else if (tv.type() == XML_DTAG) {
2958 decodedTag = tv.val();
2959 }
2960
2961 } // else, not a type and val, probably an end element. rewind and return false.
2962
2963 } catch ( e) {
2964
2965 } finally {
2966 try {
2967 //this.istream.reset();
2968 this.offset = previousOffset;
2969 } catch ( e) {
2970 Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
2971 throw new Error("Cannot reset stream! " + e.getMessage(), e);
2972 }
2973 }
2974 return decodedTag;
2975 };
2976
2977
2978// returns a byte[]
2979BinaryXMLDecoder.prototype.readBinaryElement = function(
2980 //long
2981 startTag,
2982 //TreeMap<String, String>
2983 attributes){
2984 //byte []
2985 blob = null;
2986
2987 this.readStartElement(startTag, attributes);
2988 blob = this.readBlob();
2989
2990
2991 return blob;
2992
2993};
2994
2995
2996BinaryXMLDecoder.prototype.readEndElement = function(){
2997 //try {
2998 if(LOG>4)console.log('this.offset is '+this.offset);
2999
3000 var next = this.istream[this.offset];
3001
3002 this.offset++;
3003 //read();
3004
3005 if(LOG>4)console.log('XML_CLOSE IS '+XML_CLOSE);
3006 if(LOG>4)console.log('next is '+next);
3007
3008 if (next != XML_CLOSE) {
3009 console.log("Expected end element, got: " + next);
Jeff Thompson744d28e2012-10-09 23:19:04 -07003010 throw new ContentDecodingException("Expected end element, got: " + next);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003011 }
3012 //} catch ( e) {
Jeff Thompson744d28e2012-10-09 23:19:04 -07003013 //throw new ContentDecodingException(e);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003014 //}
3015 };
3016
3017
3018//String
3019BinaryXMLDecoder.prototype.readUString = function(){
3020 //String
3021 ustring = this.decodeUString(this.istream);
3022 this.readEndElement();
3023 return ustring;
3024
3025 };
3026
3027
3028//returns a byte[]
3029BinaryXMLDecoder.prototype.readBlob = function() {
3030 //byte []
3031
3032 blob = this.decodeBlob(this.istream);
3033 this.readEndElement();
3034 return blob;
3035
3036 };
3037
3038
3039//CCNTime
3040BinaryXMLDecoder.prototype.readDateTime = function(
3041 //long
3042 startTag) {
3043 //byte []
3044
3045 var byteTimestamp = this.readBinaryElement(startTag);
3046
3047 //var lontimestamp = DataUtils.byteArrayToUnsignedLong(byteTimestamp);
3048
3049 var byteTimestamp = DataUtils.toHex(byteTimestamp);
3050
3051
3052 var byteTimestamp = parseInt(byteTimestamp, 16);
3053
3054 lontimestamp = (byteTimestamp/ 4096) * 1000;
3055
3056 //if(lontimestamp<0) lontimestamp = - lontimestamp;
3057
3058 if(LOG>3) console.log('DECODED DATE WITH VALUE');
3059 if(LOG>3) console.log(lontimestamp);
3060
3061
3062 //CCNTime
3063 timestamp = new CCNTime(lontimestamp);
3064 //timestamp.setDateBinary(byteTimestamp);
3065
3066 if (null == timestamp) {
Jeff Thompson744d28e2012-10-09 23:19:04 -07003067 throw new ContentDecodingException("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003068 }
3069 return timestamp;
3070};
3071
3072BinaryXMLDecoder.prototype.decodeTypeAndVal = function(
3073 /*InputStream*/
3074 istream) {
3075
3076 /*int*/next;
3077 /*int*/type = -1;
3078 /*long*/val = 0;
3079 /*boolean*/more = true;
3080
3081
3082 //var savedOffset = this.offset;
3083 var count = 0;
3084
3085 do {
3086
3087 var next = this.istream[this.offset ];
3088
3089
3090 if (next < 0) {
3091 return null;
3092 }
3093
3094 if ((0 == next) && (0 == val)) {
3095 return null;
3096 }
3097
3098 more = (0 == (next & XML_TT_NO_MORE));
3099
3100 if (more) {
3101 val = val << XML_REG_VAL_BITS;
3102 val |= (next & XML_REG_VAL_MASK);
3103 } else {
3104
3105 type = next & XML_TT_MASK;
3106 val = val << XML_TT_VAL_BITS;
3107 val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
3108 }
3109
3110 this.offset++;
3111
3112 } while (more);
3113
3114 if(LOG>3)console.log('TYPE is '+ type + ' VAL is '+ val);
3115
3116 return new TypeAndVal(type, val);
3117};
3118
3119
3120
3121//TypeAndVal
3122BinaryXMLDecoder.peekTypeAndVal = function(
3123 //InputStream
3124 istream) {
3125 //TypeAndVal
3126 tv = null;
3127
3128 //istream.mark(LONG_BYTES*2);
3129
3130 var previousOffset = this.offset;
3131
3132 try {
3133 tv = this.decodeTypeAndVal(this.istream);
3134 } finally {
3135 //istream.reset();
3136 this.offset = previousOffset;
3137 }
3138
3139 return tv;
3140};
3141
3142
3143//byte[]
3144BinaryXMLDecoder.prototype.decodeBlob = function(
3145 //InputStream
3146 istream,
3147 //int
3148 blobLength) {
3149
3150
3151 if(null == blobLength){
3152 //TypeAndVal
3153 tv = this.decodeTypeAndVal(this.istream);
3154
3155 var valval ;
3156
3157 if(typeof tv.val() == 'string'){
3158 valval = (parseInt(tv.val()));
3159 }
3160 else
3161 valval = (tv.val());
3162
3163 //console.log('valval here is ' + valval);
3164 return this.decodeBlob(this.istream, valval);
3165 }
3166
3167 //
3168 //byte []
3169
3170 bytes = this.istream.slice(this.offset, this.offset+ blobLength);
3171 this.offset += blobLength;
3172
3173 //int
3174 return bytes;
3175
3176 count = 0;
3177
3178};
3179
3180var count =0;
3181
3182//String
3183BinaryXMLDecoder.prototype.decodeUString = function(
3184 //InputStream
3185 istream,
3186 //int
3187 byteLength) {
3188
3189 /*
3190 console.log('COUNT IS '+count);
3191 console.log('INPUT BYTELENGTH IS '+byteLength);
3192 count++;
3193 if(null == byteLength|| undefined == byteLength){
3194 console.log("!!!!");
3195 tv = this.decodeTypeAndVal(this.istream);
3196 var valval ;
3197 if(typeof tv.val() == 'string'){
3198 valval = (parseInt(tv.val()));
3199 }
3200 else
3201 valval = (tv.val());
3202
3203 if(LOG>4) console.log('valval is ' + valval);
3204 byteLength= this.decodeUString(this.istream, valval);
3205
3206 //if(LOG>4) console.log('byte Length found in type val is '+ byteLength.charCodeAt(0));
3207 byteLength = parseInt(byteLength);
3208
3209
3210 //byteLength = byteLength.charCodeAt(0);
3211 //if(LOG>4) console.log('byte Length found in type val is '+ byteLength);
3212 }
3213 if(LOG>4)console.log('byteLength is '+byteLength);
3214 if(LOG>4)console.log('type of byteLength is '+typeof byteLength);
3215
3216 stringBytes = this.decodeBlob(this.istream, byteLength);
3217
3218 //console.log('String bytes are '+ stringBytes);
3219 //console.log('stringBytes);
3220
3221 if(LOG>4)console.log('byteLength is '+byteLength);
3222 if(LOG>4)console.log('this.offset is '+this.offset);
3223
3224 tempBuffer = this.istream.slice(this.offset, this.offset+byteLength);
3225 if(LOG>4)console.log('TEMPBUFFER IS' + tempBuffer);
3226 if(LOG>4)console.log( tempBuffer);
3227
3228 if(LOG>4)console.log('ADDING to offset value' + byteLength);
3229 this.offset+= byteLength;
3230 //if(LOG>3)console.log('read the String' + tempBuffer.toString('ascii'));
3231 //return tempBuffer.toString('ascii');//
3232
3233
3234 //if(LOG>3)console.log( 'STRING READ IS '+ DataUtils.getUTF8StringFromBytes(stringBytes) ) ;
3235 //if(LOG>3)console.log( 'STRING READ IS '+ DataUtils.getUTF8StringFromBytes(tempBuffer) ) ;
3236 //if(LOG>3)console.log(DataUtils.getUTF8StringFromBytes(tempBuffer) ) ;
3237 //return DataUtils.getUTF8StringFromBytes(tempBuffer);
3238
3239 if(LOG>3)console.log( 'STRING READ IS '+ DataUtils.toString(stringBytes) ) ;
3240 if(LOG>3)console.log( 'TYPE OF STRING READ IS '+ typeof DataUtils.toString(stringBytes) ) ;
3241
3242 return DataUtils.toString(stringBytes);*/
3243
3244 if(null == byteLength ){
3245 var tempStreamPosition = this.offset;
3246
3247 //TypeAndVal
3248 tv = this.decodeTypeAndVal(istream);
3249
3250 if(LOG>3)console.log('TV is '+tv);
3251 if(LOG>3)console.log(tv);
3252
3253 if(LOG>3)console.log('Type of TV is '+typeof tv);
3254
3255 if ((null == tv) || (XML_UDATA != tv.type())) { // if we just have closers left, will get back null
3256 //if (Log.isLoggable(Log.FAC_ENCODING, Level.FINEST))
3257 //Log.finest(Log.FAC_ENCODING, "Expected UDATA, got " + ((null == tv) ? " not a tag " : tv.type()) + ", assuming elided 0-length blob.");
3258
3259 this.offset = tempStreamPosition;
3260
3261 return "";
3262 }
3263
3264 return this.decodeUString(istream, tv.val());
3265 }
3266 else{
3267 //byte []
3268 stringBytes = this.decodeBlob(istream, byteLength);
3269
3270 //return DataUtils.getUTF8StringFromBytes(stringBytes);
3271 return DataUtils.toString(stringBytes);
3272
3273 }
3274};
3275
3276
3277
3278
3279//OBject containg a pair of type and value
3280var TypeAndVal = function TypeAndVal(_type,_val) {
3281 this.t = _type;
3282 this.v = _val;
3283};
3284
3285TypeAndVal.prototype.type = function(){
3286 return this.t;
3287};
3288
3289TypeAndVal.prototype.val = function(){
3290 return this.v;
3291};
3292//TODO
3293
3294
3295
3296
3297
3298
3299BinaryXMLDecoder.prototype.readIntegerElement =function(
3300 //String
3301 startTag) {
3302
3303 //String
3304 if(LOG>4) console.log('READING INTEGER '+ startTag);
3305 if(LOG>4) console.log('TYPE OF '+ typeof startTag);
3306
3307 //try {
3308
3309 strVal = this.readUTF8Element(startTag);
3310
3311 //}
3312 //catch (e) {
3313 //throw new Error("Cannot parse " + startTag + ": " + strVal);
3314 //}
3315
3316 return parseInt(strVal);
3317};
3318
3319
3320BinaryXMLDecoder.prototype.readUTF8Element =function(
3321 //String
3322 startTag,
3323 //TreeMap<String, String>
3324 attributes) {
Jeff Thompson744d28e2012-10-09 23:19:04 -07003325 //throws ContentDecodingException
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003326
3327 this.readStartElement(startTag, attributes); // can't use getElementText, can't get attributes
3328 //String
3329 strElementText = this.readUString();
3330 return strElementText;
3331};
3332
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003333/*
3334 * This class contains utilities to help parse the data
3335 * author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07003336 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003337 */
3338
3339var DataUtils = function DataUtils(){
3340
3341
3342};
3343
3344
3345/*
3346 * NOTE THIS IS CURRENTLY NOT BEHING USED
3347 *
3348 */
3349
3350DataUtils.keyStr = "ABCDEFGHIJKLMNOP" +
3351 "QRSTUVWXYZabcdef" +
3352 "ghijklmnopqrstuv" +
3353 "wxyz0123456789+/" +
3354 "=";
3355
3356
3357/**
3358 * Raw String to Base 64
3359 */
3360DataUtils.stringtoBase64=function stringtoBase64(input) {
3361 input = escape(input);
3362 var output = "";
3363 var chr1, chr2, chr3 = "";
3364 var enc1, enc2, enc3, enc4 = "";
3365 var i = 0;
3366
3367 do {
3368 chr1 = input.charCodeAt(i++);
3369 chr2 = input.charCodeAt(i++);
3370 chr3 = input.charCodeAt(i++);
3371
3372 enc1 = chr1 >> 2;
3373 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
3374 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
3375 enc4 = chr3 & 63;
3376
3377 if (isNaN(chr2)) {
3378 enc3 = enc4 = 64;
3379 } else if (isNaN(chr3)) {
3380 enc4 = 64;
3381 }
3382
3383 output = output +
3384 DataUtils.keyStr.charAt(enc1) +
3385 DataUtils.keyStr.charAt(enc2) +
3386 DataUtils.keyStr.charAt(enc3) +
3387 DataUtils.keyStr.charAt(enc4);
3388 chr1 = chr2 = chr3 = "";
3389 enc1 = enc2 = enc3 = enc4 = "";
3390 } while (i < input.length);
3391
3392 return output;
3393 }
3394
3395/**
3396 * Base 64 to Raw String
3397 */
3398DataUtils.base64toString = function base64toString(input) {
3399 var output = "";
3400 var chr1, chr2, chr3 = "";
3401 var enc1, enc2, enc3, enc4 = "";
3402 var i = 0;
3403
3404 // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
3405 var base64test = /[^A-Za-z0-9\+\/\=]/g;
3406 /* Test for invalid characters. */
3407 if (base64test.exec(input)) {
3408 alert("There were invalid base64 characters in the input text.\n" +
3409 "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
3410 "Expect errors in decoding.");
3411 }
3412
3413 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
3414
3415 do {
3416 enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
3417 enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
3418 enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
3419 enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));
3420
3421 chr1 = (enc1 << 2) | (enc2 >> 4);
3422 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
3423 chr3 = ((enc3 & 3) << 6) | enc4;
3424
3425 output = output + String.fromCharCode(chr1);
3426
3427 if (enc3 != 64) {
3428 output = output + String.fromCharCode(chr2);
3429 }
3430 if (enc4 != 64) {
3431 output = output + String.fromCharCode(chr3);
3432 }
3433
3434 chr1 = chr2 = chr3 = "";
3435 enc1 = enc2 = enc3 = enc4 = "";
3436
3437 } while (i < input.length);
3438
3439 return unescape(output);
3440 };
3441
3442//byte []
3443
3444/**
3445 * NOT WORKING!!!!!
3446 *
3447 * Unsiged Long Number to Byte Array
3448 */
3449
3450 /*
3451DataUtils.unsignedLongToByteArray= function( value) {
3452
3453 if(LOG>4)console.log('INPUT IS '+value);
3454
3455 if( 0 == value )
3456 return [0];
3457
3458 if( 0 <= value && value <= 0x00FF ) {
3459 //byte []
3460 var bb = new Array(1);
3461 bb[0] = (value & 0x00FF);
3462 return bb;
3463 }
3464
3465 if(LOG>4) console.log('type of value is '+typeof value);
3466 if(LOG>4) console.log('value is '+value);
3467 //byte []
3468 var out = null;
3469 //int
3470 var offset = -1;
3471 for(var i = 7; i >=0; --i) {
3472 //byte
3473 console.log(i);
3474 console.log('value is '+value);
3475 console.log('(value >> (i * 8)) '+ (value >> (i * 8)) );
3476 console.log(' ((value >> (i * 8)) & 0xFF) '+ ((value >> (i * 8)) & 0xFF) );
3477
3478 var b = ((value >> (i * 8)) & 0xFF) ;
3479
3480 if(LOG>4) console.log('b is '+b);
3481
3482 if( out == null && b != 0 ) {
3483 //out = new byte[i+1];
3484 out = new Array(i+1);
3485 offset = i;
3486 }
3487
3488 if( out != null )
3489 out[ offset - i ] = b;
3490 }
3491 if(LOG>4)console.log('OUTPUT IS ');
3492 if(LOG>4)console.log(out);
3493 return out;
3494}
3495*/
3496
3497/**
3498 * NOT WORKING!!!!!
3499 *
3500 * Unsiged Long Number to Byte Array
3501 *//*
3502DataUtils.byteArrayToUnsignedLong = function(//final byte []
3503 src) {
3504 if(LOG>4) console.log('INPUT IS ');
3505 if(LOG>4) console.log(src);
3506
3507 var value = 0;
3508 for(var i = 0; i < src.length; i++) {
3509 value = value << 8;
3510 // Java will assume the byte is signed, so extend it and trim it.
3511
3512
3513 var b = ((src[i]) & 0xFF );
3514 value |= b;
3515 }
3516
3517 if(LOG>4) console.log('OUTPUT IS ');
3518
3519 if(LOG>4) console.log(value);
3520
3521 return value;
3522 }*/
3523
3524
3525/**
3526 * Hex String to Byte Array
3527 */
3528 //THIS IS NOT WORKING
3529/*
3530DataUtils.HexStringtoByteArray = function(str) {
3531 var byteArray = [];
3532 for (var i = 0; i < str.length; i++)
3533 if (str.charCodeAt(i) <= 0x7F)
3534 byteArray.push(str.charCodeAt(i));
3535 else {
3536 var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
3537 for (var j = 0; j < h.length; j++)
3538 byteArray.push(parseInt(h[j], 16));
3539 }
3540 return byteArray;
3541};
3542*/
3543
3544/**
3545 * Byte Array to Hex String
3546 */
3547DataUtils.byteArrayToHexString = function(byteArray) {
3548 var str = '';
3549 for (var i = 0; i < byteArray.length; i++)
3550 str += byteArray[i] <= 0x7F?
3551 byteArray[i] === 0x25 ? "%25" : // %
3552 String.fromCharCode(byteArray[i]) :
3553 "%" + byteArray[i].toString(16).toUpperCase();
3554 return decodeURIComponent(str);
3555};
3556
3557
3558/**
3559 * Byte array to Hex String
3560 */
3561//http://ejohn.org/blog/numbers-hex-and-colors/
3562DataUtils.toHex = function(arguments){
3563 if(LOG>4) console.log('ABOUT TO CONVERT '+ arguments);
3564 //console.log(arguments);
3565 var ret = "";
3566 for ( var i = 0; i < arguments.length; i++ )
3567 ret += (arguments[i] < 16 ? "0" : "") + arguments[i].toString(16);
3568 return ret; //.toUpperCase();
3569}
3570
3571/**
3572 * Raw string to hex string.
3573 */
3574DataUtils.stringToHex = function(arguments){
3575 var ret = "";
3576 for (var i = 0; i < arguments.length; ++i) {
3577 var value = arguments.charCodeAt(i);
3578 ret += (value < 16 ? "0" : "") + value.toString(16);
3579 }
3580 return ret;
3581}
3582
3583/**
3584 * Byte array to raw string
3585 */
3586//DOES NOT SEEM TO WORK
3587DataUtils.toString = function(arguments){
3588 //console.log(arguments);
3589 var ret = "";
3590 for ( var i = 0; i < arguments.length; i++ )
3591 ret += String.fromCharCode(arguments[i]);
3592 return ret;
3593}
3594
3595/**
3596 * Hex String to byte array
3597 */
3598DataUtils.toNumbers=function( str ){
3599 if(typeof str =='string'){
3600 var ret = [];
3601 str.replace(/(..)/g, function(str){
3602 ret.push( parseInt( str, 16 ) );
3603 });
3604 return ret;
3605 }
3606}
3607
3608/**
3609 * Hex String to raw string.
3610 */
3611DataUtils.hexToRawString = function(str) {
3612 if(typeof str =='string') {
3613 var ret = "";
3614 str.replace(/(..)/g, function(s) {
3615 ret += String.fromCharCode(parseInt(s, 16));
3616 });
3617 return ret;
3618 }
3619}
3620
3621/**
3622 * Raw String to Byte Array
3623 */
3624DataUtils.toNumbersFromString = function( str ){
3625 var bytes = new Array(str.length);
3626 for(var i=0;i<str.length;i++)
3627 bytes[i] = str.charCodeAt(i);
3628 return bytes;
3629}
3630
3631DataUtils.encodeUtf8 = function (string) {
3632 string = string.replace(/\r\n/g,"\n");
3633 var utftext = "";
3634
3635 for (var n = 0; n < string.length; n++) {
3636
3637 var c = string.charCodeAt(n);
3638
3639 if (c < 128) {
3640 utftext += String.fromCharCode(c);
3641 }
3642 else if((c > 127) && (c < 2048)) {
3643 utftext += String.fromCharCode((c >> 6) | 192);
3644 utftext += String.fromCharCode((c & 63) | 128);
3645 }
3646 else {
3647 utftext += String.fromCharCode((c >> 12) | 224);
3648 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
3649 utftext += String.fromCharCode((c & 63) | 128);
3650 }
3651
3652 }
3653
3654 return utftext;
3655 };
3656
3657 // public method for url decoding
3658DataUtils.decodeUtf8 = function (utftext) {
3659 var string = "";
3660 var i = 0;
3661 var c = c1 = c2 = 0;
3662
3663 while ( i < utftext.length ) {
3664
3665 c = utftext.charCodeAt(i);
3666
3667 if (c < 128) {
3668 string += String.fromCharCode(c);
3669 i++;
3670 }
3671 else if((c > 191) && (c < 224)) {
3672 c2 = utftext.charCodeAt(i+1);
3673 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
3674 i += 2;
3675 }
3676 else {
3677 c2 = utftext.charCodeAt(i+1);
3678 c3 = utftext.charCodeAt(i+2);
3679 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
3680 i += 3;
3681 }
3682
3683 }
3684
3685 return string;
3686 };
3687
3688 test = function(){
3689 console.log(DataUtils.decodeUtf8("HELLO.~"));
3690 return DataUtils.decodeUtf8("HELLO.~");
3691 }
3692
3693//NOT WORKING
3694/*
3695DataUtils.getUTF8StringFromBytes = function(bytes) {
3696
3697 bytes = toString(bytes);
3698
3699 var ix = 0;
3700
3701 if( bytes.slice(0,3) == "\xEF\xBB\xBF") {
3702 ix = 3;
3703 }
3704
3705 var string = "";
3706 for( ; ix < bytes.length; ix++ ) {
3707 var byte1 = bytes[ix].charCodeAt(0);
3708 if( byte1 < 0x80 ) {
3709 string += String.fromCharCode(byte1);
3710 } else if( byte1 >= 0xC2 && byte1 < 0xE0 ) {
3711 var byte2 = bytes[++ix].charCodeAt(0);
3712 string += String.fromCharCode(((byte1&0x1F)<<6) + (byte2&0x3F));
3713 } else if( byte1 >= 0xE0 && byte1 < 0xF0 ) {
3714 var byte2 = bytes[++ix].charCodeAt(0);
3715 var byte3 = bytes[++ix].charCodeAt(0);
3716 string += String.fromCharCode(((byte1&0xFF)<<12) + ((byte2&0x3F)<<6) + (byte3&0x3F));
3717 } else if( byte1 >= 0xF0 && byte1 < 0xF5) {
3718 var byte2 = bytes[++ix].charCodeAt(0);
3719 var byte3 = bytes[++ix].charCodeAt(0);
3720 var byte4 = bytes[++ix].charCodeAt(0);
3721 var codepoint = ((byte1&0x07)<<18) + ((byte2&0x3F)<<12)+ ((byte3&0x3F)<<6) + (byte4&0x3F);
3722 codepoint -= 0x10000;
3723 string += String.fromCharCode(
3724 (codepoint>>10) + 0xD800,
3725 (codepoint&0x3FF) + 0xDC00
3726 );
3727 }
3728 }
3729
3730 return string;
3731}*/
3732
3733/**
3734 * Return true if a1 and a2 are the same length with equal elements.
3735 */
3736DataUtils.arraysEqual = function(a1, a2){
3737 if (a1.length != a2.length)
3738 return false;
3739
3740 for (var i = 0; i < a1.length; ++i) {
3741 if (a1[i] != a2[i])
3742 return false;
3743 }
3744
3745 return true;
3746}
Jeff Thompson745026e2012-10-13 12:49:20 -07003747/*
3748 * This file contains utilities to help encode and decode NDN objects.
3749 * author: ucla-cs
3750 * See COPYING for copyright and distribution information.
3751 */
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003752
3753function encodeToHexInterest(interest){
3754
3755 var enc = new BinaryXMLEncoder();
3756
3757 interest.to_ccnb(enc);
3758
3759 var hex = DataUtils.toHex(enc.getReducedOstream());
3760
3761 return hex;
3762
3763
3764}
3765
3766
3767function encodeToHexContentObject(co){
3768 var enc = new BinaryXMLEncoder();
3769
3770 co.to_ccnb(enc);
3771
3772 var hex = DataUtils.toHex(enc.getReducedOstream());
3773
3774 return hex;
3775
3776
3777}
3778
3779function encodeToBinaryContentObject(co){
3780 var enc = new BinaryXMLEncoder();
3781
3782 co.to_ccnb(enc);
3783
3784 var hex = enc.getReducedOstream();
3785
3786 return hex;
3787
3788
3789}
3790
3791function encodeForwardingEntry(co){
3792 var enc = new BinaryXMLEncoder();
3793
3794 co.to_ccnb(enc);
3795
3796 var bytes = enc.getReducedOstream();
3797
3798 return bytes;
3799
3800
3801}
3802
3803
3804
3805function decodeHexFaceInstance(result){
3806
3807 var numbers = DataUtils.toNumbers(result);
3808
3809
3810 decoder = new BinaryXMLDecoder(numbers);
3811
3812 if(LOG>3)console.log('DECODING HEX FACE INSTANCE \n'+numbers);
3813
3814 var faceInstance = new FaceInstance();
3815
3816 faceInstance.from_ccnb(decoder);
3817
3818 return faceInstance;
3819
3820}
3821
3822function decodeHexInterest(result){
3823 var numbers = DataUtils.toNumbers(result);
3824
3825
3826 decoder = new BinaryXMLDecoder(numbers);
3827 if(LOG>3)console.log('DECODING HEX INTERST \n'+numbers);
3828
3829 var interest = new Interest();
3830
3831 interest.from_ccnb(decoder);
3832
3833 return interest;
3834
3835}
3836
3837
3838
3839function decodeHexContentObject(result){
3840 var numbers = DataUtils.toNumbers(result);
3841
3842 decoder = new BinaryXMLDecoder(numbers);
3843 if(LOG>3)console.log('DECODED HEX CONTENT OBJECT \n'+numbers);
3844
3845 co = new ContentObject();
3846
3847 co.from_ccnb(decoder);
3848
3849 return co;
3850
3851}
3852
3853
3854
3855function decodeHexForwardingEntry(result){
3856 var numbers = DataUtils.toNumbers(result);
3857
3858 decoder = new BinaryXMLDecoder(numbers);
3859
3860 if(LOG>3)console.log('DECODED HEX FORWARDING ENTRY \n'+numbers);
3861
3862 forwardingEntry = new ForwardingEntry();
3863
3864 forwardingEntry.from_ccnb(decoder);
3865
3866 return forwardingEntry;
3867
3868}
3869
3870/* Return a user friendly HTML string with the contents of co.
3871 This also outputs to console.log.
3872 */
3873function contentObjectToHtml(/* ContentObject */ co) {
3874 var output ="";
3875
3876 if(co==-1)
3877 output+= "NO CONTENT FOUND"
3878 else if (co==-2)
3879 output+= "CONTENT NAME IS EMPTY"
3880 else{
3881 if(co.name!=null && co.name.components!=null){
3882 output+= "NAME: ";
3883
3884 for(var i=0;i<co.name.components.length;i++){
3885 output+= "/"+ DataUtils.toString(co.name.components[i]);
3886 }
3887 output+= "<br />";
3888 output+= "<br />";
3889 }
3890
3891 if(co.content !=null){
3892 output += "CONTENT(ASCII): "+ DataUtils.toString(co.content);
3893
3894 output+= "<br />";
3895 output+= "<br />";
3896 }
3897 if(co.content !=null){
3898 output += "CONTENT(hex): "+ DataUtils.toHex(co.content);
3899
3900 output+= "<br />";
3901 output+= "<br />";
3902 }
3903 if(co.signature !=null && co.signature.signature!=null){
3904 output += "SIGNATURE(hex): "+ DataUtils.toHex(co.signature.signature);
3905
3906 output+= "<br />";
3907 output+= "<br />";
3908 }
3909 if(co.signedInfo !=null && co.signedInfo.publisher!=null && co.signedInfo.publisher.publisherPublicKeyDigest!=null){
3910 output += "Publisher Public Key Digest(hex): "+ DataUtils.toHex(co.signedInfo.publisher.publisherPublicKeyDigest);
3911
3912 output+= "<br />";
3913 output+= "<br />";
3914 }
3915 if(co.signedInfo !=null && co.signedInfo.timestamp!=null){
3916 var d = new Date();
3917 d.setTime( co.signedInfo.timestamp.msec );
3918
3919 var bytes = [217, 185, 12, 225, 217, 185, 12, 225];
3920
3921 output += "TimeStamp: "+d;
3922 output+= "<br />";
3923 output += "TimeStamp(number): "+ co.signedInfo.timestamp.msec;
3924
3925 output+= "<br />";
3926 }
3927 if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.certificate!=null){
3928 var tmp = DataUtils.toString(co.signedInfo.locator.certificate);
3929 var publickey = rstr2b64(tmp);
3930 var publickeyHex = DataUtils.toHex(co.signedInfo.locator.certificate).toLowerCase();
3931 var publickeyString = DataUtils.toString(co.signedInfo.locator.certificate);
3932 var signature = DataUtils.toHex(co.signature.signature).toLowerCase();
3933 var input = DataUtils.toString(co.rawSignatureData);
3934
3935 output += "DER Certificate: "+publickey ;
3936
3937 output+= "<br />";
3938 output+= "<br />";
3939
3940 if(LOG>2) console.log(" ContentName + SignedInfo + Content = "+input);
3941
3942 if(LOG>2) console.log("HEX OF ContentName + SignedInfo + Content = ");
3943 if(LOG>2) console.log(DataUtils.stringtoBase64(input));
3944
3945 if(LOG>2) console.log(" PublicKey = "+publickey );
3946 if(LOG>2) console.log(" PublicKeyHex = "+publickeyHex );
3947 if(LOG>2) console.log(" PublicKeyString = "+publickeyString );
3948
3949 if(LOG>2) console.log(" Signature is");
3950 if(LOG>2) console.log( signature );
3951 //if(LOG>2) console.log(" Signature NOW IS" );
3952 //if(LOG>2) console.log(co.signature.signature);
3953
3954 var x509 = new X509();
3955 x509.readCertPEM(publickey);
3956
3957 //x509.readCertPEMWithoutRSAInit(publickey);
3958
3959 var result = x509.subjectPublicKeyRSA.verifyByteArray(co.rawSignatureData, signature);
3960 if(LOG>2) console.log('result is '+result);
3961
3962 var n = x509.subjectPublicKeyRSA.n;
3963 var e = x509.subjectPublicKeyRSA.e;
3964
3965 if(LOG>2) console.log('PUBLIC KEY n after is ');
3966 if(LOG>2) console.log(n);
3967
3968 if(LOG>2) console.log('EXPONENT e after is ');
3969 if(LOG>2) console.log(e);
3970
3971 /*var rsakey = new RSAKey();
3972
3973 var kp = publickeyHex.slice(56,314);
3974
3975 output += "PUBLISHER KEY(hex): "+kp ;
3976
3977 output+= "<br />";
3978 output+= "<br />";
3979
3980 console.log('kp is '+kp);
3981
3982 var exp = publickeyHex.slice(318,324);
3983
3984 console.log('kp size is '+kp.length );
3985 output += "exponent: "+exp ;
3986
3987 output+= "<br />";
3988 output+= "<br />";
3989
3990 console.log('exp is '+exp);
3991
3992 rsakey.setPublic(kp,exp);
3993
3994 var result = rsakey.verifyString(input, signature);*/
3995
3996 if(result)
3997 output += 'SIGNATURE VALID';
3998 else
3999 output += 'SIGNATURE INVALID';
4000
4001 //output += "VALID: "+ toHex(co.signedInfo.locator.publicKey);
4002
4003 output+= "<br />";
4004 output+= "<br />";
4005
4006 //if(LOG>4) console.log('str'[1]);
4007 }
4008 if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.publicKey!=null){
4009 var publickey = rstr2b64(DataUtils.toString(co.signedInfo.locator.publicKey));
4010 var publickeyHex = DataUtils.toHex(co.signedInfo.locator.publicKey).toLowerCase();
4011 var publickeyString = DataUtils.toString(co.signedInfo.locator.publicKey);
4012 var signature = DataUtils.toHex(co.signature.signature).toLowerCase();
4013 var input = DataUtils.toString(co.rawSignatureData);
4014
4015 output += "DER Certificate: "+publickey ;
4016
4017 output+= "<br />";
4018 output+= "<br />";
4019
4020 if(LOG>2) console.log(" ContentName + SignedInfo + Content = "+input);
4021 if(LOG>2) console.log(" PublicKey = "+publickey );
4022 if(LOG>2) console.log(" PublicKeyHex = "+publickeyHex );
4023 if(LOG>2) console.log(" PublicKeyString = "+publickeyString );
4024
4025 if(LOG>2) console.log(" Signature "+signature );
4026
4027 if(LOG>2) console.log(" Signature NOW IS" );
4028
4029 if(LOG>2) console.log(co.signature.signature);
4030
4031 /*var x509 = new X509();
4032
4033 x509.readCertPEM(publickey);
4034
4035
4036 //x509.readCertPEMWithoutRSAInit(publickey);
4037
4038 var result = x509.subjectPublicKeyRSA.verifyString(input, signature);*/
4039 //console.log('result is '+result);
4040
4041 var kp = publickeyHex.slice(56,314);
4042
4043 output += "PUBLISHER KEY(hex): "+kp ;
4044
4045 output+= "<br />";
4046 output+= "<br />";
4047
4048 console.log('PUBLIC KEY IN HEX is ');
4049 console.log(kp);
4050
4051 var exp = publickeyHex.slice(318,324);
4052
4053 console.log('kp size is '+kp.length );
4054 output += "exponent: "+exp ;
4055
4056 output+= "<br />";
4057 output+= "<br />";
4058
4059 console.log('EXPONENT is ');
4060 console.log(exp);
4061
4062 /*var c1 = hex_sha256(input);
4063 var c2 = signature;
4064
4065 if(LOG>4)console.log('input is ');
4066 if(LOG>4)console.log(input);
4067 if(LOG>4)console.log('C1 is ');
4068 if(LOG>4)console.log(c1);
4069 if(LOG>4)console.log('C2 is ');
4070 if(LOG>4)console.log(c2);
4071 var result = c1 == c2;*/
4072
4073 var rsakey = new RSAKey();
4074
4075 rsakey.setPublic(kp,exp);
4076
4077 var result = rsakey.verifyByteArray(co.rawSignatureData,signature);
4078 // var result = rsakey.verifyString(input, signature);
4079
4080 console.log('PUBLIC KEY n after is ');
4081 console.log(rsakey.n);
4082
4083 console.log('EXPONENT e after is ');
4084 console.log(rsakey.e);
4085
4086 if(result)
4087 output += 'SIGNATURE VALID';
4088 else
4089 output += 'SIGNATURE INVALID';
4090
4091 //output += "VALID: "+ toHex(co.signedInfo.locator.publicKey);
4092
4093 output+= "<br />";
4094 output+= "<br />";
4095
4096 //if(LOG>4) console.log('str'[1]);
4097 }
4098 }
4099
4100 return output;
4101}
4102
Jeff Thompson745026e2012-10-13 12:49:20 -07004103/*
4104 * @author: ucla-cs
4105 * See COPYING for copyright and distribution information.
4106 */
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07004107
4108var KeyManager = function KeyManager(){
4109
4110
4111//Certificate from CCNx
4112
4113this.certificate = 'MIIBmzCCAQQCCQC32FyQa61S7jANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwd'+
4114
4115'heGVsY2R2MB4XDTEyMDQyODIzNDQzN1oXDTEyMDUyODIzNDQzN1owEjEQMA4GA1'+
4116
4117'UEAxMHYXhlbGNkdjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4X0wp9goq'+
4118
4119'xuECxdULcr2IHr9Ih4Iaypg0Wy39URIup8/CLzQmdsh3RYqd55hqonu5VTTpH3i'+
4120
4121'MLx6xZDVJAZ8OJi7pvXcQ2C4Re2kjL2c8SanI0RfDhlS1zJadfr1VhRPmpivcYa'+
4122
4123'wJ4aFuOLAi+qHFxtN7lhcGCgpW1OV60oXd58CAwEAATANBgkqhkiG9w0BAQUFAA'+
4124
4125'OBgQDLOrA1fXzSrpftUB5Ro6DigX1Bjkf7F5Bkd69hSVp+jYeJFBBlsILQAfSxU'+
4126
4127'ZPQtD+2Yc3iCmSYNyxqu9PcufDRJlnvB7PG29+L3y9lR37tetzUV9eTscJ7rdp8'+
4128
4129'Wt6AzpW32IJ/54yKNfP7S6ZIoIG+LP6EIxq6s8K1MXRt8uBJKw==';
4130
4131
4132//this.publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQAB';
4133this.publicKey ='30819F300D06092A864886F70D010101050003818D0030818902818100E17D30A7D828AB1B840B17542DCAF6207AFD221E086B2A60D16CB7F54448BA9F3F08BCD099DB21DD162A779E61AA89EEE554D3A47DE230BC7AC590D524067C3898BBA6F5DC4360B845EDA48CBD9CF126A723445F0E1952D7325A75FAF556144F9A98AF7186B0278685B8E2C08BEA87171B4DEE585C1828295B5395EB4A17779F0203010001';
4134//Private Key from CCNx
4135
4136this.privateKey ='MIICXQIBAAKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQABAoGAGkv6T6jC3WmhFZYL6CdCWvlc6gysmKrhjarrLTxgavtFY6R5g2ft5BXAsCCVbUkWxkIFSKqxpVNl0gKZCNGEzPDN6mHJOQI/h0rlxNIHAuGfoAbCzALnqmyZivhJAPGijAyKuU9tczsst5+Kpn+bn7ehzHQuj7iwJonS5WbojqECQQD851K8TpW2GrRizNgG4dx6orZxAaon/Jnl8lS7soXhllQty7qG+oDfzznmdMsiznCqEABzHUUKOVGE9RWPN3aRAkEA5D/w9N55d0ibnChFJlc8cUAoaqH+w+U3oQP2Lb6AZHJpLptN4y4b/uf5d4wYU5/i/gC7SSBH3wFhh9bjRLUDLwJAVOx8vN0Kqt7myfKNbCo19jxjVSlA8TKCn1Oznl/BU1I+rC4oUaEW25DjmX6IpAR8kq7S59ThVSCQPjxqY/A08QJBAIRaF2zGPITQk3r/VumemCvLWiRK/yG0noc9dtibqHOWbCtcXtOm/xDWjq+lis2i3ssOvYrvrv0/HcDY+Dv1An0CQQCLJtMsfSg4kvG/FRY5UMhtMuwo8ovYcMXt4Xv/LWaMhndD67b2UGawQCRqr5ghRTABWdDD/HuuMBjrkPsX0861';
4137
4138
4139/*
4140 this.certificate =
4141 'MIIBvTCCASYCCQD55fNzc0WF7TANBgkqhkiG9w0BAQUFADAjMQswCQYDVQQGEwJK'+
4142 'UDEUMBIGA1UEChMLMDAtVEVTVC1SU0EwHhcNMTAwNTI4MDIwODUxWhcNMjAwNTI1'+
4143 'MDIwODUxWjAjMQswCQYDVQQGEwJKUDEUMBIGA1UEChMLMDAtVEVTVC1SU0EwgZ8w'+
4144 'DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANGEYXtfgDRlWUSDn3haY4NVVQiKI9Cz'+
4145 'Thoua9+DxJuiseyzmBBe7Roh1RPqdvmtOHmEPbJ+kXZYhbozzPRbFGHCJyBfCLzQ'+
4146 'fVos9/qUQ88u83b0SFA2MGmQWQAlRtLy66EkR4rDRwTj2DzR4EEXgEKpIvo8VBs/'+
4147 '3+sHLF3ESgAhAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAEZ6mXFFq3AzfaqWHmCy1'+
4148 'ARjlauYAa8ZmUFnLm0emg9dkVBJ63aEqARhtok6bDQDzSJxiLpCEF6G4b/Nv/M/M'+
4149 'LyhP+OoOTmETMegAVQMq71choVJyOFE5BtQa6M/lCHEOya5QUfoRF2HF9EjRF44K'+
4150 '3OK+u3ivTSj3zwjtpudY5Xo=';
4151
4152 this.privateKey =
4153 'MIICWwIBAAKBgQDRhGF7X4A0ZVlEg594WmODVVUIiiPQs04aLmvfg8SborHss5gQ'+
4154 'Xu0aIdUT6nb5rTh5hD2yfpF2WIW6M8z0WxRhwicgXwi80H1aLPf6lEPPLvN29EhQ'+
4155 'NjBpkFkAJUbS8uuhJEeKw0cE49g80eBBF4BCqSL6PFQbP9/rByxdxEoAIQIDAQAB'+
4156 'AoGAA9/q3Zk6ib2GFRpKDLO/O2KMnAfR+b4XJ6zMGeoZ7Lbpi3MW0Nawk9ckVaX0'+
4157 'ZVGqxbSIX5Cvp/yjHHpww+QbUFrw/gCjLiiYjM9E8C3uAF5AKJ0r4GBPl4u8K4bp'+
4158 'bXeSxSB60/wPQFiQAJVcA5xhZVzqNuF3EjuKdHsw+dk+dPECQQDubX/lVGFgD/xY'+
4159 'uchz56Yc7VHX+58BUkNSewSzwJRbcueqknXRWwj97SXqpnYfKqZq78dnEF10SWsr'+
4160 '/NMKi+7XAkEA4PVqDv/OZAbWr4syXZNv/Mpl4r5suzYMMUD9U8B2JIRnrhmGZPzL'+
4161 'x23N9J4hEJ+Xh8tSKVc80jOkrvGlSv+BxwJAaTOtjA3YTV+gU7Hdza53sCnSw/8F'+
4162 'YLrgc6NOJtYhX9xqdevbyn1lkU0zPr8mPYg/F84m6MXixm2iuSz8HZoyzwJARi2p'+
4163 'aYZ5/5B2lwroqnKdZBJMGKFpUDn7Mb5hiSgocxnvMkv6NjT66Xsi3iYakJII9q8C'+
4164 'Ma1qZvT/cigmdbAh7wJAQNXyoizuGEltiSaBXx4H29EdXNYWDJ9SS5f070BRbAIl'+
4165 'dqRh3rcNvpY6BKJqFapda1DjdcncZECMizT/GMrc1w==';
4166
4167 */
4168};
4169
4170
4171KeyManager.prototype.verify = function verify(message,signature){
4172
4173 var input = message;
4174
4175 var _PEM_X509CERT_STRING_ = this.certificate;
4176
4177 var x509 = new X509();
4178
4179 x509.readCertPEM(_PEM_X509CERT_STRING_);
4180
4181 var result = x509.subjectPublicKeyRSA.verifyString(input, signature);
4182
4183 return result;
4184};
4185
4186KeyManager.prototype.sign= function sign(message){
4187
4188 var input = message;
4189
4190 var _PEM_PRIVATE_KEY_STRING_ = this.privateKey;
4191
4192 var rsa = new RSAKey();
4193
4194 rsa.readPrivateKeyFromPEMString(_PEM_PRIVATE_KEY_STRING_);
4195
4196 var hSig = rsa.signString(input, "sha256");
4197
4198 return hSig;
4199
4200};
4201
4202
4203
4204var globalKeyManager = new KeyManager();
4205//var KeyPair = { "public" : "PUBLIC KEY" , "private" : "PRIVATE KEY" };
4206
4207
4208
4209/*
4210 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
4211 * in FIPS 180-1
4212 * Version 2.2 Copyright Paul Johnston 2000 - 2009.
4213 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
4214 * Distributed under the BSD License
4215 * See http://pajhome.org.uk/crypt/md5 for details.
4216 */
4217
4218/*
4219 * Configurable variables. You may need to tweak these to be compatible with
4220 * the server-side, but the defaults work in most cases.
4221 */
4222var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
4223var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
4224
4225/**
4226 * These are the functions you'll usually want to call
4227 * They take string arguments and return either hex or base-64 encoded strings
4228 */
4229function hex_sha1(s) { return rstr2hex(rstr_sha1(str2rstr_utf8(s))); }
4230function b64_sha1(s) { return rstr2b64(rstr_sha1(str2rstr_utf8(s))); }
4231function any_sha1(s, e) { return rstr2any(rstr_sha1(str2rstr_utf8(s)), e); }
4232function hex_hmac_sha1(k, d)
4233 { return rstr2hex(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); }
4234function b64_hmac_sha1(k, d)
4235 { return rstr2b64(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); }
4236function any_hmac_sha1(k, d, e)
4237 { return rstr2any(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
4238
4239/**
4240 * Perform a simple self-test to see if the VM is working
4241 */
4242function sha1_vm_test()
4243{
4244 return hex_sha1("abc").toLowerCase() == "a9993e364706816aba3e25717850c26c9cd0d89d";
4245}
4246
4247/**
4248 * Calculate the SHA1 of a raw string
4249 */
4250function rstr_sha1(s)
4251{
4252 return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8));
4253}
4254
4255/**
4256 * Calculate the HMAC-SHA1 of a key and some data (raw strings)
4257 */
4258function rstr_hmac_sha1(key, data)
4259{
4260 var bkey = rstr2binb(key);
4261 if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8);
4262
4263 var ipad = Array(16), opad = Array(16);
4264 for(var i = 0; i < 16; i++)
4265 {
4266 ipad[i] = bkey[i] ^ 0x36363636;
4267 opad[i] = bkey[i] ^ 0x5C5C5C5C;
4268 }
4269
4270 var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
4271 return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160));
4272}
4273
4274/**
4275 * Convert a raw string to a hex string
4276 */
4277function rstr2hex(input)
4278{
4279 try { hexcase } catch(e) { hexcase=0; }
4280 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
4281 var output = "";
4282 var x;
4283 for(var i = 0; i < input.length; i++)
4284 {
4285 x = input.charCodeAt(i);
4286 output += hex_tab.charAt((x >>> 4) & 0x0F)
4287 + hex_tab.charAt( x & 0x0F);
4288 }
4289 return output;
4290}
4291
4292/**
4293 * Convert a raw string to a base-64 string
4294 */
4295function rstr2b64(input)
4296{
4297 try { b64pad } catch(e) { b64pad=''; }
4298 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4299 var output = "";
4300 var len = input.length;
4301 for(var i = 0; i < len; i += 3)
4302 {
4303 var triplet = (input.charCodeAt(i) << 16)
4304 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
4305 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
4306 for(var j = 0; j < 4; j++)
4307 {
4308 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
4309 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
4310 }
4311 }
4312 return output;
4313}
4314
4315/**
4316 * Convert a raw string to an arbitrary string encoding
4317 */
4318function rstr2any(input, encoding)
4319{
4320 var divisor = encoding.length;
4321 var remainders = Array();
4322 var i, q, x, quotient;
4323
4324 /* Convert to an array of 16-bit big-endian values, forming the dividend */
4325 var dividend = Array(Math.ceil(input.length / 2));
4326 for(i = 0; i < dividend.length; i++)
4327 {
4328 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
4329 }
4330
4331 /*
4332 * Repeatedly perform a long division. The binary array forms the dividend,
4333 * the length of the encoding is the divisor. Once computed, the quotient
4334 * forms the dividend for the next step. We stop when the dividend is zero.
4335 * All remainders are stored for later use.
4336 */
4337 while(dividend.length > 0)
4338 {
4339 quotient = Array();
4340 x = 0;
4341 for(i = 0; i < dividend.length; i++)
4342 {
4343 x = (x << 16) + dividend[i];
4344 q = Math.floor(x / divisor);
4345 x -= q * divisor;
4346 if(quotient.length > 0 || q > 0)
4347 quotient[quotient.length] = q;
4348 }
4349 remainders[remainders.length] = x;
4350 dividend = quotient;
4351 }
4352
4353 /* Convert the remainders to the output string */
4354 var output = "";
4355 for(i = remainders.length - 1; i >= 0; i--)
4356 output += encoding.charAt(remainders[i]);
4357
4358 /* Append leading zero equivalents */
4359 var full_length = Math.ceil(input.length * 8 /
4360 (Math.log(encoding.length) / Math.log(2)));
4361 for(i = output.length; i < full_length; i++)
4362 output = encoding[0] + output;
4363
4364 return output;
4365}
4366
4367/**
4368 * Encode a string as utf-8.
4369 * For efficiency, this assumes the input is valid utf-16.
4370 */
4371function str2rstr_utf8(input)
4372{
4373 var output = "";
4374 var i = -1;
4375 var x, y;
4376
4377 while(++i < input.length)
4378 {
4379 /* Decode utf-16 surrogate pairs */
4380 x = input.charCodeAt(i);
4381 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
4382 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
4383 {
4384 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
4385 i++;
4386 }
4387
4388 /* Encode output as utf-8 */
4389 if(x <= 0x7F)
4390 output += String.fromCharCode(x);
4391 else if(x <= 0x7FF)
4392 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
4393 0x80 | ( x & 0x3F));
4394 else if(x <= 0xFFFF)
4395 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
4396 0x80 | ((x >>> 6 ) & 0x3F),
4397 0x80 | ( x & 0x3F));
4398 else if(x <= 0x1FFFFF)
4399 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
4400 0x80 | ((x >>> 12) & 0x3F),
4401 0x80 | ((x >>> 6 ) & 0x3F),
4402 0x80 | ( x & 0x3F));
4403 }
4404 return output;
4405}
4406
4407/**
4408 * Encode a string as utf-16
4409 */
4410function str2rstr_utf16le(input)
4411{
4412 var output = "";
4413 for(var i = 0; i < input.length; i++)
4414 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
4415 (input.charCodeAt(i) >>> 8) & 0xFF);
4416 return output;
4417}
4418
4419function str2rstr_utf16be(input)
4420{
4421 var output = "";
4422 for(var i = 0; i < input.length; i++)
4423 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
4424 input.charCodeAt(i) & 0xFF);
4425 return output;
4426}
4427
4428/**
4429 * Convert a raw string to an array of big-endian words
4430 * Characters >255 have their high-byte silently ignored.
4431 */
4432function rstr2binb(input)
4433{
4434 var output = Array(input.length >> 2);
4435 for(var i = 0; i < output.length; i++)
4436 output[i] = 0;
4437 for(var i = 0; i < input.length * 8; i += 8)
4438 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
4439 return output;
4440}
4441
4442/**
4443 * Convert an array of big-endian words to a string
4444 */
4445function binb2rstr(input)
4446{
4447 var output = "";
4448 for(var i = 0; i < input.length * 32; i += 8)
4449 output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
4450 return output;
4451}
4452
4453/**
4454 * Calculate the SHA-1 of an array of big-endian words, and a bit length
4455 */
4456function binb_sha1(x, len)
4457{
4458 /* append padding */
4459 x[len >> 5] |= 0x80 << (24 - len % 32);
4460 x[((len + 64 >> 9) << 4) + 15] = len;
4461
4462 var w = Array(80);
4463 var a = 1732584193;
4464 var b = -271733879;
4465 var c = -1732584194;
4466 var d = 271733878;
4467 var e = -1009589776;
4468
4469 for(var i = 0; i < x.length; i += 16)
4470 {
4471 var olda = a;
4472 var oldb = b;
4473 var oldc = c;
4474 var oldd = d;
4475 var olde = e;
4476
4477 for(var j = 0; j < 80; j++)
4478 {
4479 if(j < 16) w[j] = x[i + j];
4480 else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
4481 var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
4482 safe_add(safe_add(e, w[j]), sha1_kt(j)));
4483 e = d;
4484 d = c;
4485 c = bit_rol(b, 30);
4486 b = a;
4487 a = t;
4488 }
4489
4490 a = safe_add(a, olda);
4491 b = safe_add(b, oldb);
4492 c = safe_add(c, oldc);
4493 d = safe_add(d, oldd);
4494 e = safe_add(e, olde);
4495 }
4496 return Array(a, b, c, d, e);
4497
4498}
4499
4500/**
4501 * Perform the appropriate triplet combination function for the current
4502 * iteration
4503 */
4504function sha1_ft(t, b, c, d)
4505{
4506 if(t < 20) return (b & c) | ((~b) & d);
4507 if(t < 40) return b ^ c ^ d;
4508 if(t < 60) return (b & c) | (b & d) | (c & d);
4509 return b ^ c ^ d;
4510}
4511
4512/**
4513 * Determine the appropriate additive constant for the current iteration
4514 */
4515function sha1_kt(t)
4516{
4517 return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
4518 (t < 60) ? -1894007588 : -899497514;
4519}
4520
4521/**
4522 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
4523 * to work around bugs in some JS interpreters.
4524 */
4525function safe_add(x, y)
4526{
4527 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
4528 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
4529 return (msw << 16) | (lsw & 0xFFFF);
4530}
4531
4532/**
4533 * Bitwise rotate a 32-bit number to the left.
4534 */
4535function bit_rol(num, cnt)
4536{
4537 return (num << cnt) | (num >>> (32 - cnt));
4538}
4539
4540/*
4541 * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
4542 * in FIPS 180-2
4543 * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
4544 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
4545 * Distributed under the BSD License
4546 * See http://pajhome.org.uk/crypt/md5 for details.
4547 * Also http://anmar.eu.org/projects/jssha2/
4548 */
4549
4550/*
4551 * Configurable variables. You may need to tweak these to be compatible with
4552 * the server-side, but the defaults work in most cases.
4553 */
4554var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
4555var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
4556
4557/*
4558 * These are the functions you'll usually want to call
4559 * They take string arguments and return either hex or base-64 encoded strings
4560 */
4561
4562//@author axelcdv
4563/**
4564 * Computes the Sha-256 hash of the given byte array
4565 * @param {byte[]}
4566 * @return the hex string corresponding to the Sha-256 hash of the byte array
4567 */
4568function hex_sha256_from_bytes(byteArray){
4569 return rstr2hex(binb2rstr(binb_sha256( byteArray2binb(byteArray), byteArray.length * 8)));
4570}
4571
4572function hex_sha256(s) { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); }
4573function b64_sha256(s) { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); }
4574function any_sha256(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); }
4575function hex_hmac_sha256(k, d)
4576 { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
4577function b64_hmac_sha256(k, d)
4578 { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
4579function any_hmac_sha256(k, d, e)
4580 { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
4581
4582
4583/*
4584 function hex_sha256(s) { return rstr2hex(rstr_sha256(s)); }
4585function b64_sha256(s) { return rstr2b64(rstr_sha256(s)); }
4586function any_sha256(s, e) { return rstr2any(rstr_sha256(s), e); }
4587function hex_hmac_sha256(k, d)
4588 { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), d)); }
4589function b64_hmac_sha256(k, d)
4590 { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), d)); }
4591function any_hmac_sha256(k, d, e)
4592 { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), d), e); }
4593*/
4594
4595/*
4596 * Perform a simple self-test to see if the VM is working
4597 */
4598function sha256_vm_test()
4599{
4600 return hex_sha256("abc").toLowerCase() ==
4601 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
4602}
4603
4604/**
4605 * Calculate the sha256 of a raw string
4606 * @param s: the raw string
4607 */
4608function rstr_sha256(s)
4609{
4610 return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8));
4611}
4612
4613/**
4614 * Calculate the HMAC-sha256 of a key and some data (raw strings)
4615 */
4616function rstr_hmac_sha256(key, data)
4617{
4618 var bkey = rstr2binb(key);
4619 if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8);
4620
4621 var ipad = Array(16), opad = Array(16);
4622 for(var i = 0; i < 16; i++)
4623 {
4624 ipad[i] = bkey[i] ^ 0x36363636;
4625 opad[i] = bkey[i] ^ 0x5C5C5C5C;
4626 }
4627
4628 var hash = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
4629 return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256));
4630}
4631
4632/**
4633 * Convert a raw string to a hex string
4634 */
4635function rstr2hex(input)
4636{
4637 try { hexcase } catch(e) { hexcase=0; }
4638 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
4639 var output = "";
4640 var x;
4641 for(var i = 0; i < input.length; i++)
4642 {
4643 x = input.charCodeAt(i);
4644 output += hex_tab.charAt((x >>> 4) & 0x0F)
4645 + hex_tab.charAt( x & 0x0F);
4646 }
4647 return output;
4648}
4649
4650/*
4651 * Convert a raw string to a base-64 string
4652 */
4653function rstr2b64(input)
4654{
4655 try { b64pad } catch(e) { b64pad=''; }
4656 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4657 var output = "";
4658 var len = input.length;
4659 for(var i = 0; i < len; i += 3)
4660 {
4661 var triplet = (input.charCodeAt(i) << 16)
4662 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
4663 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
4664 for(var j = 0; j < 4; j++)
4665 {
4666 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
4667 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
4668 }
4669 }
4670 return output;
4671}
4672
4673/*
4674 * Convert a raw string to an arbitrary string encoding
4675 */
4676function rstr2any(input, encoding)
4677{
4678 var divisor = encoding.length;
4679 var remainders = Array();
4680 var i, q, x, quotient;
4681
4682 /* Convert to an array of 16-bit big-endian values, forming the dividend */
4683 var dividend = Array(Math.ceil(input.length / 2));
4684 for(i = 0; i < dividend.length; i++)
4685 {
4686 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
4687 }
4688
4689 /*
4690 * Repeatedly perform a long division. The binary array forms the dividend,
4691 * the length of the encoding is the divisor. Once computed, the quotient
4692 * forms the dividend for the next step. We stop when the dividend is zero.
4693 * All remainders are stored for later use.
4694 */
4695 while(dividend.length > 0)
4696 {
4697 quotient = Array();
4698 x = 0;
4699 for(i = 0; i < dividend.length; i++)
4700 {
4701 x = (x << 16) + dividend[i];
4702 q = Math.floor(x / divisor);
4703 x -= q * divisor;
4704 if(quotient.length > 0 || q > 0)
4705 quotient[quotient.length] = q;
4706 }
4707 remainders[remainders.length] = x;
4708 dividend = quotient;
4709 }
4710
4711 /* Convert the remainders to the output string */
4712 var output = "";
4713 for(i = remainders.length - 1; i >= 0; i--)
4714 output += encoding.charAt(remainders[i]);
4715
4716 /* Append leading zero equivalents */
4717 var full_length = Math.ceil(input.length * 8 /
4718 (Math.log(encoding.length) / Math.log(2)))
4719 for(i = output.length; i < full_length; i++)
4720 output = encoding[0] + output;
4721
4722 return output;
4723}
4724
4725/*
4726 * Encode a string as utf-8.
4727 * For efficiency, this assumes the input is valid utf-16.
4728 */
4729function str2rstr_utf8(input)
4730{
4731 var output = "";
4732 var i = -1;
4733 var x, y;
4734
4735 while(++i < input.length)
4736 {
4737 /* Decode utf-16 surrogate pairs */
4738 x = input.charCodeAt(i);
4739 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
4740 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
4741 {
4742 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
4743 i++;
4744 }
4745
4746 /* Encode output as utf-8 */
4747 if(x <= 0x7F)
4748 output += String.fromCharCode(x);
4749 else if(x <= 0x7FF)
4750 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
4751 0x80 | ( x & 0x3F));
4752 else if(x <= 0xFFFF)
4753 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
4754 0x80 | ((x >>> 6 ) & 0x3F),
4755 0x80 | ( x & 0x3F));
4756 else if(x <= 0x1FFFFF)
4757 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
4758 0x80 | ((x >>> 12) & 0x3F),
4759 0x80 | ((x >>> 6 ) & 0x3F),
4760 0x80 | ( x & 0x3F));
4761 }
4762 return output;
4763}
4764
4765/*
4766 * Encode a string as utf-16
4767 */
4768function str2rstr_utf16le(input)
4769{
4770 var output = "";
4771 for(var i = 0; i < input.length; i++)
4772 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
4773 (input.charCodeAt(i) >>> 8) & 0xFF);
4774 return output;
4775}
4776
4777function str2rstr_utf16be(input)
4778{
4779 var output = "";
4780 for(var i = 0; i < input.length; i++)
4781 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
4782 input.charCodeAt(i) & 0xFF);
4783 return output;
4784}
4785
4786/**
4787 * Convert a raw string to an array of big-endian words
4788 * Characters >255 have their high-byte silently ignored.
4789 */
4790function rstr2binb(input)
4791{
4792 console.log('Raw string comming is '+input);
4793 var output = Array(input.length >> 2);
4794 for(var i = 0; i < output.length; i++)
4795 output[i] = 0;
4796 for(var i = 0; i < input.length * 8; i += 8)
4797 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
4798 return output;
4799}
4800
4801/**
4802 * @author axelcdv
4803 * Convert a byte array to an array of big-endian words
4804 * @param {byte[]} input
4805 * @return the array of big-endian words
4806 */
4807function byteArray2binb(input){
4808 console.log("Byte array coming is " + input);
4809 var output = Array(input.length >> 2);
4810 for(var i = 0; i < output.length; i++)
4811 output[i] = 0;
4812 for(var i = 0; i < input.length * 8; i += 8)
4813 output[i>>5] |= (input[i / 8] & 0xFF) << (24 - i % 32);
4814 return output;
4815}
4816
4817/*
4818 * Convert an array of big-endian words to a string
4819 */
4820function binb2rstr(input)
4821{
4822 var output = "";
4823 for(var i = 0; i < input.length * 32; i += 8)
4824 output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
4825 return output;
4826}
4827
4828/*
4829 * Main sha256 function, with its support functions
4830 */
4831function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
4832function sha256_R (X, n) {return ( X >>> n );}
4833function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
4834function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
4835function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
4836function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
4837function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
4838function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
4839function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
4840function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
4841function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
4842function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
4843
4844var sha256_K = new Array
4845(
4846 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,
4847 -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
4848 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
4849 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,
4850 -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
4851 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
4852 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,
4853 -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
4854 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
4855 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,
4856 -1866530822, -1538233109, -1090935817, -965641998
4857);
4858
4859function binb_sha256(m, l)
4860{
4861 var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534,
4862 1359893119, -1694144372, 528734635, 1541459225);
4863 var W = new Array(64);
4864 var a, b, c, d, e, f, g, h;
4865 var i, j, T1, T2;
4866
4867 /* append padding */
4868 m[l >> 5] |= 0x80 << (24 - l % 32);
4869 m[((l + 64 >> 9) << 4) + 15] = l;
4870
4871 for(i = 0; i < m.length; i += 16)
4872 {
4873 a = HASH[0];
4874 b = HASH[1];
4875 c = HASH[2];
4876 d = HASH[3];
4877 e = HASH[4];
4878 f = HASH[5];
4879 g = HASH[6];
4880 h = HASH[7];
4881
4882 for(j = 0; j < 64; j++)
4883 {
4884 if (j < 16) W[j] = m[j + i];
4885 else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
4886 sha256_Gamma0256(W[j - 15])), W[j - 16]);
4887
4888 T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
4889 sha256_K[j]), W[j]);
4890 T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
4891 h = g;
4892 g = f;
4893 f = e;
4894 e = safe_add(d, T1);
4895 d = c;
4896 c = b;
4897 b = a;
4898 a = safe_add(T1, T2);
4899 }
4900
4901 HASH[0] = safe_add(a, HASH[0]);
4902 HASH[1] = safe_add(b, HASH[1]);
4903 HASH[2] = safe_add(c, HASH[2]);
4904 HASH[3] = safe_add(d, HASH[3]);
4905 HASH[4] = safe_add(e, HASH[4]);
4906 HASH[5] = safe_add(f, HASH[5]);
4907 HASH[6] = safe_add(g, HASH[6]);
4908 HASH[7] = safe_add(h, HASH[7]);
4909 }
4910 return HASH;
4911}
4912
4913function safe_add (x, y)
4914{
4915 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
4916 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
4917 return (msw << 16) | (lsw & 0xFFFF);
4918}
4919
4920/*
4921 * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined
4922 * in FIPS 180-2
4923 * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
4924 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
4925 * Distributed under the BSD License
4926 * See http://pajhome.org.uk/crypt/md5 for details.
4927 */
4928
4929/*
4930 * Configurable variables. You may need to tweak these to be compatible with
4931 * the server-side, but the defaults work in most cases.
4932 */
4933var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
4934var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
4935
4936/*
4937 * These are the functions you'll usually want to call
4938 * They take string arguments and return either hex or base-64 encoded strings
4939 */
4940function hex_sha512(s) { return rstr2hex(rstr_sha512(str2rstr_utf8(s))); }
4941function b64_sha512(s) { return rstr2b64(rstr_sha512(str2rstr_utf8(s))); }
4942function any_sha512(s, e) { return rstr2any(rstr_sha512(str2rstr_utf8(s)), e);}
4943function hex_hmac_sha512(k, d)
4944 { return rstr2hex(rstr_hmac_sha512(str2rstr_utf8(k), str2rstr_utf8(d))); }
4945function b64_hmac_sha512(k, d)
4946 { return rstr2b64(rstr_hmac_sha512(str2rstr_utf8(k), str2rstr_utf8(d))); }
4947function any_hmac_sha512(k, d, e)
4948 { return rstr2any(rstr_hmac_sha512(str2rstr_utf8(k), str2rstr_utf8(d)), e);}
4949
4950/*
4951 * Perform a simple self-test to see if the VM is working
4952 */
4953function sha512_vm_test()
4954{
4955 return hex_sha512("abc").toLowerCase() ==
4956 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
4957 "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
4958}
4959
4960/*
4961 * Calculate the SHA-512 of a raw string
4962 */
4963function rstr_sha512(s)
4964{
4965 return binb2rstr(binb_sha512(rstr2binb(s), s.length * 8));
4966}
4967
4968/*
4969 * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
4970 */
4971function rstr_hmac_sha512(key, data)
4972{
4973 var bkey = rstr2binb(key);
4974 if(bkey.length > 32) bkey = binb_sha512(bkey, key.length * 8);
4975
4976 var ipad = Array(32), opad = Array(32);
4977 for(var i = 0; i < 32; i++)
4978 {
4979 ipad[i] = bkey[i] ^ 0x36363636;
4980 opad[i] = bkey[i] ^ 0x5C5C5C5C;
4981 }
4982
4983 var hash = binb_sha512(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
4984 return binb2rstr(binb_sha512(opad.concat(hash), 1024 + 512));
4985}
4986
4987/*
4988 * Convert a raw string to a hex string
4989 */
4990function rstr2hex(input)
4991{
4992 try { hexcase } catch(e) { hexcase=0; }
4993 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
4994 var output = "";
4995 var x;
4996 for(var i = 0; i < input.length; i++)
4997 {
4998 x = input.charCodeAt(i);
4999 output += hex_tab.charAt((x >>> 4) & 0x0F)
5000 + hex_tab.charAt( x & 0x0F);
5001 }
5002 return output;
5003}
5004
5005/*
5006 * Convert a raw string to a base-64 string
5007 */
5008function rstr2b64(input)
5009{
5010 try { b64pad } catch(e) { b64pad=''; }
5011 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5012 var output = "";
5013 var len = input.length;
5014 for(var i = 0; i < len; i += 3)
5015 {
5016 var triplet = (input.charCodeAt(i) << 16)
5017 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
5018 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
5019 for(var j = 0; j < 4; j++)
5020 {
5021 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
5022 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
5023 }
5024 }
5025 return output;
5026}
5027
5028/*
5029 * Convert a raw string to an arbitrary string encoding
5030 */
5031function rstr2any(input, encoding)
5032{
5033 var divisor = encoding.length;
5034 var i, j, q, x, quotient;
5035
5036 /* Convert to an array of 16-bit big-endian values, forming the dividend */
5037 var dividend = Array(Math.ceil(input.length / 2));
5038 for(i = 0; i < dividend.length; i++)
5039 {
5040 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
5041 }
5042
5043 /*
5044 * Repeatedly perform a long division. The binary array forms the dividend,
5045 * the length of the encoding is the divisor. Once computed, the quotient
5046 * forms the dividend for the next step. All remainders are stored for later
5047 * use.
5048 */
5049 var full_length = Math.ceil(input.length * 8 /
5050 (Math.log(encoding.length) / Math.log(2)));
5051 var remainders = Array(full_length);
5052 for(j = 0; j < full_length; j++)
5053 {
5054 quotient = Array();
5055 x = 0;
5056 for(i = 0; i < dividend.length; i++)
5057 {
5058 x = (x << 16) + dividend[i];
5059 q = Math.floor(x / divisor);
5060 x -= q * divisor;
5061 if(quotient.length > 0 || q > 0)
5062 quotient[quotient.length] = q;
5063 }
5064 remainders[j] = x;
5065 dividend = quotient;
5066 }
5067
5068 /* Convert the remainders to the output string */
5069 var output = "";
5070 for(i = remainders.length - 1; i >= 0; i--)
5071 output += encoding.charAt(remainders[i]);
5072
5073 return output;
5074}
5075
5076/*
5077 * Encode a string as utf-8.
5078 * For efficiency, this assumes the input is valid utf-16.
5079 */
5080function str2rstr_utf8(input)
5081{
5082 var output = "";
5083 var i = -1;
5084 var x, y;
5085
5086 while(++i < input.length)
5087 {
5088 /* Decode utf-16 surrogate pairs */
5089 x = input.charCodeAt(i);
5090 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
5091 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
5092 {
5093 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
5094 i++;
5095 }
5096
5097 /* Encode output as utf-8 */
5098 if(x <= 0x7F)
5099 output += String.fromCharCode(x);
5100 else if(x <= 0x7FF)
5101 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
5102 0x80 | ( x & 0x3F));
5103 else if(x <= 0xFFFF)
5104 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
5105 0x80 | ((x >>> 6 ) & 0x3F),
5106 0x80 | ( x & 0x3F));
5107 else if(x <= 0x1FFFFF)
5108 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
5109 0x80 | ((x >>> 12) & 0x3F),
5110 0x80 | ((x >>> 6 ) & 0x3F),
5111 0x80 | ( x & 0x3F));
5112 }
5113 return output;
5114}
5115
5116/*
5117 * Encode a string as utf-16
5118 */
5119function str2rstr_utf16le(input)
5120{
5121 var output = "";
5122 for(var i = 0; i < input.length; i++)
5123 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
5124 (input.charCodeAt(i) >>> 8) & 0xFF);
5125 return output;
5126}
5127
5128function str2rstr_utf16be(input)
5129{
5130 var output = "";
5131 for(var i = 0; i < input.length; i++)
5132 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
5133 input.charCodeAt(i) & 0xFF);
5134 return output;
5135}
5136
5137/*
5138 * Convert a raw string to an array of big-endian words
5139 * Characters >255 have their high-byte silently ignored.
5140 */
5141function rstr2binb(input)
5142{
5143 var output = Array(input.length >> 2);
5144 for(var i = 0; i < output.length; i++)
5145 output[i] = 0;
5146 for(var i = 0; i < input.length * 8; i += 8)
5147 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
5148 return output;
5149}
5150
5151/*
5152 * Convert an array of big-endian words to a string
5153 */
5154function binb2rstr(input)
5155{
5156 var output = "";
5157 for(var i = 0; i < input.length * 32; i += 8)
5158 output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
5159 return output;
5160}
5161
5162/*
5163 * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
5164 */
5165var sha512_k;
5166function binb_sha512(x, len)
5167{
5168 if(sha512_k == undefined)
5169 {
5170 //SHA512 constants
5171 sha512_k = new Array(
5172new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
5173new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
5174new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
5175new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
5176new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
5177new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
5178new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
5179new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
5180new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
5181new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
5182new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
5183new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
5184new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
5185new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
5186new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
5187new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
5188new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
5189new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
5190new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
5191new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
5192new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
5193new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
5194new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
5195new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
5196new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
5197new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
5198new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
5199new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
5200new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
5201new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
5202new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
5203new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
5204new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
5205new int64(-354779690, -840897762), new int64(-176337025, -294727304),
5206new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
5207new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
5208new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
5209new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
5210new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
5211new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817));
5212 }
5213
5214 //Initial hash values
5215 var H = new Array(
5216new int64(0x6a09e667, -205731576),
5217new int64(-1150833019, -2067093701),
5218new int64(0x3c6ef372, -23791573),
5219new int64(-1521486534, 0x5f1d36f1),
5220new int64(0x510e527f, -1377402159),
5221new int64(-1694144372, 0x2b3e6c1f),
5222new int64(0x1f83d9ab, -79577749),
5223new int64(0x5be0cd19, 0x137e2179));
5224
5225 var T1 = new int64(0, 0),
5226 T2 = new int64(0, 0),
5227 a = new int64(0,0),
5228 b = new int64(0,0),
5229 c = new int64(0,0),
5230 d = new int64(0,0),
5231 e = new int64(0,0),
5232 f = new int64(0,0),
5233 g = new int64(0,0),
5234 h = new int64(0,0),
5235 //Temporary variables not specified by the document
5236 s0 = new int64(0, 0),
5237 s1 = new int64(0, 0),
5238 Ch = new int64(0, 0),
5239 Maj = new int64(0, 0),
5240 r1 = new int64(0, 0),
5241 r2 = new int64(0, 0),
5242 r3 = new int64(0, 0);
5243 var j, i;
5244 var W = new Array(80);
5245 for(i=0; i<80; i++)
5246 W[i] = new int64(0, 0);
5247
5248 // append padding to the source string. The format is described in the FIPS.
5249 x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
5250 x[((len + 128 >> 10)<< 5) + 31] = len;
5251
5252 for(i = 0; i<x.length; i+=32) //32 dwords is the block size
5253 {
5254 int64copy(a, H[0]);
5255 int64copy(b, H[1]);
5256 int64copy(c, H[2]);
5257 int64copy(d, H[3]);
5258 int64copy(e, H[4]);
5259 int64copy(f, H[5]);
5260 int64copy(g, H[6]);
5261 int64copy(h, H[7]);
5262
5263 for(j=0; j<16; j++)
5264 {
5265 W[j].h = x[i + 2*j];
5266 W[j].l = x[i + 2*j + 1];
5267 }
5268
5269 for(j=16; j<80; j++)
5270 {
5271 //sigma1
5272 int64rrot(r1, W[j-2], 19);
5273 int64revrrot(r2, W[j-2], 29);
5274 int64shr(r3, W[j-2], 6);
5275 s1.l = r1.l ^ r2.l ^ r3.l;
5276 s1.h = r1.h ^ r2.h ^ r3.h;
5277 //sigma0
5278 int64rrot(r1, W[j-15], 1);
5279 int64rrot(r2, W[j-15], 8);
5280 int64shr(r3, W[j-15], 7);
5281 s0.l = r1.l ^ r2.l ^ r3.l;
5282 s0.h = r1.h ^ r2.h ^ r3.h;
5283
5284 int64add4(W[j], s1, W[j-7], s0, W[j-16]);
5285 }
5286
5287 for(j = 0; j < 80; j++)
5288 {
5289 //Ch
5290 Ch.l = (e.l & f.l) ^ (~e.l & g.l);
5291 Ch.h = (e.h & f.h) ^ (~e.h & g.h);
5292
5293 //Sigma1
5294 int64rrot(r1, e, 14);
5295 int64rrot(r2, e, 18);
5296 int64revrrot(r3, e, 9);
5297 s1.l = r1.l ^ r2.l ^ r3.l;
5298 s1.h = r1.h ^ r2.h ^ r3.h;
5299
5300 //Sigma0
5301 int64rrot(r1, a, 28);
5302 int64revrrot(r2, a, 2);
5303 int64revrrot(r3, a, 7);
5304 s0.l = r1.l ^ r2.l ^ r3.l;
5305 s0.h = r1.h ^ r2.h ^ r3.h;
5306
5307 //Maj
5308 Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
5309 Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
5310
5311 int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
5312 int64add(T2, s0, Maj);
5313
5314 int64copy(h, g);
5315 int64copy(g, f);
5316 int64copy(f, e);
5317 int64add(e, d, T1);
5318 int64copy(d, c);
5319 int64copy(c, b);
5320 int64copy(b, a);
5321 int64add(a, T1, T2);
5322 }
5323 int64add(H[0], H[0], a);
5324 int64add(H[1], H[1], b);
5325 int64add(H[2], H[2], c);
5326 int64add(H[3], H[3], d);
5327 int64add(H[4], H[4], e);
5328 int64add(H[5], H[5], f);
5329 int64add(H[6], H[6], g);
5330 int64add(H[7], H[7], h);
5331 }
5332
5333 //represent the hash as an array of 32-bit dwords
5334 var hash = new Array(16);
5335 for(i=0; i<8; i++)
5336 {
5337 hash[2*i] = H[i].h;
5338 hash[2*i + 1] = H[i].l;
5339 }
5340 return hash;
5341}
5342
5343//A constructor for 64-bit numbers
5344function int64(h, l)
5345{
5346 this.h = h;
5347 this.l = l;
5348 //this.toString = int64toString;
5349}
5350
5351//Copies src into dst, assuming both are 64-bit numbers
5352function int64copy(dst, src)
5353{
5354 dst.h = src.h;
5355 dst.l = src.l;
5356}
5357
5358//Right-rotates a 64-bit number by shift
5359//Won't handle cases of shift>=32
5360//The function revrrot() is for that
5361function int64rrot(dst, x, shift)
5362{
5363 dst.l = (x.l >>> shift) | (x.h << (32-shift));
5364 dst.h = (x.h >>> shift) | (x.l << (32-shift));
5365}
5366
5367//Reverses the dwords of the source and then rotates right by shift.
5368//This is equivalent to rotation by 32+shift
5369function int64revrrot(dst, x, shift)
5370{
5371 dst.l = (x.h >>> shift) | (x.l << (32-shift));
5372 dst.h = (x.l >>> shift) | (x.h << (32-shift));
5373}
5374
5375//Bitwise-shifts right a 64-bit number by shift
5376//Won't handle shift>=32, but it's never needed in SHA512
5377function int64shr(dst, x, shift)
5378{
5379 dst.l = (x.l >>> shift) | (x.h << (32-shift));
5380 dst.h = (x.h >>> shift);
5381}
5382
5383//Adds two 64-bit numbers
5384//Like the original implementation, does not rely on 32-bit operations
5385function int64add(dst, x, y)
5386{
5387 var w0 = (x.l & 0xffff) + (y.l & 0xffff);
5388 var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
5389 var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
5390 var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
5391 dst.l = (w0 & 0xffff) | (w1 << 16);
5392 dst.h = (w2 & 0xffff) | (w3 << 16);
5393}
5394
5395//Same, except with 4 addends. Works faster than adding them one by one.
5396function int64add4(dst, a, b, c, d)
5397{
5398 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
5399 var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
5400 var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
5401 var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
5402 dst.l = (w0 & 0xffff) | (w1 << 16);
5403 dst.h = (w2 & 0xffff) | (w3 << 16);
5404}
5405
5406//Same, except with 5 addends
5407function int64add5(dst, a, b, c, d, e)
5408{
5409 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff);
5410 var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16);
5411 var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16);
5412 var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
5413 dst.l = (w0 & 0xffff) | (w1 << 16);
5414 dst.h = (w2 & 0xffff) | (w3 << 16);
5415}
5416
5417/*
5418 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
5419 * Digest Algorithm, as defined in RFC 1321.
5420 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
5421 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
5422 * Distributed under the BSD License
5423 * See http://pajhome.org.uk/crypt/md5 for more info.
5424 */
5425
5426/*
5427 * Configurable variables. You may need to tweak these to be compatible with
5428 * the server-side, but the defaults work in most cases.
5429 */
5430var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
5431var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
5432
5433/*
5434 * These are the functions you'll usually want to call
5435 * They take string arguments and return either hex or base-64 encoded strings
5436 */
5437function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
5438function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
5439function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
5440function hex_hmac_md5(k, d)
5441 { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
5442function b64_hmac_md5(k, d)
5443 { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
5444function any_hmac_md5(k, d, e)
5445 { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
5446
5447/*
5448 * Perform a simple self-test to see if the VM is working
5449 */
5450function md5_vm_test()
5451{
5452 return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
5453}
5454
5455/*
5456 * Calculate the MD5 of a raw string
5457 */
5458function rstr_md5(s)
5459{
5460 return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
5461}
5462
5463/*
5464 * Calculate the HMAC-MD5, of a key and some data (raw strings)
5465 */
5466function rstr_hmac_md5(key, data)
5467{
5468 var bkey = rstr2binl(key);
5469 if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
5470
5471 var ipad = Array(16), opad = Array(16);
5472 for(var i = 0; i < 16; i++)
5473 {
5474 ipad[i] = bkey[i] ^ 0x36363636;
5475 opad[i] = bkey[i] ^ 0x5C5C5C5C;
5476 }
5477
5478 var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
5479 return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
5480}
5481
5482/*
5483 * Convert a raw string to a hex string
5484 */
5485function rstr2hex(input)
5486{
5487 try { hexcase } catch(e) { hexcase=0; }
5488 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
5489 var output = "";
5490 var x;
5491 for(var i = 0; i < input.length; i++)
5492 {
5493 x = input.charCodeAt(i);
5494 output += hex_tab.charAt((x >>> 4) & 0x0F)
5495 + hex_tab.charAt( x & 0x0F);
5496 }
5497 return output;
5498}
5499
5500/*
5501 * Convert a raw string to a base-64 string
5502 */
5503function rstr2b64(input)
5504{
5505 try { b64pad } catch(e) { b64pad=''; }
5506 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5507 var output = "";
5508 var len = input.length;
5509 for(var i = 0; i < len; i += 3)
5510 {
5511 var triplet = (input.charCodeAt(i) << 16)
5512 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
5513 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
5514 for(var j = 0; j < 4; j++)
5515 {
5516 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
5517 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
5518 }
5519 }
5520 return output;
5521}
5522
5523/*
5524 * Convert a raw string to an arbitrary string encoding
5525 */
5526function rstr2any(input, encoding)
5527{
5528 var divisor = encoding.length;
5529 var i, j, q, x, quotient;
5530
5531 /* Convert to an array of 16-bit big-endian values, forming the dividend */
5532 var dividend = Array(Math.ceil(input.length / 2));
5533 for(i = 0; i < dividend.length; i++)
5534 {
5535 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
5536 }
5537
5538 /*
5539 * Repeatedly perform a long division. The binary array forms the dividend,
5540 * the length of the encoding is the divisor. Once computed, the quotient
5541 * forms the dividend for the next step. All remainders are stored for later
5542 * use.
5543 */
5544 var full_length = Math.ceil(input.length * 8 /
5545 (Math.log(encoding.length) / Math.log(2)));
5546 var remainders = Array(full_length);
5547 for(j = 0; j < full_length; j++)
5548 {
5549 quotient = Array();
5550 x = 0;
5551 for(i = 0; i < dividend.length; i++)
5552 {
5553 x = (x << 16) + dividend[i];
5554 q = Math.floor(x / divisor);
5555 x -= q * divisor;
5556 if(quotient.length > 0 || q > 0)
5557 quotient[quotient.length] = q;
5558 }
5559 remainders[j] = x;
5560 dividend = quotient;
5561 }
5562
5563 /* Convert the remainders to the output string */
5564 var output = "";
5565 for(i = remainders.length - 1; i >= 0; i--)
5566 output += encoding.charAt(remainders[i]);
5567
5568 return output;
5569}
5570
5571/*
5572 * Encode a string as utf-8.
5573 * For efficiency, this assumes the input is valid utf-16.
5574 */
5575function str2rstr_utf8(input)
5576{
5577 var output = "";
5578 var i = -1;
5579 var x, y;
5580
5581 while(++i < input.length)
5582 {
5583 /* Decode utf-16 surrogate pairs */
5584 x = input.charCodeAt(i);
5585 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
5586 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
5587 {
5588 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
5589 i++;
5590 }
5591
5592 /* Encode output as utf-8 */
5593 if(x <= 0x7F)
5594 output += String.fromCharCode(x);
5595 else if(x <= 0x7FF)
5596 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
5597 0x80 | ( x & 0x3F));
5598 else if(x <= 0xFFFF)
5599 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
5600 0x80 | ((x >>> 6 ) & 0x3F),
5601 0x80 | ( x & 0x3F));
5602 else if(x <= 0x1FFFFF)
5603 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
5604 0x80 | ((x >>> 12) & 0x3F),
5605 0x80 | ((x >>> 6 ) & 0x3F),
5606 0x80 | ( x & 0x3F));
5607 }
5608 return output;
5609}
5610
5611/*
5612 * Encode a string as utf-16
5613 */
5614function str2rstr_utf16le(input)
5615{
5616 var output = "";
5617 for(var i = 0; i < input.length; i++)
5618 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
5619 (input.charCodeAt(i) >>> 8) & 0xFF);
5620 return output;
5621}
5622
5623function str2rstr_utf16be(input)
5624{
5625 var output = "";
5626 for(var i = 0; i < input.length; i++)
5627 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
5628 input.charCodeAt(i) & 0xFF);
5629 return output;
5630}
5631
5632/*
5633 * Convert a raw string to an array of little-endian words
5634 * Characters >255 have their high-byte silently ignored.
5635 */
5636function rstr2binl(input)
5637{
5638 var output = Array(input.length >> 2);
5639 for(var i = 0; i < output.length; i++)
5640 output[i] = 0;
5641 for(var i = 0; i < input.length * 8; i += 8)
5642 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
5643 return output;
5644}
5645
5646/*
5647 * Convert an array of little-endian words to a string
5648 */
5649function binl2rstr(input)
5650{
5651 var output = "";
5652 for(var i = 0; i < input.length * 32; i += 8)
5653 output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
5654 return output;
5655}
5656
5657/*
5658 * Calculate the MD5 of an array of little-endian words, and a bit length.
5659 */
5660function binl_md5(x, len)
5661{
5662 /* append padding */
5663 x[len >> 5] |= 0x80 << ((len) % 32);
5664 x[(((len + 64) >>> 9) << 4) + 14] = len;
5665
5666 var a = 1732584193;
5667 var b = -271733879;
5668 var c = -1732584194;
5669 var d = 271733878;
5670
5671 for(var i = 0; i < x.length; i += 16)
5672 {
5673 var olda = a;
5674 var oldb = b;
5675 var oldc = c;
5676 var oldd = d;
5677
5678 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
5679 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
5680 c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
5681 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
5682 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
5683 d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
5684 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
5685 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
5686 a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
5687 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
5688 c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
5689 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
5690 a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
5691 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
5692 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
5693 b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
5694
5695 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
5696 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
5697 c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
5698 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
5699 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
5700 d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
5701 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
5702 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
5703 a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
5704 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
5705 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
5706 b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
5707 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
5708 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
5709 c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
5710 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
5711
5712 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
5713 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
5714 c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
5715 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
5716 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
5717 d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
5718 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
5719 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
5720 a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
5721 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
5722 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
5723 b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
5724 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
5725 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
5726 c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
5727 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
5728
5729 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
5730 d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
5731 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
5732 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
5733 a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
5734 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
5735 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
5736 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
5737 a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
5738 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
5739 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
5740 b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
5741 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
5742 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
5743 c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
5744 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
5745
5746 a = safe_add(a, olda);
5747 b = safe_add(b, oldb);
5748 c = safe_add(c, oldc);
5749 d = safe_add(d, oldd);
5750 }
5751 return Array(a, b, c, d);
5752}
5753
5754/*
5755 * These functions implement the four basic operations the algorithm uses.
5756 */
5757function md5_cmn(q, a, b, x, s, t)
5758{
5759 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
5760}
5761function md5_ff(a, b, c, d, x, s, t)
5762{
5763 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
5764}
5765function md5_gg(a, b, c, d, x, s, t)
5766{
5767 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
5768}
5769function md5_hh(a, b, c, d, x, s, t)
5770{
5771 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
5772}
5773function md5_ii(a, b, c, d, x, s, t)
5774{
5775 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
5776}
5777
5778/*
5779 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
5780 * to work around bugs in some JS interpreters.
5781 */
5782function safe_add(x, y)
5783{
5784 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
5785 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
5786 return (msw << 16) | (lsw & 0xFFFF);
5787}
5788
5789/*
5790 * Bitwise rotate a 32-bit number to the left.
5791 */
5792function bit_rol(num, cnt)
5793{
5794 return (num << cnt) | (num >>> (32 - cnt));
5795}
5796
5797/*
5798 * A JavaScript implementation of the RIPEMD-160 Algorithm
5799 * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
5800 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
5801 * Distributed under the BSD License
5802 * See http://pajhome.org.uk/crypt/md5 for details.
5803 * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
5804 */
5805
5806/*
5807 * Configurable variables. You may need to tweak these to be compatible with
5808 * the server-side, but the defaults work in most cases.
5809 */
5810var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
5811var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
5812
5813/*
5814 * These are the functions you'll usually want to call
5815 * They take string arguments and return either hex or base-64 encoded strings
5816 */
5817function hex_rmd160(s) { return rstr2hex(rstr_rmd160(str2rstr_utf8(s))); }
5818function b64_rmd160(s) { return rstr2b64(rstr_rmd160(str2rstr_utf8(s))); }
5819function any_rmd160(s, e) { return rstr2any(rstr_rmd160(str2rstr_utf8(s)), e); }
5820function hex_hmac_rmd160(k, d)
5821 { return rstr2hex(rstr_hmac_rmd160(str2rstr_utf8(k), str2rstr_utf8(d))); }
5822function b64_hmac_rmd160(k, d)
5823 { return rstr2b64(rstr_hmac_rmd160(str2rstr_utf8(k), str2rstr_utf8(d))); }
5824function any_hmac_rmd160(k, d, e)
5825 { return rstr2any(rstr_hmac_rmd160(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
5826
5827/*
5828 * Perform a simple self-test to see if the VM is working
5829 */
5830function rmd160_vm_test()
5831{
5832 return hex_rmd160("abc").toLowerCase() == "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc";
5833}
5834
5835/*
5836 * Calculate the rmd160 of a raw string
5837 */
5838function rstr_rmd160(s)
5839{
5840 return binl2rstr(binl_rmd160(rstr2binl(s), s.length * 8));
5841}
5842
5843/*
5844 * Calculate the HMAC-rmd160 of a key and some data (raw strings)
5845 */
5846function rstr_hmac_rmd160(key, data)
5847{
5848 var bkey = rstr2binl(key);
5849 if(bkey.length > 16) bkey = binl_rmd160(bkey, key.length * 8);
5850
5851 var ipad = Array(16), opad = Array(16);
5852 for(var i = 0; i < 16; i++)
5853 {
5854 ipad[i] = bkey[i] ^ 0x36363636;
5855 opad[i] = bkey[i] ^ 0x5C5C5C5C;
5856 }
5857
5858 var hash = binl_rmd160(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
5859 return binl2rstr(binl_rmd160(opad.concat(hash), 512 + 160));
5860}
5861
5862/*
5863 * Convert a raw string to a hex string
5864 */
5865function rstr2hex(input)
5866{
5867 try { hexcase } catch(e) { hexcase=0; }
5868 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
5869 var output = "";
5870 var x;
5871 for(var i = 0; i < input.length; i++)
5872 {
5873 x = input.charCodeAt(i);
5874 output += hex_tab.charAt((x >>> 4) & 0x0F)
5875 + hex_tab.charAt( x & 0x0F);
5876 }
5877 return output;
5878}
5879
5880/*
5881 * Convert a raw string to a base-64 string
5882 */
5883function rstr2b64(input)
5884{
5885 try { b64pad } catch(e) { b64pad=''; }
5886 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5887 var output = "";
5888 var len = input.length;
5889 for(var i = 0; i < len; i += 3)
5890 {
5891 var triplet = (input.charCodeAt(i) << 16)
5892 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
5893 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
5894 for(var j = 0; j < 4; j++)
5895 {
5896 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
5897 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
5898 }
5899 }
5900 return output;
5901}
5902
5903/*
5904 * Convert a raw string to an arbitrary string encoding
5905 */
5906function rstr2any(input, encoding)
5907{
5908 var divisor = encoding.length;
5909 var remainders = Array();
5910 var i, q, x, quotient;
5911
5912 /* Convert to an array of 16-bit big-endian values, forming the dividend */
5913 var dividend = Array(Math.ceil(input.length / 2));
5914 for(i = 0; i < dividend.length; i++)
5915 {
5916 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
5917 }
5918
5919 /*
5920 * Repeatedly perform a long division. The binary array forms the dividend,
5921 * the length of the encoding is the divisor. Once computed, the quotient
5922 * forms the dividend for the next step. We stop when the dividend is zero.
5923 * All remainders are stored for later use.
5924 */
5925 while(dividend.length > 0)
5926 {
5927 quotient = Array();
5928 x = 0;
5929 for(i = 0; i < dividend.length; i++)
5930 {
5931 x = (x << 16) + dividend[i];
5932 q = Math.floor(x / divisor);
5933 x -= q * divisor;
5934 if(quotient.length > 0 || q > 0)
5935 quotient[quotient.length] = q;
5936 }
5937 remainders[remainders.length] = x;
5938 dividend = quotient;
5939 }
5940
5941 /* Convert the remainders to the output string */
5942 var output = "";
5943 for(i = remainders.length - 1; i >= 0; i--)
5944 output += encoding.charAt(remainders[i]);
5945
5946 /* Append leading zero equivalents */
5947 var full_length = Math.ceil(input.length * 8 /
5948 (Math.log(encoding.length) / Math.log(2)))
5949 for(i = output.length; i < full_length; i++)
5950 output = encoding[0] + output;
5951
5952 return output;
5953}
5954
5955/*
5956 * Encode a string as utf-8.
5957 * For efficiency, this assumes the input is valid utf-16.
5958 */
5959function str2rstr_utf8(input)
5960{
5961 var output = "";
5962 var i = -1;
5963 var x, y;
5964
5965 while(++i < input.length)
5966 {
5967 /* Decode utf-16 surrogate pairs */
5968 x = input.charCodeAt(i);
5969 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
5970 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
5971 {
5972 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
5973 i++;
5974 }
5975
5976 /* Encode output as utf-8 */
5977 if(x <= 0x7F)
5978 output += String.fromCharCode(x);
5979 else if(x <= 0x7FF)
5980 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
5981 0x80 | ( x & 0x3F));
5982 else if(x <= 0xFFFF)
5983 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
5984 0x80 | ((x >>> 6 ) & 0x3F),
5985 0x80 | ( x & 0x3F));
5986 else if(x <= 0x1FFFFF)
5987 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
5988 0x80 | ((x >>> 12) & 0x3F),
5989 0x80 | ((x >>> 6 ) & 0x3F),
5990 0x80 | ( x & 0x3F));
5991 }
5992 return output;
5993}
5994
5995/*
5996 * Encode a string as utf-16
5997 */
5998function str2rstr_utf16le(input)
5999{
6000 var output = "";
6001 for(var i = 0; i < input.length; i++)
6002 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
6003 (input.charCodeAt(i) >>> 8) & 0xFF);
6004 return output;
6005}
6006
6007function str2rstr_utf16be(input)
6008{
6009 var output = "";
6010 for(var i = 0; i < input.length; i++)
6011 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
6012 input.charCodeAt(i) & 0xFF);
6013 return output;
6014}
6015
6016/*
6017 * Convert a raw string to an array of little-endian words
6018 * Characters >255 have their high-byte silently ignored.
6019 */
6020function rstr2binl(input)
6021{
6022 var output = Array(input.length >> 2);
6023 for(var i = 0; i < output.length; i++)
6024 output[i] = 0;
6025 for(var i = 0; i < input.length * 8; i += 8)
6026 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
6027 return output;
6028}
6029
6030/*
6031 * Convert an array of little-endian words to a string
6032 */
6033function binl2rstr(input)
6034{
6035 var output = "";
6036 for(var i = 0; i < input.length * 32; i += 8)
6037 output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
6038 return output;
6039}
6040
6041/*
6042 * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
6043 */
6044function binl_rmd160(x, len)
6045{
6046 /* append padding */
6047 x[len >> 5] |= 0x80 << (len % 32);
6048 x[(((len + 64) >>> 9) << 4) + 14] = len;
6049
6050 var h0 = 0x67452301;
6051 var h1 = 0xefcdab89;
6052 var h2 = 0x98badcfe;
6053 var h3 = 0x10325476;
6054 var h4 = 0xc3d2e1f0;
6055
6056 for (var i = 0; i < x.length; i += 16) {
6057 var T;
6058 var A1 = h0, B1 = h1, C1 = h2, D1 = h3, E1 = h4;
6059 var A2 = h0, B2 = h1, C2 = h2, D2 = h3, E2 = h4;
6060 for (var j = 0; j <= 79; ++j) {
6061 T = safe_add(A1, rmd160_f(j, B1, C1, D1));
6062 T = safe_add(T, x[i + rmd160_r1[j]]);
6063 T = safe_add(T, rmd160_K1(j));
6064 T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
6065 A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T;
6066 T = safe_add(A2, rmd160_f(79-j, B2, C2, D2));
6067 T = safe_add(T, x[i + rmd160_r2[j]]);
6068 T = safe_add(T, rmd160_K2(j));
6069 T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
6070 A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T;
6071 }
6072 T = safe_add(h1, safe_add(C1, D2));
6073 h1 = safe_add(h2, safe_add(D1, E2));
6074 h2 = safe_add(h3, safe_add(E1, A2));
6075 h3 = safe_add(h4, safe_add(A1, B2));
6076 h4 = safe_add(h0, safe_add(B1, C2));
6077 h0 = T;
6078 }
6079 return [h0, h1, h2, h3, h4];
6080}
6081
6082function rmd160_f(j, x, y, z)
6083{
6084 return ( 0 <= j && j <= 15) ? (x ^ y ^ z) :
6085 (16 <= j && j <= 31) ? (x & y) | (~x & z) :
6086 (32 <= j && j <= 47) ? (x | ~y) ^ z :
6087 (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
6088 (64 <= j && j <= 79) ? x ^ (y | ~z) :
6089 "rmd160_f: j out of range";
6090}
6091function rmd160_K1(j)
6092{
6093 return ( 0 <= j && j <= 15) ? 0x00000000 :
6094 (16 <= j && j <= 31) ? 0x5a827999 :
6095 (32 <= j && j <= 47) ? 0x6ed9eba1 :
6096 (48 <= j && j <= 63) ? 0x8f1bbcdc :
6097 (64 <= j && j <= 79) ? 0xa953fd4e :
6098 "rmd160_K1: j out of range";
6099}
6100function rmd160_K2(j)
6101{
6102 return ( 0 <= j && j <= 15) ? 0x50a28be6 :
6103 (16 <= j && j <= 31) ? 0x5c4dd124 :
6104 (32 <= j && j <= 47) ? 0x6d703ef3 :
6105 (48 <= j && j <= 63) ? 0x7a6d76e9 :
6106 (64 <= j && j <= 79) ? 0x00000000 :
6107 "rmd160_K2: j out of range";
6108}
6109var rmd160_r1 = [
6110 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
6111 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
6112 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
6113 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
6114 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
6115];
6116var rmd160_r2 = [
6117 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6118 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
6119 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
6120 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
6121 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
6122];
6123var rmd160_s1 = [
6124 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
6125 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
6126 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
6127 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
6128 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
6129];
6130var rmd160_s2 = [
6131 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
6132 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
6133 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
6134 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
6135 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
6136];
6137
6138/*
6139 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
6140 * to work around bugs in some JS interpreters.
6141 */
6142function safe_add(x, y)
6143{
6144 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
6145 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
6146 return (msw << 16) | (lsw & 0xFFFF);
6147}
6148
6149/*
6150 * Bitwise rotate a 32-bit number to the left.
6151 */
6152function bit_rol(num, cnt)
6153{
6154 return (num << cnt) | (num >>> (32 - cnt));
6155}
6156
6157var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6158var b64pad="=";
6159
6160function hex2b64(h) {
6161 var i;
6162 var c;
6163 var ret = "";
6164 for(i = 0; i+3 <= h.length; i+=3) {
6165 c = parseInt(h.substring(i,i+3),16);
6166 ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
6167 }
6168 if(i+1 == h.length) {
6169 c = parseInt(h.substring(i,i+1),16);
6170 ret += b64map.charAt(c << 2);
6171 }
6172 else if(i+2 == h.length) {
6173 c = parseInt(h.substring(i,i+2),16);
6174 ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
6175 }
6176 while((ret.length & 3) > 0) ret += b64pad;
6177 return ret;
6178}
6179
6180// convert a base64 string to hex
6181function b64tohex(s) {
6182 var ret = ""
6183 var i;
6184 var k = 0; // b64 state, 0-3
6185 var slop;
6186 for(i = 0; i < s.length; ++i) {
6187 if(s.charAt(i) == b64pad) break;
6188 v = b64map.indexOf(s.charAt(i));
6189 if(v < 0) continue;
6190 if(k == 0) {
6191 ret += int2char(v >> 2);
6192 slop = v & 3;
6193 k = 1;
6194 }
6195 else if(k == 1) {
6196 ret += int2char((slop << 2) | (v >> 4));
6197 slop = v & 0xf;
6198 k = 2;
6199 }
6200 else if(k == 2) {
6201 ret += int2char(slop);
6202 ret += int2char(v >> 2);
6203 slop = v & 3;
6204 k = 3;
6205 }
6206 else {
6207 ret += int2char((slop << 2) | (v >> 4));
6208 ret += int2char(v & 0xf);
6209 k = 0;
6210 }
6211 }
6212 if(k == 1)
6213 ret += int2char(slop << 2);
6214 return ret;
6215}
6216
6217// convert a base64 string to a byte/number array
6218function b64toBA(s) {
6219 //piggyback on b64tohex for now, optimize later
6220 var h = b64tohex(s);
6221 var i;
6222 var a = new Array();
6223 for(i = 0; 2*i < h.length; ++i) {
6224 a[i] = parseInt(h.substring(2*i,2*i+2),16);
6225 }
6226 return a;
6227}
6228
6229// Depends on jsbn.js and rng.js
6230
6231// Version 1.1: support utf-8 encoding in pkcs1pad2
6232
6233// convert a (hex) string to a bignum object
6234function parseBigInt(str,r) {
6235 return new BigInteger(str,r);
6236}
6237
6238function linebrk(s,n) {
6239 var ret = "";
6240 var i = 0;
6241 while(i + n < s.length) {
6242 ret += s.substring(i,i+n) + "\n";
6243 i += n;
6244 }
6245 return ret + s.substring(i,s.length);
6246}
6247
6248function byte2Hex(b) {
6249 if(b < 0x10)
6250 return "0" + b.toString(16);
6251 else
6252 return b.toString(16);
6253}
6254
6255/**
6256 * PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
6257 * @param s: the string to encode
6258 * @param n: the size in byte
6259 */
6260function pkcs1pad2(s,n) {
6261 if(n < s.length + 11) { // TODO: fix for utf-8
6262 alert("Message too long for RSA");
6263 return null;
6264 }
6265 var ba = new Array();
6266 var i = s.length - 1;
6267 while(i >= 0 && n > 0) {
6268 var c = s.charCodeAt(i--);
6269 if(c < 128) { // encode using utf-8
6270 ba[--n] = c;
6271 }
6272 else if((c > 127) && (c < 2048)) {
6273 ba[--n] = (c & 63) | 128;
6274 ba[--n] = (c >> 6) | 192;
6275 }
6276 else {
6277 ba[--n] = (c & 63) | 128;
6278 ba[--n] = ((c >> 6) & 63) | 128;
6279 ba[--n] = (c >> 12) | 224;
6280 }
6281 }
6282 ba[--n] = 0;
6283 var rng = new SecureRandom();
6284 var x = new Array();
6285 while(n > 2) { // random non-zero pad
6286 x[0] = 0;
6287 while(x[0] == 0) rng.nextBytes(x);
6288 ba[--n] = x[0];
6289 }
6290 ba[--n] = 2;
6291 ba[--n] = 0;
6292 return new BigInteger(ba);
6293}
6294
6295/**
6296 * "empty" RSA key constructor
6297 * @returns {RSAKey}
6298 */
6299function RSAKey() {
6300 this.n = null;
6301 this.e = 0;
6302 this.d = null;
6303 this.p = null;
6304 this.q = null;
6305 this.dmp1 = null;
6306 this.dmq1 = null;
6307 this.coeff = null;
6308}
6309
6310/**
6311 * Set the public key fields N and e from hex strings
6312 * @param N
6313 * @param E
6314 * @returns {RSASetPublic}
6315 */
6316function RSASetPublic(N,E) {
6317 if(N != null && E != null && N.length > 0 && E.length > 0) {
6318 this.n = parseBigInt(N,16);
6319 this.e = parseInt(E,16);
6320 }
6321 else
6322 alert("Invalid RSA public key");
6323}
6324
6325/**
6326 * Perform raw public operation on "x": return x^e (mod n)
6327 * @param x
6328 * @returns x^e (mod n)
6329 */
6330function RSADoPublic(x) {
6331 return x.modPowInt(this.e, this.n);
6332}
6333
6334/**
6335 * Return the PKCS#1 RSA encryption of "text" as an even-length hex string
6336 */
6337function RSAEncrypt(text) {
6338 var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
6339 if(m == null) return null;
6340 var c = this.doPublic(m);
6341 if(c == null) return null;
6342 var h = c.toString(16);
6343 if((h.length & 1) == 0) return h; else return "0" + h;
6344}
6345
6346// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
6347//function RSAEncryptB64(text) {
6348// var h = this.encrypt(text);
6349// if(h) return hex2b64(h); else return null;
6350//}
6351
6352// protected
6353RSAKey.prototype.doPublic = RSADoPublic;
6354
6355// public
6356RSAKey.prototype.setPublic = RSASetPublic;
6357RSAKey.prototype.encrypt = RSAEncrypt;
6358//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
6359
6360// Depends on rsa.js and jsbn2.js
6361
6362// Version 1.1: support utf-8 decoding in pkcs1unpad2
6363
6364// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
6365function pkcs1unpad2(d,n) {
6366 var b = d.toByteArray();
6367 var i = 0;
6368 while(i < b.length && b[i] == 0) ++i;
6369 if(b.length-i != n-1 || b[i] != 2)
6370 return null;
6371 ++i;
6372 while(b[i] != 0)
6373 if(++i >= b.length) return null;
6374 var ret = "";
6375 while(++i < b.length) {
6376 var c = b[i] & 255;
6377 if(c < 128) { // utf-8 decode
6378 ret += String.fromCharCode(c);
6379 }
6380 else if((c > 191) && (c < 224)) {
6381 ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63));
6382 ++i;
6383 }
6384 else {
6385 ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63));
6386 i += 2;
6387 }
6388 }
6389 return ret;
6390}
6391
6392// Set the private key fields N, e, and d from hex strings
6393function RSASetPrivate(N,E,D) {
6394 if(N != null && E != null && N.length > 0 && E.length > 0) {
6395 this.n = parseBigInt(N,16);
6396 this.e = parseInt(E,16);
6397 this.d = parseBigInt(D,16);
6398 }
6399 else
6400 alert("Invalid RSA private key");
6401}
6402
6403// Set the private key fields N, e, d and CRT params from hex strings
6404function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
6405 if(N != null && E != null && N.length > 0 && E.length > 0) {
6406 this.n = parseBigInt(N,16);
6407 this.e = parseInt(E,16);
6408 this.d = parseBigInt(D,16);
6409 this.p = parseBigInt(P,16);
6410 this.q = parseBigInt(Q,16);
6411 this.dmp1 = parseBigInt(DP,16);
6412 this.dmq1 = parseBigInt(DQ,16);
6413 this.coeff = parseBigInt(C,16);
6414 }
6415 else
6416 alert("Invalid RSA private key");
6417}
6418
6419/**
6420 * Generate a new random private key B bits long, using public expt E
6421 */
6422function RSAGenerate(B,E) {
6423 var rng = new SecureRandom();
6424 var qs = B>>1;
6425 this.e = parseInt(E,16);
6426 var ee = new BigInteger(E,16);
6427 for(;;) {
6428 for(;;) {
6429 this.p = new BigInteger(B-qs,1,rng);
6430 if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
6431 }
6432 for(;;) {
6433 this.q = new BigInteger(qs,1,rng);
6434 if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
6435 }
6436 if(this.p.compareTo(this.q) <= 0) {
6437 var t = this.p;
6438 this.p = this.q;
6439 this.q = t;
6440 }
6441 var p1 = this.p.subtract(BigInteger.ONE); // p1 = p - 1
6442 var q1 = this.q.subtract(BigInteger.ONE); // q1 = q - 1
6443 var phi = p1.multiply(q1);
6444 if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
6445 this.n = this.p.multiply(this.q); // this.n = p * q
6446 this.d = ee.modInverse(phi); // this.d =
6447 this.dmp1 = this.d.mod(p1); // this.dmp1 = d mod (p - 1)
6448 this.dmq1 = this.d.mod(q1); // this.dmq1 = d mod (q - 1)
6449 this.coeff = this.q.modInverse(this.p); // this.coeff = (q ^ -1) mod p
6450 break;
6451 }
6452 }
6453}
6454
6455/**
6456 * Perform raw private operation on "x": return x^d (mod n)
6457 * @return x^d (mod n)
6458 */
6459function RSADoPrivate(x) {
6460 if(this.p == null || this.q == null)
6461 return x.modPow(this.d, this.n);
6462
6463 // TODO: re-calculate any missing CRT params
6464 var xp = x.mod(this.p).modPow(this.dmp1, this.p); // xp=cp?
6465 var xq = x.mod(this.q).modPow(this.dmq1, this.q); // xq=cq?
6466
6467 while(xp.compareTo(xq) < 0)
6468 xp = xp.add(this.p);
6469 // NOTE:
6470 // xp.subtract(xq) => cp -cq
6471 // xp.subtract(xq).multiply(this.coeff).mod(this.p) => (cp - cq) * u mod p = h
6472 // xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq) => cq + (h * q) = M
6473 return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
6474}
6475
6476// Return the PKCS#1 RSA decryption of "ctext".
6477// "ctext" is an even-length hex string and the output is a plain string.
6478function RSADecrypt(ctext) {
6479 var c = parseBigInt(ctext, 16);
6480 var m = this.doPrivate(c);
6481 if(m == null) return null;
6482 return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
6483}
6484
6485// Return the PKCS#1 RSA decryption of "ctext".
6486// "ctext" is a Base64-encoded string and the output is a plain string.
6487//function RSAB64Decrypt(ctext) {
6488// var h = b64tohex(ctext);
6489// if(h) return this.decrypt(h); else return null;
6490//}
6491
6492// protected
6493RSAKey.prototype.doPrivate = RSADoPrivate;
6494
6495// public
6496RSAKey.prototype.setPrivate = RSASetPrivate;
6497RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
6498RSAKey.prototype.generate = RSAGenerate;
6499RSAKey.prototype.decrypt = RSADecrypt;
6500//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
6501
6502/*! rsapem-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
6503 */
6504//
6505// rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
6506// to RSAKey class.
6507//
6508// version: 1.1 (2012-May-10)
6509//
6510// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
6511//
6512// This software is licensed under the terms of the MIT License.
6513// http://kjur.github.com/jsrsasign/license/
6514//
6515// The above copyright and license notice shall be
6516// included in all copies or substantial portions of the Software.
6517//
6518//
6519// Depends on:
6520//
6521//
6522//
6523// _RSApem_pemToBase64(sPEM)
6524//
6525// removing PEM header, PEM footer and space characters including
6526// new lines from PEM formatted RSA private key string.
6527//
6528
6529function _rsapem_pemToBase64(sPEMPrivateKey) {
6530 var s = sPEMPrivateKey;
6531 s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
6532 s = s.replace("-----END RSA PRIVATE KEY-----", "");
6533 s = s.replace(/[ \n]+/g, "");
6534 return s;
6535}
6536
6537function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
6538 var a = new Array();
6539 var v1 = ASN1HEX.getStartPosOfV_AtObj(hPrivateKey, 0);
6540 var n1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, v1);
6541 var e1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, n1);
6542 var d1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, e1);
6543 var p1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, d1);
6544 var q1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, p1);
6545 var dp1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, q1);
6546 var dq1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dp1);
6547 var co1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dq1);
6548 a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
6549 return a;
6550}
6551
6552function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
6553 var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
6554 var v = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[0]);
6555 var n = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[1]);
6556 var e = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[2]);
6557 var d = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[3]);
6558 var p = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[4]);
6559 var q = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[5]);
6560 var dp = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[6]);
6561 var dq = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[7]);
6562 var co = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[8]);
6563 var a = new Array();
6564 a.push(v, n, e, d, p, q, dp, dq, co);
6565 return a;
6566}
6567
6568/**
6569 * read PKCS#1 private key from a string
6570 * @name readPrivateKeyFromPEMString
6571 * @memberOf RSAKey#
6572 * @function
6573 * @param {String} keyPEM string of PKCS#1 private key.
6574 */
6575function _rsapem_readPrivateKeyFromPEMString(keyPEM) {
6576 var keyB64 = _rsapem_pemToBase64(keyPEM);
6577 var keyHex = b64tohex(keyB64) // depends base64.js
6578 var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
6579 this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
6580}
6581
6582RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
6583
6584/*! rsasign-1.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
6585 */
6586//
6587// rsa-sign.js - adding signing functions to RSAKey class.
6588//
6589//
6590// version: 1.2.1 (08 May 2012)
6591//
6592// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
6593//
6594// This software is licensed under the terms of the MIT License.
6595// http://kjur.github.com/jsrsasign/license/
6596//
6597// The above copyright and license notice shall be
6598// included in all copies or substantial portions of the Software.
6599
6600//
6601// Depends on:
6602// function sha1.hex(s) of sha1.js
6603// jsbn.js
6604// jsbn2.js
6605// rsa.js
6606// rsa2.js
6607//
6608
6609// keysize / pmstrlen
6610// 512 / 128
6611// 1024 / 256
6612// 2048 / 512
6613// 4096 / 1024
6614
6615/**
6616 * @property {Dictionary} _RSASIGN_DIHEAD
6617 * @description Array of head part of hexadecimal DigestInfo value for hash algorithms.
6618 * You can add any DigestInfo hash algorith for signing.
6619 * See PKCS#1 v2.1 spec (p38).
6620 */
6621var _RSASIGN_DIHEAD = [];
6622_RSASIGN_DIHEAD['sha1'] = "3021300906052b0e03021a05000414";
6623_RSASIGN_DIHEAD['sha256'] = "3031300d060960864801650304020105000420";
6624_RSASIGN_DIHEAD['sha384'] = "3041300d060960864801650304020205000430";
6625_RSASIGN_DIHEAD['sha512'] = "3051300d060960864801650304020305000440";
6626_RSASIGN_DIHEAD['md2'] = "3020300c06082a864886f70d020205000410";
6627_RSASIGN_DIHEAD['md5'] = "3020300c06082a864886f70d020505000410";
6628_RSASIGN_DIHEAD['ripemd160'] = "3021300906052b2403020105000414";
6629
6630/**
6631 * @property {Dictionary} _RSASIGN_HASHHEXFUNC
6632 * @description Array of functions which calculate hash and returns it as hexadecimal.
6633 * You can add any hash algorithm implementations.
6634 */
6635var _RSASIGN_HASHHEXFUNC = [];
6636_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return hex_sha1(s);}; // http://pajhome.org.uk/crypt/md5/md5.html
6637_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return hex_sha256(s);} // http://pajhome.org.uk/crypt/md5/md5.html
6638_RSASIGN_HASHHEXFUNC['sha512'] = function(s){return hex_sha512(s);} // http://pajhome.org.uk/crypt/md5/md5.html
6639_RSASIGN_HASHHEXFUNC['md5'] = function(s){return hex_md5(s);}; // http://pajhome.org.uk/crypt/md5/md5.html
6640_RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return hex_rmd160(s);}; // http://pajhome.org.uk/crypt/md5/md5.html
6641
6642//@author axelcdv
6643var _RSASIGN_HASHBYTEFUNC = [];
6644_RSASIGN_HASHBYTEFUNC['sha256'] = function(byteArray){return hex_sha256_from_bytes(byteArray);};
6645
6646//_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return sha1.hex(s);} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
6647//_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
6648
6649var _RE_HEXDECONLY = new RegExp("");
6650_RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
6651
6652// ========================================================================
6653// Signature Generation
6654// ========================================================================
6655
6656function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
6657 var pmStrLen = keySize / 4;
6658 var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
6659 var sHashHex = hashFunc(s);
6660
6661 var sHead = "0001";
6662 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
6663 var sMid = "";
6664 var fLen = pmStrLen - sHead.length - sTail.length;
6665 for (var i = 0; i < fLen; i += 2) {
6666 sMid += "ff";
6667 }
6668 sPaddedMessageHex = sHead + sMid + sTail;
6669 return sPaddedMessageHex;
6670}
6671
6672
6673//@author: ucla-cs
6674function _rsasign_getHexPaddedDigestInfoForStringHEX(s, keySize, hashAlg) {
6675 var pmStrLen = keySize / 4;
6676 var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
6677 var sHashHex = hashFunc(s);
6678
6679 var sHead = "0001";
6680 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
6681 var sMid = "";
6682 var fLen = pmStrLen - sHead.length - sTail.length;
6683 for (var i = 0; i < fLen; i += 2) {
6684 sMid += "ff";
6685 }
6686 sPaddedMessageHex = sHead + sMid + sTail;
6687 return sPaddedMessageHex;
6688}
6689
6690/**
6691 * Apply padding, then computes the hash of the given byte array, according to the key size and with the hash algorithm
6692 * @param byteArray (byte[])
6693 * @param keySize (int)
6694 * @param hashAlg the hash algorithm to apply (string)
6695 * @return the hash of byteArray
6696 */
6697function _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, keySize, hashAlg){
6698 var pmStrLen = keySize / 4;
6699 var hashFunc = _RSASIGN_HASHBYTEFUNC[hashAlg];
6700 var sHashHex = hashFunc(byteArray); //returns hex hash
6701
6702 var sHead = "0001";
6703 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
6704 var sMid = "";
6705 var fLen = pmStrLen - sHead.length - sTail.length;
6706 for (var i = 0; i < fLen; i += 2) {
6707 sMid += "ff";
6708 }
6709 sPaddedMessageHex = sHead + sMid + sTail;
6710 return sPaddedMessageHex;
6711}
6712
6713function _zeroPaddingOfSignature(hex, bitLength) {
6714 var s = "";
6715 var nZero = bitLength / 4 - hex.length;
6716 for (var i = 0; i < nZero; i++) {
6717 s = s + "0";
6718 }
6719 return s + hex;
6720}
6721
6722/**
6723 * sign for a message string with RSA private key.<br/>
6724 * @name signString
6725 * @memberOf RSAKey#
6726 * @function
6727 * @param {String} s message string to be signed.
6728 * @param {String} hashAlg hash algorithm name for signing.<br/>
6729 * @return returns hexadecimal string of signature value.
6730 */
6731function _rsasign_signString(s, hashAlg) {
6732 //alert("this.n.bitLength() = " + this.n.bitLength());
6733 var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
6734 var biPaddedMessage = parseBigInt(hPM, 16);
6735 var biSign = this.doPrivate(biPaddedMessage);
6736 var hexSign = biSign.toString(16);
6737 return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
6738}
6739
6740//@author: ucla-cs
6741function _rsasign_signStringHEX(s, hashAlg) {
6742 //alert("this.n.bitLength() = " + this.n.bitLength());
6743 var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
6744 var biPaddedMessage = parseBigInt(hPM, 16);
6745 var biSign = this.doPrivate(biPaddedMessage);
6746 var hexSign = biSign.toString(16);
6747 return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
6748}
6749
6750
6751/**
6752 * Sign a message byteArray with an RSA private key
6753 * @name signByteArray
6754 * @memberOf RSAKey#
6755 * @function
6756 * @param {byte[]} byteArray
6757 * @param {Sring} hashAlg the hash algorithm to apply
6758 * @param {RSAKey} rsa key to sign with: hack because the context is lost here
6759 * @return hexadecimal string of signature value
6760 */
6761function _rsasign_signByteArray(byteArray, hashAlg, rsaKey) {
6762 var hPM = _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, rsaKey.n.bitLength(), hashAlg); ///hack because the context is lost here
6763 var biPaddedMessage = parseBigInt(hPM, 16);
6764 var biSign = rsaKey.doPrivate(biPaddedMessage); //hack because the context is lost here
6765 var hexSign = biSign.toString(16);
6766 return _zeroPaddingOfSignature(hexSign, rsaKey.n.bitLength()); //hack because the context is lost here
6767}
6768
6769/**
6770 * Sign a byte array with the Sha-256 algorithm
6771 * @param {byte[]} byteArray
6772 * @return hexadecimal string of signature value
6773 */
6774function _rsasign_signByteArrayWithSHA256(byteArray){
6775 return _rsasign_signByteArray(byteArray, 'sha256', this); //Hack because the context is lost in the next function
6776}
6777
6778
6779function _rsasign_signStringWithSHA1(s) {
6780 return _rsasign_signString(s, 'sha1');
6781}
6782
6783function _rsasign_signStringWithSHA256(s) {
6784 return _rsasign_signString(s, 'sha256');
6785}
6786
6787// ========================================================================
6788// Signature Verification
6789// ========================================================================
6790
6791function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
6792 var rsa = new RSAKey();
6793 rsa.setPublic(hN, hE);
6794 var biDecryptedSig = rsa.doPublic(biSig);
6795 return biDecryptedSig;
6796}
6797
6798function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
6799 var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
6800 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
6801 return hDigestInfo;
6802}
6803
6804function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
6805 for (var algName in _RSASIGN_DIHEAD) {
6806 var head = _RSASIGN_DIHEAD[algName];
6807 var len = head.length;
6808 if (hDigestInfo.substring(0, len) == head) {
6809 var a = [algName, hDigestInfo.substring(len)];
6810 return a;
6811 }
6812 }
6813 return [];
6814}
6815
6816function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
6817 var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
6818 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
6819 if (digestInfoAry.length == 0) return false;
6820 var algName = digestInfoAry[0];
6821 var diHashValue = digestInfoAry[1];
6822 var ff = _RSASIGN_HASHHEXFUNC[algName];
6823 var msgHashValue = ff(sMsg);
6824 return (diHashValue == msgHashValue);
6825}
6826
6827function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
6828 var biSig = parseBigInt(hSig, 16);
6829 var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
6830 this.n.toString(16),
6831 this.e.toString(16));
6832 return result;
6833}
6834
6835/**
6836 * verifies a sigature for a message string with RSA public key.<br/>
6837 * @name verifyString
6838 * @memberOf RSAKey#
6839 * @function
6840 * @param {String} sMsg message string to be verified.
6841 * @param {String} hSig hexadecimal string of siganture.<br/>
6842 * non-hexadecimal charactors including new lines will be ignored.
6843 * @return returns 1 if valid, otherwise 0
6844 */
6845function _rsasign_verifyString(sMsg, hSig) {
6846 hSig = hSig.replace(_RE_HEXDECONLY, '');
6847
6848 if(LOG>3)console.log('n is '+this.n);
6849 if(LOG>3)console.log('e is '+this.e);
6850
6851 if (hSig.length != this.n.bitLength() / 4) return 0;
6852 hSig = hSig.replace(/[ \n]+/g, "");
6853 var biSig = parseBigInt(hSig, 16);
6854 var biDecryptedSig = this.doPublic(biSig);
6855 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
6856 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
6857
6858 if (digestInfoAry.length == 0) return false;
6859 var algName = digestInfoAry[0];
6860 var diHashValue = digestInfoAry[1];
6861 var ff = _RSASIGN_HASHHEXFUNC[algName];
6862 var msgHashValue = ff(sMsg);
6863 return (diHashValue == msgHashValue);
6864}
6865
6866/**
6867 * verifies a sigature for a message byte array with RSA public key.<br/>
6868 * @name verifyByteArray
6869 * @memberOf RSAKey#
6870 * @function
6871 * @param {byte[]} byteArray message byte array to be verified.
6872 * @param {String} hSig hexadecimal string of signature.<br/>
6873 * non-hexadecimal charactors including new lines will be ignored.
6874 * @return returns 1 if valid, otherwise 0
6875 */
6876function _rsasign_verifyByteArray(byteArray, hSig) {
6877 hSig = hSig.replace(_RE_HEXDECONLY, '');
6878
6879 if(LOG>3)console.log('n is '+this.n);
6880 if(LOG>3)console.log('e is '+this.e);
6881
6882 if (hSig.length != this.n.bitLength() / 4) return 0;
6883 hSig = hSig.replace(/[ \n]+/g, "");
6884 var biSig = parseBigInt(hSig, 16);
6885 var biDecryptedSig = this.doPublic(biSig);
6886 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
6887 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
6888
6889 if (digestInfoAry.length == 0) return false;
6890 var algName = digestInfoAry[0];
6891 var diHashValue = digestInfoAry[1];
6892 var ff = _RSASIGN_HASHBYTEFUNC[algName];
6893 var msgHashValue = ff(byteArray);
6894 return (diHashValue == msgHashValue);
6895}
6896
6897RSAKey.prototype.signString = _rsasign_signString;
6898
6899RSAKey.prototype.signByteArray = _rsasign_signByteArray; //@author axelcdv
6900RSAKey.prototype.signByteArrayWithSHA256 = _rsasign_signByteArrayWithSHA256; //@author axelcdv
6901
6902RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
6903RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
6904RSAKey.prototype.sign = _rsasign_signString;
6905RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
6906RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
6907
6908
6909/*RSAKey.prototype.signStringHEX = _rsasign_signStringHEX;
6910RSAKey.prototype.signStringWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
6911RSAKey.prototype.signStringWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
6912RSAKey.prototype.signHEX = _rsasign_signStringHEX;
6913RSAKey.prototype.signWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
6914RSAKey.prototype.signWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
6915*/
6916
6917RSAKey.prototype.verifyByteArray = _rsasign_verifyByteArray;
6918RSAKey.prototype.verifyString = _rsasign_verifyString;
6919RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
6920RSAKey.prototype.verify = _rsasign_verifyString;
6921RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
6922
6923/*
6924RSAKey.prototype.verifyStringHEX = _rsasign_verifyStringHEX;
6925RSAKey.prototype.verifyHexSignatureForMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
6926RSAKey.prototype.verifyHEX = _rsasign_verifyStringHEX;
6927RSAKey.prototype.verifyHexSignatureForByteArrayMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
6928*/
6929
6930
6931/**
6932 * @name RSAKey
6933 * @class
6934 * @description Tom Wu's RSA Key class and extension
6935 */
6936
6937/*! asn1hex-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
6938 */
6939//
6940// asn1hex.js - Hexadecimal represented ASN.1 string library
6941//
6942// version: 1.1 (09-May-2012)
6943//
6944// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
6945//
6946// This software is licensed under the terms of the MIT License.
6947// http://kjur.github.com/jsrsasign/license/
6948//
6949// The above copyright and license notice shall be
6950// included in all copies or substantial portions of the Software.
6951//
6952// Depends on:
6953//
6954
6955// MEMO:
6956// f('3082025b02...', 2) ... 82025b ... 3bytes
6957// f('020100', 2) ... 01 ... 1byte
6958// f('0203001...', 2) ... 03 ... 1byte
6959// f('02818003...', 2) ... 8180 ... 2bytes
6960// f('3080....0000', 2) ... 80 ... -1
6961//
6962// Requirements:
6963// - ASN.1 type octet length MUST be 1.
6964// (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
6965// -
6966/**
6967 * get byte length for ASN.1 L(length) bytes
6968 * @name getByteLengthOfL_AtObj
6969 * @memberOf ASN1HEX
6970 * @function
6971 * @param {String} s hexadecimal string of ASN.1 DER encoded data
6972 * @param {Number} pos string index
6973 * @return byte length for ASN.1 L(length) bytes
6974 */
6975function _asnhex_getByteLengthOfL_AtObj(s, pos) {
6976 if (s.substring(pos + 2, pos + 3) != '8') return 1;
6977 var i = parseInt(s.substring(pos + 3, pos + 4));
6978 if (i == 0) return -1; // length octet '80' indefinite length
6979 if (0 < i && i < 10) return i + 1; // including '8?' octet;
6980 return -2; // malformed format
6981}
6982
6983
6984/**
6985 * get hexadecimal string for ASN.1 L(length) bytes
6986 * @name getHexOfL_AtObj
6987 * @memberOf ASN1HEX
6988 * @function
6989 * @param {String} s hexadecimal string of ASN.1 DER encoded data
6990 * @param {Number} pos string index
6991 * @return {String} hexadecimal string for ASN.1 L(length) bytes
6992 */
6993function _asnhex_getHexOfL_AtObj(s, pos) {
6994 var len = _asnhex_getByteLengthOfL_AtObj(s, pos);
6995 if (len < 1) return '';
6996 return s.substring(pos + 2, pos + 2 + len * 2);
6997}
6998
6999//
7000// getting ASN.1 length value at the position 'idx' of
7001// hexa decimal string 's'.
7002//
7003// f('3082025b02...', 0) ... 82025b ... ???
7004// f('020100', 0) ... 01 ... 1
7005// f('0203001...', 0) ... 03 ... 3
7006// f('02818003...', 0) ... 8180 ... 128
7007/**
7008 * get integer value of ASN.1 length for ASN.1 data
7009 * @name getIntOfL_AtObj
7010 * @memberOf ASN1HEX
7011 * @function
7012 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7013 * @param {Number} pos string index
7014 * @return ASN.1 L(length) integer value
7015 */
7016function _asnhex_getIntOfL_AtObj(s, pos) {
7017 var hLength = _asnhex_getHexOfL_AtObj(s, pos);
7018 if (hLength == '') return -1;
7019 var bi;
7020 if (parseInt(hLength.substring(0, 1)) < 8) {
7021 bi = parseBigInt(hLength, 16);
7022 } else {
7023 bi = parseBigInt(hLength.substring(2), 16);
7024 }
7025 return bi.intValue();
7026}
7027
7028/**
7029 * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
7030 * @name getStartPosOfV_AtObj
7031 * @memberOf ASN1HEX
7032 * @function
7033 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7034 * @param {Number} pos string index
7035 */
7036function _asnhex_getStartPosOfV_AtObj(s, pos) {
7037 var l_len = _asnhex_getByteLengthOfL_AtObj(s, pos);
7038 if (l_len < 0) return l_len;
7039 return pos + (l_len + 1) * 2;
7040}
7041
7042/**
7043 * get hexadecimal string of ASN.1 V(value)
7044 * @name getHexOfV_AtObj
7045 * @memberOf ASN1HEX
7046 * @function
7047 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7048 * @param {Number} pos string index
7049 * @return {String} hexadecimal string of ASN.1 value.
7050 */
7051function _asnhex_getHexOfV_AtObj(s, pos) {
7052 var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
7053 var len = _asnhex_getIntOfL_AtObj(s, pos);
7054 return s.substring(pos1, pos1 + len * 2);
7055}
7056
7057/**
7058 * get hexadecimal string of ASN.1 TLV at
7059 * @name getHexOfTLV_AtObj
7060 * @memberOf ASN1HEX
7061 * @function
7062 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7063 * @param {Number} pos string index
7064 * @return {String} hexadecimal string of ASN.1 TLV.
7065 * @since 1.1
7066 */
7067function _asnhex_getHexOfTLV_AtObj(s, pos) {
7068 var hT = s.substr(pos, 2);
7069 var hL = _asnhex_getHexOfL_AtObj(s, pos);
7070 var hV = _asnhex_getHexOfV_AtObj(s, pos);
7071 return hT + hL + hV;
7072}
7073
7074/**
7075 * get next sibling starting index for ASN.1 object string
7076 * @name getPosOfNextSibling_AtObj
7077 * @memberOf ASN1HEX
7078 * @function
7079 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7080 * @param {Number} pos string index
7081 * @return next sibling starting index for ASN.1 object string
7082 */
7083function _asnhex_getPosOfNextSibling_AtObj(s, pos) {
7084 var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
7085 var len = _asnhex_getIntOfL_AtObj(s, pos);
7086 return pos1 + len * 2;
7087}
7088
7089/**
7090 * get array of indexes of child ASN.1 objects
7091 * @name getPosArrayOfChildren_AtObj
7092 * @memberOf ASN1HEX
7093 * @function
7094 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7095 * @param {Number} start string index of ASN.1 object
7096 * @return {Array of Number} array of indexes for childen of ASN.1 objects
7097 */
7098function _asnhex_getPosArrayOfChildren_AtObj(h, pos) {
7099 var a = new Array();
7100 var p0 = _asnhex_getStartPosOfV_AtObj(h, pos);
7101 a.push(p0);
7102
7103 var len = _asnhex_getIntOfL_AtObj(h, pos);
7104 var p = p0;
7105 var k = 0;
7106 while (1) {
7107 var pNext = _asnhex_getPosOfNextSibling_AtObj(h, p);
7108 if (pNext == null || (pNext - p0 >= (len * 2))) break;
7109 if (k >= 200) break;
7110
7111 a.push(pNext);
7112 p = pNext;
7113
7114 k++;
7115 }
7116
7117 return a;
7118}
7119
7120/**
7121 * get string index of nth child object of ASN.1 object refered by h, idx
7122 * @name getNthChildIndex_AtObj
7123 * @memberOf ASN1HEX
7124 * @function
7125 * @param {String} h hexadecimal string of ASN.1 DER encoded data
7126 * @param {Number} idx start string index of ASN.1 object
7127 * @param {Number} nth for child
7128 * @return {Number} string index of nth child.
7129 * @since 1.1
7130 */
7131function _asnhex_getNthChildIndex_AtObj(h, idx, nth) {
7132 var a = _asnhex_getPosArrayOfChildren_AtObj(h, idx);
7133 return a[nth];
7134}
7135
7136// ========== decendant methods ==============================
7137
7138/**
7139 * get string index of nth child object of ASN.1 object refered by h, idx
7140 * @name getDecendantIndexByNthList
7141 * @memberOf ASN1HEX
7142 * @function
7143 * @param {String} h hexadecimal string of ASN.1 DER encoded data
7144 * @param {Number} currentIndex start string index of ASN.1 object
7145 * @param {Array of Number} nthList array list of nth
7146 * @return {Number} string index refered by nthList
7147 * @since 1.1
7148 */
7149function _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList) {
7150 if (nthList.length == 0) {
7151 return currentIndex;
7152 }
7153 var firstNth = nthList.shift();
7154 var a = _asnhex_getPosArrayOfChildren_AtObj(h, currentIndex);
7155 return _asnhex_getDecendantIndexByNthList(h, a[firstNth], nthList);
7156}
7157
7158/**
7159 * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
7160 * @name getDecendantHexTLVByNthList
7161 * @memberOf ASN1HEX
7162 * @function
7163 * @param {String} h hexadecimal string of ASN.1 DER encoded data
7164 * @param {Number} currentIndex start string index of ASN.1 object
7165 * @param {Array of Number} nthList array list of nth
7166 * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
7167 * @since 1.1
7168 */
7169function _asnhex_getDecendantHexTLVByNthList(h, currentIndex, nthList) {
7170 var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
7171 return _asnhex_getHexOfTLV_AtObj(h, idx);
7172}
7173
7174/**
7175 * get hexadecimal string of ASN.1 V refered by current index and nth index list.
7176 * @name getDecendantHexVByNthList
7177 * @memberOf ASN1HEX
7178 * @function
7179 * @param {String} h hexadecimal string of ASN.1 DER encoded data
7180 * @param {Number} currentIndex start string index of ASN.1 object
7181 * @param {Array of Number} nthList array list of nth
7182 * @return {Number} hexadecimal string of ASN.1 V refered by nthList
7183 * @since 1.1
7184 */
7185function _asnhex_getDecendantHexVByNthList(h, currentIndex, nthList) {
7186 var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
7187 return _asnhex_getHexOfV_AtObj(h, idx);
7188}
7189
7190// ========== class definition ==============================
7191
7192/**
7193 * ASN.1 DER encoded hexadecimal string utility class
7194 * @class ASN.1 DER encoded hexadecimal string utility class
7195 * @author Kenji Urushima
7196 * @version 1.1 (09 May 2012)
7197 * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
7198 * @since 1.1
7199 */
7200function ASN1HEX() {
7201 return ASN1HEX;
7202}
7203
7204ASN1HEX.getByteLengthOfL_AtObj = _asnhex_getByteLengthOfL_AtObj;
7205ASN1HEX.getHexOfL_AtObj = _asnhex_getHexOfL_AtObj;
7206ASN1HEX.getIntOfL_AtObj = _asnhex_getIntOfL_AtObj;
7207ASN1HEX.getStartPosOfV_AtObj = _asnhex_getStartPosOfV_AtObj;
7208ASN1HEX.getHexOfV_AtObj = _asnhex_getHexOfV_AtObj;
7209ASN1HEX.getHexOfTLV_AtObj = _asnhex_getHexOfTLV_AtObj;
7210ASN1HEX.getPosOfNextSibling_AtObj = _asnhex_getPosOfNextSibling_AtObj;
7211ASN1HEX.getPosArrayOfChildren_AtObj = _asnhex_getPosArrayOfChildren_AtObj;
7212ASN1HEX.getNthChildIndex_AtObj = _asnhex_getNthChildIndex_AtObj;
7213ASN1HEX.getDecendantIndexByNthList = _asnhex_getDecendantIndexByNthList;
7214ASN1HEX.getDecendantHexVByNthList = _asnhex_getDecendantHexVByNthList;
7215ASN1HEX.getDecendantHexTLVByNthList = _asnhex_getDecendantHexTLVByNthList;
7216
7217/*! x509-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
7218 */
7219//
7220// x509.js - X509 class to read subject public key from certificate.
7221//
7222// version: 1.1 (10-May-2012)
7223//
7224// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
7225//
7226// This software is licensed under the terms of the MIT License.
7227// http://kjur.github.com/jsrsasign/license
7228//
7229// The above copyright and license notice shall be
7230// included in all copies or substantial portions of the Software.
7231//
7232
7233// Depends:
7234// base64.js
7235// rsa.js
7236// asn1hex.js
7237
7238function _x509_pemToBase64(sCertPEM) {
7239 var s = sCertPEM;
7240 s = s.replace("-----BEGIN CERTIFICATE-----", "");
7241 s = s.replace("-----END CERTIFICATE-----", "");
7242 s = s.replace(/[ \n]+/g, "");
7243 return s;
7244}
7245
7246function _x509_pemToHex(sCertPEM) {
7247 var b64Cert = _x509_pemToBase64(sCertPEM);
7248 var hCert = b64tohex(b64Cert);
7249 return hCert;
7250}
7251
7252function _x509_getHexTbsCertificateFromCert(hCert) {
7253 var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
7254 return pTbsCert;
7255}
7256
7257// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
7258// NOTE: v1 and v3 supported
7259function _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert) {
7260 var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
7261 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert);
7262 if (a.length < 1) return -1;
7263 if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
7264 if (a.length < 6) return -1;
7265 return a[6];
7266 } else {
7267 if (a.length < 5) return -1;
7268 return a[5];
7269 }
7270}
7271
7272// NOTE: Without BITSTRING encapsulation.
7273function _x509_getSubjectPublicKeyPosFromCertHex(hCert) {
7274 var pInfo = _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert);
7275 if (pInfo == -1) return -1;
7276 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo);
7277
7278 if (a.length != 2) return -1;
7279 var pBitString = a[1];
7280 if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
7281 var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
7282
7283 if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
7284 return pBitStringV + 2;
7285}
7286
7287function _x509_getPublicKeyHexArrayFromCertHex(hCert) {
7288 var p = _x509_getSubjectPublicKeyPosFromCertHex(hCert);
7289 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
7290 //var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a[3]);
7291 if(LOG>4){
7292 console.log('a is now');
7293 console.log(a);
7294 }
7295
7296 //if (a.length != 2) return [];
7297 if (a.length < 2) return [];
7298
7299 var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
7300 var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
7301 if (hN != null && hE != null) {
7302 return [hN, hE];
7303 } else {
7304 return [];
7305 }
7306}
7307
7308function _x509_getPublicKeyHexArrayFromCertPEM(sCertPEM) {
7309 var hCert = _x509_pemToHex(sCertPEM);
7310 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
7311 return a;
7312}
7313
7314// ===== get basic fields from hex =====================================
7315/**
7316 * get hexadecimal string of serialNumber field of certificate.<br/>
7317 * @name getSerialNumberHex
7318 * @memberOf X509#
7319 * @function
7320 */
7321function _x509_getSerialNumberHex() {
7322 return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
7323}
7324
7325/**
7326 * get hexadecimal string of issuer field of certificate.<br/>
7327 * @name getIssuerHex
7328 * @memberOf X509#
7329 * @function
7330 */
7331function _x509_getIssuerHex() {
7332 return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
7333}
7334
7335/**
7336 * get string of issuer field of certificate.<br/>
7337 * @name getIssuerString
7338 * @memberOf X509#
7339 * @function
7340 */
7341function _x509_getIssuerString() {
7342 return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
7343}
7344
7345/**
7346 * get hexadecimal string of subject field of certificate.<br/>
7347 * @name getSubjectHex
7348 * @memberOf X509#
7349 * @function
7350 */
7351function _x509_getSubjectHex() {
7352 return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
7353}
7354
7355/**
7356 * get string of subject field of certificate.<br/>
7357 * @name getSubjectString
7358 * @memberOf X509#
7359 * @function
7360 */
7361function _x509_getSubjectString() {
7362 return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
7363}
7364
7365/**
7366 * get notBefore field string of certificate.<br/>
7367 * @name getNotBefore
7368 * @memberOf X509#
7369 * @function
7370 */
7371function _x509_getNotBefore() {
7372 var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
7373 s = s.replace(/(..)/g, "%$1");
7374 s = decodeURIComponent(s);
7375 return s;
7376}
7377
7378/**
7379 * get notAfter field string of certificate.<br/>
7380 * @name getNotAfter
7381 * @memberOf X509#
7382 * @function
7383 */
7384function _x509_getNotAfter() {
7385 var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
7386 s = s.replace(/(..)/g, "%$1");
7387 s = decodeURIComponent(s);
7388 return s;
7389}
7390
7391// ===== read certificate =====================================
7392
7393_x509_DN_ATTRHEX = {
7394 "0603550406": "C",
7395 "060355040a": "O",
7396 "060355040b": "OU",
7397 "0603550403": "CN",
7398 "0603550405": "SN",
7399 "0603550408": "ST",
7400 "0603550407": "L" };
7401
7402function _x509_hex2dn(hDN) {
7403 var s = "";
7404 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
7405 for (var i = 0; i < a.length; i++) {
7406 var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
7407 s = s + "/" + _x509_hex2rdn(hRDN);
7408 }
7409 return s;
7410}
7411
7412function _x509_hex2rdn(hRDN) {
7413 var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
7414 var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
7415 var type = "";
7416 try { type = _x509_DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
7417 hValue = hValue.replace(/(..)/g, "%$1");
7418 var value = decodeURIComponent(hValue);
7419 return type + "=" + value;
7420}
7421
7422// ===== read certificate =====================================
7423
7424
7425/**
7426 * read PEM formatted X.509 certificate from string.<br/>
7427 * @name readCertPEM
7428 * @memberOf X509#
7429 * @function
7430 * @param {String} sCertPEM string for PEM formatted X.509 certificate
7431 */
7432function _x509_readCertPEM(sCertPEM) {
7433 var hCert = _x509_pemToHex(sCertPEM);
7434 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
7435 if(LOG>4){
7436 console.log('HEX VALUE IS ' + hCert);
7437 console.log('type of a' + typeof a);
7438 console.log('a VALUE IS ');
7439 console.log(a);
7440 console.log('a[0] VALUE IS ' + a[0]);
7441 console.log('a[1] VALUE IS ' + a[1]);
7442 }
7443 var rsa = new RSAKey();
7444 rsa.setPublic(a[0], a[1]);
7445 this.subjectPublicKeyRSA = rsa;
7446 this.subjectPublicKeyRSA_hN = a[0];
7447 this.subjectPublicKeyRSA_hE = a[1];
7448 this.hex = hCert;
7449}
7450
7451function _x509_readCertPEMWithoutRSAInit(sCertPEM) {
7452 var hCert = _x509_pemToHex(sCertPEM);
7453 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
7454 this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
7455 this.subjectPublicKeyRSA_hN = a[0];
7456 this.subjectPublicKeyRSA_hE = a[1];
7457 this.hex = hCert;
7458}
7459
7460/**
7461 * X.509 certificate class.<br/>
7462 * @class X.509 certificate class
7463 * @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object
7464 * @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key
7465 * @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key
7466 * @property {String} hex hexacedimal string for X.509 certificate.
7467 * @author Kenji Urushima
7468 * @version 1.0.1 (08 May 2012)
7469 * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
7470 */
7471function X509() {
7472 this.subjectPublicKeyRSA = null;
7473 this.subjectPublicKeyRSA_hN = null;
7474 this.subjectPublicKeyRSA_hE = null;
7475 this.hex = null;
7476}
7477
7478X509.prototype.readCertPEM = _x509_readCertPEM;
7479X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
7480X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
7481X509.prototype.getIssuerHex = _x509_getIssuerHex;
7482X509.prototype.getSubjectHex = _x509_getSubjectHex;
7483X509.prototype.getIssuerString = _x509_getIssuerString;
7484X509.prototype.getSubjectString = _x509_getSubjectString;
7485X509.prototype.getNotBefore = _x509_getNotBefore;
7486X509.prototype.getNotAfter = _x509_getNotAfter;
7487
7488
7489// Copyright (c) 2005 Tom Wu
7490// All Rights Reserved.
7491// See "LICENSE" for details.
7492
7493// Basic JavaScript BN library - subset useful for RSA encryption.
7494
7495// Bits per digit
7496var dbits;
7497
7498// JavaScript engine analysis
7499var canary = 0xdeadbeefcafe;
7500var j_lm = ((canary&0xffffff)==0xefcafe);
7501
7502// (public) Constructor
7503function BigInteger(a,b,c) {
7504 if(a != null)
7505 if("number" == typeof a) this.fromNumber(a,b,c);
7506 else if(b == null && "string" != typeof a) this.fromString(a,256);
7507 else this.fromString(a,b);
7508}
7509
7510// return new, unset BigInteger
7511function nbi() { return new BigInteger(null); }
7512
7513// am: Compute w_j += (x*this_i), propagate carries,
7514// c is initial carry, returns final carry.
7515// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
7516// We need to select the fastest one that works in this environment.
7517
7518// am1: use a single mult and divide to get the high bits,
7519// max digit bits should be 26 because
7520// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
7521function am1(i,x,w,j,c,n) {
7522 while(--n >= 0) {
7523 var v = x*this[i++]+w[j]+c;
7524 c = Math.floor(v/0x4000000);
7525 w[j++] = v&0x3ffffff;
7526 }
7527 return c;
7528}
7529// am2 avoids a big mult-and-extract completely.
7530// Max digit bits should be <= 30 because we do bitwise ops
7531// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
7532function am2(i,x,w,j,c,n) {
7533 var xl = x&0x7fff, xh = x>>15;
7534 while(--n >= 0) {
7535 var l = this[i]&0x7fff;
7536 var h = this[i++]>>15;
7537 var m = xh*l+h*xl;
7538 l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
7539 c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
7540 w[j++] = l&0x3fffffff;
7541 }
7542 return c;
7543}
7544// Alternately, set max digit bits to 28 since some
7545// browsers slow down when dealing with 32-bit numbers.
7546function am3(i,x,w,j,c,n) {
7547 var xl = x&0x3fff, xh = x>>14;
7548 while(--n >= 0) {
7549 var l = this[i]&0x3fff;
7550 var h = this[i++]>>14;
7551 var m = xh*l+h*xl;
7552 l = xl*l+((m&0x3fff)<<14)+w[j]+c;
7553 c = (l>>28)+(m>>14)+xh*h;
7554 w[j++] = l&0xfffffff;
7555 }
7556 return c;
7557}
7558if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
7559 BigInteger.prototype.am = am2;
7560 dbits = 30;
7561}
7562else if(j_lm && (navigator.appName != "Netscape")) {
7563 BigInteger.prototype.am = am1;
7564 dbits = 26;
7565}
7566else { // Mozilla/Netscape seems to prefer am3
7567 BigInteger.prototype.am = am3;
7568 dbits = 28;
7569}
7570
7571BigInteger.prototype.DB = dbits;
7572BigInteger.prototype.DM = ((1<<dbits)-1);
7573BigInteger.prototype.DV = (1<<dbits);
7574
7575var BI_FP = 52;
7576BigInteger.prototype.FV = Math.pow(2,BI_FP);
7577BigInteger.prototype.F1 = BI_FP-dbits;
7578BigInteger.prototype.F2 = 2*dbits-BI_FP;
7579
7580// Digit conversions
7581var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
7582var BI_RC = new Array();
7583var rr,vv;
7584rr = "0".charCodeAt(0);
7585for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
7586rr = "a".charCodeAt(0);
7587for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
7588rr = "A".charCodeAt(0);
7589for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
7590
7591function int2char(n) { return BI_RM.charAt(n); }
7592function intAt(s,i) {
7593 var c = BI_RC[s.charCodeAt(i)];
7594 return (c==null)?-1:c;
7595}
7596
7597// (protected) copy this to r
7598function bnpCopyTo(r) {
7599 for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
7600 r.t = this.t;
7601 r.s = this.s;
7602}
7603
7604// (protected) set from integer value x, -DV <= x < DV
7605function bnpFromInt(x) {
7606 this.t = 1;
7607 this.s = (x<0)?-1:0;
7608 if(x > 0) this[0] = x;
7609 else if(x < -1) this[0] = x+DV;
7610 else this.t = 0;
7611}
7612
7613// return bigint initialized to value
7614function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
7615
7616// (protected) set from string and radix
7617function bnpFromString(s,b) {
7618 var k;
7619 if(b == 16) k = 4;
7620 else if(b == 8) k = 3;
7621 else if(b == 256) k = 8; // byte array
7622 else if(b == 2) k = 1;
7623 else if(b == 32) k = 5;
7624 else if(b == 4) k = 2;
7625 else { this.fromRadix(s,b); return; }
7626 this.t = 0;
7627 this.s = 0;
7628 var i = s.length, mi = false, sh = 0;
7629 while(--i >= 0) {
7630 var x = (k==8)?s[i]&0xff:intAt(s,i);
7631 if(x < 0) {
7632 if(s.charAt(i) == "-") mi = true;
7633 continue;
7634 }
7635 mi = false;
7636 if(sh == 0)
7637 this[this.t++] = x;
7638 else if(sh+k > this.DB) {
7639 this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
7640 this[this.t++] = (x>>(this.DB-sh));
7641 }
7642 else
7643 this[this.t-1] |= x<<sh;
7644 sh += k;
7645 if(sh >= this.DB) sh -= this.DB;
7646 }
7647 if(k == 8 && (s[0]&0x80) != 0) {
7648 this.s = -1;
7649 if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
7650 }
7651 this.clamp();
7652 if(mi) BigInteger.ZERO.subTo(this,this);
7653}
7654
7655// (protected) clamp off excess high words
7656function bnpClamp() {
7657 var c = this.s&this.DM;
7658 while(this.t > 0 && this[this.t-1] == c) --this.t;
7659}
7660
7661// (public) return string representation in given radix
7662function bnToString(b) {
7663 if(this.s < 0) return "-"+this.negate().toString(b);
7664 var k;
7665 if(b == 16) k = 4;
7666 else if(b == 8) k = 3;
7667 else if(b == 2) k = 1;
7668 else if(b == 32) k = 5;
7669 else if(b == 4) k = 2;
7670 else return this.toRadix(b);
7671 var km = (1<<k)-1, d, m = false, r = "", i = this.t;
7672 var p = this.DB-(i*this.DB)%k;
7673 if(i-- > 0) {
7674 if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
7675 while(i >= 0) {
7676 if(p < k) {
7677 d = (this[i]&((1<<p)-1))<<(k-p);
7678 d |= this[--i]>>(p+=this.DB-k);
7679 }
7680 else {
7681 d = (this[i]>>(p-=k))&km;
7682 if(p <= 0) { p += this.DB; --i; }
7683 }
7684 if(d > 0) m = true;
7685 if(m) r += int2char(d);
7686 }
7687 }
7688 return m?r:"0";
7689}
7690
7691// (public) -this
7692function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
7693
7694// (public) |this|
7695function bnAbs() { return (this.s<0)?this.negate():this; }
7696
7697// (public) return + if this > a, - if this < a, 0 if equal
7698function bnCompareTo(a) {
7699 var r = this.s-a.s;
7700 if(r != 0) return r;
7701 var i = this.t;
7702 r = i-a.t;
7703 if(r != 0) return r;
7704 while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
7705 return 0;
7706}
7707
7708// returns bit length of the integer x
7709function nbits(x) {
7710 var r = 1, t;
7711 if((t=x>>>16) != 0) { x = t; r += 16; }
7712 if((t=x>>8) != 0) { x = t; r += 8; }
7713 if((t=x>>4) != 0) { x = t; r += 4; }
7714 if((t=x>>2) != 0) { x = t; r += 2; }
7715 if((t=x>>1) != 0) { x = t; r += 1; }
7716 return r;
7717}
7718
7719// (public) return the number of bits in "this"
7720function bnBitLength() {
7721 if(this.t <= 0) return 0;
7722 return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
7723}
7724
7725// (protected) r = this << n*DB
7726function bnpDLShiftTo(n,r) {
7727 var i;
7728 for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
7729 for(i = n-1; i >= 0; --i) r[i] = 0;
7730 r.t = this.t+n;
7731 r.s = this.s;
7732}
7733
7734// (protected) r = this >> n*DB
7735function bnpDRShiftTo(n,r) {
7736 for(var i = n; i < this.t; ++i) r[i-n] = this[i];
7737 r.t = Math.max(this.t-n,0);
7738 r.s = this.s;
7739}
7740
7741// (protected) r = this << n
7742function bnpLShiftTo(n,r) {
7743 var bs = n%this.DB;
7744 var cbs = this.DB-bs;
7745 var bm = (1<<cbs)-1;
7746 var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
7747 for(i = this.t-1; i >= 0; --i) {
7748 r[i+ds+1] = (this[i]>>cbs)|c;
7749 c = (this[i]&bm)<<bs;
7750 }
7751 for(i = ds-1; i >= 0; --i) r[i] = 0;
7752 r[ds] = c;
7753 r.t = this.t+ds+1;
7754 r.s = this.s;
7755 r.clamp();
7756}
7757
7758// (protected) r = this >> n
7759function bnpRShiftTo(n,r) {
7760 r.s = this.s;
7761 var ds = Math.floor(n/this.DB);
7762 if(ds >= this.t) { r.t = 0; return; }
7763 var bs = n%this.DB;
7764 var cbs = this.DB-bs;
7765 var bm = (1<<bs)-1;
7766 r[0] = this[ds]>>bs;
7767 for(var i = ds+1; i < this.t; ++i) {
7768 r[i-ds-1] |= (this[i]&bm)<<cbs;
7769 r[i-ds] = this[i]>>bs;
7770 }
7771 if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
7772 r.t = this.t-ds;
7773 r.clamp();
7774}
7775
7776// (protected) r = this - a
7777function bnpSubTo(a,r) {
7778 var i = 0, c = 0, m = Math.min(a.t,this.t);
7779 while(i < m) {
7780 c += this[i]-a[i];
7781 r[i++] = c&this.DM;
7782 c >>= this.DB;
7783 }
7784 if(a.t < this.t) {
7785 c -= a.s;
7786 while(i < this.t) {
7787 c += this[i];
7788 r[i++] = c&this.DM;
7789 c >>= this.DB;
7790 }
7791 c += this.s;
7792 }
7793 else {
7794 c += this.s;
7795 while(i < a.t) {
7796 c -= a[i];
7797 r[i++] = c&this.DM;
7798 c >>= this.DB;
7799 }
7800 c -= a.s;
7801 }
7802 r.s = (c<0)?-1:0;
7803 if(c < -1) r[i++] = this.DV+c;
7804 else if(c > 0) r[i++] = c;
7805 r.t = i;
7806 r.clamp();
7807}
7808
7809// (protected) r = this * a, r != this,a (HAC 14.12)
7810// "this" should be the larger one if appropriate.
7811function bnpMultiplyTo(a,r) {
7812 var x = this.abs(), y = a.abs();
7813 var i = x.t;
7814 r.t = i+y.t;
7815 while(--i >= 0) r[i] = 0;
7816 for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
7817 r.s = 0;
7818 r.clamp();
7819 if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
7820}
7821
7822// (protected) r = this^2, r != this (HAC 14.16)
7823function bnpSquareTo(r) {
7824 var x = this.abs();
7825 var i = r.t = 2*x.t;
7826 while(--i >= 0) r[i] = 0;
7827 for(i = 0; i < x.t-1; ++i) {
7828 var c = x.am(i,x[i],r,2*i,0,1);
7829 if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
7830 r[i+x.t] -= x.DV;
7831 r[i+x.t+1] = 1;
7832 }
7833 }
7834 if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
7835 r.s = 0;
7836 r.clamp();
7837}
7838
7839// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
7840// r != q, this != m. q or r may be null.
7841function bnpDivRemTo(m,q,r) {
7842 var pm = m.abs();
7843 if(pm.t <= 0) return;
7844 var pt = this.abs();
7845 if(pt.t < pm.t) {
7846 if(q != null) q.fromInt(0);
7847 if(r != null) this.copyTo(r);
7848 return;
7849 }
7850 if(r == null) r = nbi();
7851 var y = nbi(), ts = this.s, ms = m.s;
7852 var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
7853 if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
7854 else { pm.copyTo(y); pt.copyTo(r); }
7855 var ys = y.t;
7856 var y0 = y[ys-1];
7857 if(y0 == 0) return;
7858 var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
7859 var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
7860 var i = r.t, j = i-ys, t = (q==null)?nbi():q;
7861 y.dlShiftTo(j,t);
7862 if(r.compareTo(t) >= 0) {
7863 r[r.t++] = 1;
7864 r.subTo(t,r);
7865 }
7866 BigInteger.ONE.dlShiftTo(ys,t);
7867 t.subTo(y,y); // "negative" y so we can replace sub with am later
7868 while(y.t < ys) y[y.t++] = 0;
7869 while(--j >= 0) {
7870 // Estimate quotient digit
7871 var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
7872 if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
7873 y.dlShiftTo(j,t);
7874 r.subTo(t,r);
7875 while(r[i] < --qd) r.subTo(t,r);
7876 }
7877 }
7878 if(q != null) {
7879 r.drShiftTo(ys,q);
7880 if(ts != ms) BigInteger.ZERO.subTo(q,q);
7881 }
7882 r.t = ys;
7883 r.clamp();
7884 if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
7885 if(ts < 0) BigInteger.ZERO.subTo(r,r);
7886}
7887
7888// (public) this mod a
7889function bnMod(a) {
7890 var r = nbi();
7891 this.abs().divRemTo(a,null,r);
7892 if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
7893 return r;
7894}
7895
7896// Modular reduction using "classic" algorithm
7897function Classic(m) { this.m = m; }
7898function cConvert(x) {
7899 if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
7900 else return x;
7901}
7902function cRevert(x) { return x; }
7903function cReduce(x) { x.divRemTo(this.m,null,x); }
7904function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
7905function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
7906
7907Classic.prototype.convert = cConvert;
7908Classic.prototype.revert = cRevert;
7909Classic.prototype.reduce = cReduce;
7910Classic.prototype.mulTo = cMulTo;
7911Classic.prototype.sqrTo = cSqrTo;
7912
7913// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
7914// justification:
7915// xy == 1 (mod m)
7916// xy = 1+km
7917// xy(2-xy) = (1+km)(1-km)
7918// x[y(2-xy)] = 1-k^2m^2
7919// x[y(2-xy)] == 1 (mod m^2)
7920// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
7921// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
7922// JS multiply "overflows" differently from C/C++, so care is needed here.
7923function bnpInvDigit() {
7924 if(this.t < 1) return 0;
7925 var x = this[0];
7926 if((x&1) == 0) return 0;
7927 var y = x&3; // y == 1/x mod 2^2
7928 y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
7929 y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
7930 y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
7931 // last step - calculate inverse mod DV directly;
7932 // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
7933 y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
7934 // we really want the negative inverse, and -DV < y < DV
7935 return (y>0)?this.DV-y:-y;
7936}
7937
7938// Montgomery reduction
7939function Montgomery(m) {
7940 this.m = m;
7941 this.mp = m.invDigit();
7942 this.mpl = this.mp&0x7fff;
7943 this.mph = this.mp>>15;
7944 this.um = (1<<(m.DB-15))-1;
7945 this.mt2 = 2*m.t;
7946}
7947
7948// xR mod m
7949function montConvert(x) {
7950 var r = nbi();
7951 x.abs().dlShiftTo(this.m.t,r);
7952 r.divRemTo(this.m,null,r);
7953 if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
7954 return r;
7955}
7956
7957// x/R mod m
7958function montRevert(x) {
7959 var r = nbi();
7960 x.copyTo(r);
7961 this.reduce(r);
7962 return r;
7963}
7964
7965// x = x/R mod m (HAC 14.32)
7966function montReduce(x) {
7967 while(x.t <= this.mt2) // pad x so am has enough room later
7968 x[x.t++] = 0;
7969 for(var i = 0; i < this.m.t; ++i) {
7970 // faster way of calculating u0 = x[i]*mp mod DV
7971 var j = x[i]&0x7fff;
7972 var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
7973 // use am to combine the multiply-shift-add into one call
7974 j = i+this.m.t;
7975 x[j] += this.m.am(0,u0,x,i,0,this.m.t);
7976 // propagate carry
7977 while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
7978 }
7979 x.clamp();
7980 x.drShiftTo(this.m.t,x);
7981 if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
7982}
7983
7984// r = "x^2/R mod m"; x != r
7985function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
7986
7987// r = "xy/R mod m"; x,y != r
7988function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
7989
7990Montgomery.prototype.convert = montConvert;
7991Montgomery.prototype.revert = montRevert;
7992Montgomery.prototype.reduce = montReduce;
7993Montgomery.prototype.mulTo = montMulTo;
7994Montgomery.prototype.sqrTo = montSqrTo;
7995
7996// (protected) true iff this is even
7997function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
7998
7999// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
8000function bnpExp(e,z) {
8001 if(e > 0xffffffff || e < 1) return BigInteger.ONE;
8002 var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
8003 g.copyTo(r);
8004 while(--i >= 0) {
8005 z.sqrTo(r,r2);
8006 if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
8007 else { var t = r; r = r2; r2 = t; }
8008 }
8009 return z.revert(r);
8010}
8011
8012// (public) this^e % m, 0 <= e < 2^32
8013function bnModPowInt(e,m) {
8014 var z;
8015 if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
8016 return this.exp(e,z);
8017}
8018
8019// protected
8020BigInteger.prototype.copyTo = bnpCopyTo;
8021BigInteger.prototype.fromInt = bnpFromInt;
8022BigInteger.prototype.fromString = bnpFromString;
8023BigInteger.prototype.clamp = bnpClamp;
8024BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
8025BigInteger.prototype.drShiftTo = bnpDRShiftTo;
8026BigInteger.prototype.lShiftTo = bnpLShiftTo;
8027BigInteger.prototype.rShiftTo = bnpRShiftTo;
8028BigInteger.prototype.subTo = bnpSubTo;
8029BigInteger.prototype.multiplyTo = bnpMultiplyTo;
8030BigInteger.prototype.squareTo = bnpSquareTo;
8031BigInteger.prototype.divRemTo = bnpDivRemTo;
8032BigInteger.prototype.invDigit = bnpInvDigit;
8033BigInteger.prototype.isEven = bnpIsEven;
8034BigInteger.prototype.exp = bnpExp;
8035
8036// public
8037BigInteger.prototype.toString = bnToString;
8038BigInteger.prototype.negate = bnNegate;
8039BigInteger.prototype.abs = bnAbs;
8040BigInteger.prototype.compareTo = bnCompareTo;
8041BigInteger.prototype.bitLength = bnBitLength;
8042BigInteger.prototype.mod = bnMod;
8043BigInteger.prototype.modPowInt = bnModPowInt;
8044
8045// "constants"
8046BigInteger.ZERO = nbv(0);
8047BigInteger.ONE = nbv(1);
8048
8049// Copyright (c) 2005-2009 Tom Wu
8050// All Rights Reserved.
8051// See "LICENSE" for details.
8052
8053// Extended JavaScript BN functions, required for RSA private ops.
8054
8055// Version 1.1: new BigInteger("0", 10) returns "proper" zero
8056
8057// (public)
8058function bnClone() { var r = nbi(); this.copyTo(r); return r; }
8059
8060// (public) return value as integer
8061function bnIntValue() {
8062 if(this.s < 0) {
8063 if(this.t == 1) return this[0]-this.DV;
8064 else if(this.t == 0) return -1;
8065 }
8066 else if(this.t == 1) return this[0];
8067 else if(this.t == 0) return 0;
8068 // assumes 16 < DB < 32
8069 return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
8070}
8071
8072// (public) return value as byte
8073function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
8074
8075// (public) return value as short (assumes DB>=16)
8076function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
8077
8078// (protected) return x s.t. r^x < DV
8079function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
8080
8081// (public) 0 if this == 0, 1 if this > 0
8082function bnSigNum() {
8083 if(this.s < 0) return -1;
8084 else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
8085 else return 1;
8086}
8087
8088// (protected) convert to radix string
8089function bnpToRadix(b) {
8090 if(b == null) b = 10;
8091 if(this.signum() == 0 || b < 2 || b > 36) return "0";
8092 var cs = this.chunkSize(b);
8093 var a = Math.pow(b,cs);
8094 var d = nbv(a), y = nbi(), z = nbi(), r = "";
8095 this.divRemTo(d,y,z);
8096 while(y.signum() > 0) {
8097 r = (a+z.intValue()).toString(b).substr(1) + r;
8098 y.divRemTo(d,y,z);
8099 }
8100 return z.intValue().toString(b) + r;
8101}
8102
8103// (protected) convert from radix string
8104function bnpFromRadix(s,b) {
8105 this.fromInt(0);
8106 if(b == null) b = 10;
8107 var cs = this.chunkSize(b);
8108 var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
8109 for(var i = 0; i < s.length; ++i) {
8110 var x = intAt(s,i);
8111 if(x < 0) {
8112 if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
8113 continue;
8114 }
8115 w = b*w+x;
8116 if(++j >= cs) {
8117 this.dMultiply(d);
8118 this.dAddOffset(w,0);
8119 j = 0;
8120 w = 0;
8121 }
8122 }
8123 if(j > 0) {
8124 this.dMultiply(Math.pow(b,j));
8125 this.dAddOffset(w,0);
8126 }
8127 if(mi) BigInteger.ZERO.subTo(this,this);
8128}
8129
8130// (protected) alternate constructor
8131function bnpFromNumber(a,b,c) {
8132 if("number" == typeof b) {
8133 // new BigInteger(int,int,RNG)
8134 if(a < 2) this.fromInt(1);
8135 else {
8136 this.fromNumber(a,c);
8137 if(!this.testBit(a-1)) // force MSB set
8138 this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
8139 if(this.isEven()) this.dAddOffset(1,0); // force odd
8140 while(!this.isProbablePrime(b)) {
8141 this.dAddOffset(2,0);
8142 if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
8143 }
8144 }
8145 }
8146 else {
8147 // new BigInteger(int,RNG)
8148 var x = new Array(), t = a&7;
8149 x.length = (a>>3)+1;
8150 b.nextBytes(x);
8151 if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
8152 this.fromString(x,256);
8153 }
8154}
8155
8156// (public) convert to bigendian byte array
8157function bnToByteArray() {
8158 var i = this.t, r = new Array();
8159 r[0] = this.s;
8160 var p = this.DB-(i*this.DB)%8, d, k = 0;
8161 if(i-- > 0) {
8162 if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
8163 r[k++] = d|(this.s<<(this.DB-p));
8164 while(i >= 0) {
8165 if(p < 8) {
8166 d = (this[i]&((1<<p)-1))<<(8-p);
8167 d |= this[--i]>>(p+=this.DB-8);
8168 }
8169 else {
8170 d = (this[i]>>(p-=8))&0xff;
8171 if(p <= 0) { p += this.DB; --i; }
8172 }
8173 if((d&0x80) != 0) d |= -256;
8174 if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
8175 if(k > 0 || d != this.s) r[k++] = d;
8176 }
8177 }
8178 return r;
8179}
8180
8181function bnEquals(a) { return(this.compareTo(a)==0); }
8182function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
8183function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
8184
8185// (protected) r = this op a (bitwise)
8186function bnpBitwiseTo(a,op,r) {
8187 var i, f, m = Math.min(a.t,this.t);
8188 for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
8189 if(a.t < this.t) {
8190 f = a.s&this.DM;
8191 for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
8192 r.t = this.t;
8193 }
8194 else {
8195 f = this.s&this.DM;
8196 for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
8197 r.t = a.t;
8198 }
8199 r.s = op(this.s,a.s);
8200 r.clamp();
8201}
8202
8203// (public) this & a
8204function op_and(x,y) { return x&y; }
8205function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
8206
8207// (public) this | a
8208function op_or(x,y) { return x|y; }
8209function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
8210
8211// (public) this ^ a
8212function op_xor(x,y) { return x^y; }
8213function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
8214
8215// (public) this & ~a
8216function op_andnot(x,y) { return x&~y; }
8217function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
8218
8219// (public) ~this
8220function bnNot() {
8221 var r = nbi();
8222 for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
8223 r.t = this.t;
8224 r.s = ~this.s;
8225 return r;
8226}
8227
8228// (public) this << n
8229function bnShiftLeft(n) {
8230 var r = nbi();
8231 if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
8232 return r;
8233}
8234
8235// (public) this >> n
8236function bnShiftRight(n) {
8237 var r = nbi();
8238 if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
8239 return r;
8240}
8241
8242// return index of lowest 1-bit in x, x < 2^31
8243function lbit(x) {
8244 if(x == 0) return -1;
8245 var r = 0;
8246 if((x&0xffff) == 0) { x >>= 16; r += 16; }
8247 if((x&0xff) == 0) { x >>= 8; r += 8; }
8248 if((x&0xf) == 0) { x >>= 4; r += 4; }
8249 if((x&3) == 0) { x >>= 2; r += 2; }
8250 if((x&1) == 0) ++r;
8251 return r;
8252}
8253
8254// (public) returns index of lowest 1-bit (or -1 if none)
8255function bnGetLowestSetBit() {
8256 for(var i = 0; i < this.t; ++i)
8257 if(this[i] != 0) return i*this.DB+lbit(this[i]);
8258 if(this.s < 0) return this.t*this.DB;
8259 return -1;
8260}
8261
8262// return number of 1 bits in x
8263function cbit(x) {
8264 var r = 0;
8265 while(x != 0) { x &= x-1; ++r; }
8266 return r;
8267}
8268
8269// (public) return number of set bits
8270function bnBitCount() {
8271 var r = 0, x = this.s&this.DM;
8272 for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
8273 return r;
8274}
8275
8276// (public) true iff nth bit is set
8277function bnTestBit(n) {
8278 var j = Math.floor(n/this.DB);
8279 if(j >= this.t) return(this.s!=0);
8280 return((this[j]&(1<<(n%this.DB)))!=0);
8281}
8282
8283// (protected) this op (1<<n)
8284function bnpChangeBit(n,op) {
8285 var r = BigInteger.ONE.shiftLeft(n);
8286 this.bitwiseTo(r,op,r);
8287 return r;
8288}
8289
8290// (public) this | (1<<n)
8291function bnSetBit(n) { return this.changeBit(n,op_or); }
8292
8293// (public) this & ~(1<<n)
8294function bnClearBit(n) { return this.changeBit(n,op_andnot); }
8295
8296// (public) this ^ (1<<n)
8297function bnFlipBit(n) { return this.changeBit(n,op_xor); }
8298
8299// (protected) r = this + a
8300function bnpAddTo(a,r) {
8301 var i = 0, c = 0, m = Math.min(a.t,this.t);
8302 while(i < m) {
8303 c += this[i]+a[i];
8304 r[i++] = c&this.DM;
8305 c >>= this.DB;
8306 }
8307 if(a.t < this.t) {
8308 c += a.s;
8309 while(i < this.t) {
8310 c += this[i];
8311 r[i++] = c&this.DM;
8312 c >>= this.DB;
8313 }
8314 c += this.s;
8315 }
8316 else {
8317 c += this.s;
8318 while(i < a.t) {
8319 c += a[i];
8320 r[i++] = c&this.DM;
8321 c >>= this.DB;
8322 }
8323 c += a.s;
8324 }
8325 r.s = (c<0)?-1:0;
8326 if(c > 0) r[i++] = c;
8327 else if(c < -1) r[i++] = this.DV+c;
8328 r.t = i;
8329 r.clamp();
8330}
8331
8332// (public) this + a
8333function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
8334
8335// (public) this - a
8336function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
8337
8338// (public) this * a
8339function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
8340
8341// (public) this / a
8342function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
8343
8344// (public) this % a
8345function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
8346
8347// (public) [this/a,this%a]
8348function bnDivideAndRemainder(a) {
8349 var q = nbi(), r = nbi();
8350 this.divRemTo(a,q,r);
8351 return new Array(q,r);
8352}
8353
8354// (protected) this *= n, this >= 0, 1 < n < DV
8355function bnpDMultiply(n) {
8356 this[this.t] = this.am(0,n-1,this,0,0,this.t);
8357 ++this.t;
8358 this.clamp();
8359}
8360
8361// (protected) this += n << w words, this >= 0
8362function bnpDAddOffset(n,w) {
8363 if(n == 0) return;
8364 while(this.t <= w) this[this.t++] = 0;
8365 this[w] += n;
8366 while(this[w] >= this.DV) {
8367 this[w] -= this.DV;
8368 if(++w >= this.t) this[this.t++] = 0;
8369 ++this[w];
8370 }
8371}
8372
8373// A "null" reducer
8374function NullExp() {}
8375function nNop(x) { return x; }
8376function nMulTo(x,y,r) { x.multiplyTo(y,r); }
8377function nSqrTo(x,r) { x.squareTo(r); }
8378
8379NullExp.prototype.convert = nNop;
8380NullExp.prototype.revert = nNop;
8381NullExp.prototype.mulTo = nMulTo;
8382NullExp.prototype.sqrTo = nSqrTo;
8383
8384// (public) this^e
8385function bnPow(e) { return this.exp(e,new NullExp()); }
8386
8387// (protected) r = lower n words of "this * a", a.t <= n
8388// "this" should be the larger one if appropriate.
8389function bnpMultiplyLowerTo(a,n,r) {
8390 var i = Math.min(this.t+a.t,n);
8391 r.s = 0; // assumes a,this >= 0
8392 r.t = i;
8393 while(i > 0) r[--i] = 0;
8394 var j;
8395 for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
8396 for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
8397 r.clamp();
8398}
8399
8400// (protected) r = "this * a" without lower n words, n > 0
8401// "this" should be the larger one if appropriate.
8402function bnpMultiplyUpperTo(a,n,r) {
8403 --n;
8404 var i = r.t = this.t+a.t-n;
8405 r.s = 0; // assumes a,this >= 0
8406 while(--i >= 0) r[i] = 0;
8407 for(i = Math.max(n-this.t,0); i < a.t; ++i)
8408 r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
8409 r.clamp();
8410 r.drShiftTo(1,r);
8411}
8412
8413// Barrett modular reduction
8414function Barrett(m) {
8415 // setup Barrett
8416 this.r2 = nbi();
8417 this.q3 = nbi();
8418 BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
8419 this.mu = this.r2.divide(m);
8420 this.m = m;
8421}
8422
8423function barrettConvert(x) {
8424 if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
8425 else if(x.compareTo(this.m) < 0) return x;
8426 else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
8427}
8428
8429function barrettRevert(x) { return x; }
8430
8431// x = x mod m (HAC 14.42)
8432function barrettReduce(x) {
8433 x.drShiftTo(this.m.t-1,this.r2);
8434 if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
8435 this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
8436 this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
8437 while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
8438 x.subTo(this.r2,x);
8439 while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
8440}
8441
8442// r = x^2 mod m; x != r
8443function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
8444
8445// r = x*y mod m; x,y != r
8446function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
8447
8448Barrett.prototype.convert = barrettConvert;
8449Barrett.prototype.revert = barrettRevert;
8450Barrett.prototype.reduce = barrettReduce;
8451Barrett.prototype.mulTo = barrettMulTo;
8452Barrett.prototype.sqrTo = barrettSqrTo;
8453
8454// (public) this^e % m (HAC 14.85)
8455function bnModPow(e,m) {
8456 var i = e.bitLength(), k, r = nbv(1), z;
8457 if(i <= 0) return r;
8458 else if(i < 18) k = 1;
8459 else if(i < 48) k = 3;
8460 else if(i < 144) k = 4;
8461 else if(i < 768) k = 5;
8462 else k = 6;
8463 if(i < 8)
8464 z = new Classic(m);
8465 else if(m.isEven())
8466 z = new Barrett(m);
8467 else
8468 z = new Montgomery(m);
8469
8470 // precomputation
8471 var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
8472 g[1] = z.convert(this);
8473 if(k > 1) {
8474 var g2 = nbi();
8475 z.sqrTo(g[1],g2);
8476 while(n <= km) {
8477 g[n] = nbi();
8478 z.mulTo(g2,g[n-2],g[n]);
8479 n += 2;
8480 }
8481 }
8482
8483 var j = e.t-1, w, is1 = true, r2 = nbi(), t;
8484 i = nbits(e[j])-1;
8485 while(j >= 0) {
8486 if(i >= k1) w = (e[j]>>(i-k1))&km;
8487 else {
8488 w = (e[j]&((1<<(i+1))-1))<<(k1-i);
8489 if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
8490 }
8491
8492 n = k;
8493 while((w&1) == 0) { w >>= 1; --n; }
8494 if((i -= n) < 0) { i += this.DB; --j; }
8495 if(is1) { // ret == 1, don't bother squaring or multiplying it
8496 g[w].copyTo(r);
8497 is1 = false;
8498 }
8499 else {
8500 while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
8501 if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
8502 z.mulTo(r2,g[w],r);
8503 }
8504
8505 while(j >= 0 && (e[j]&(1<<i)) == 0) {
8506 z.sqrTo(r,r2); t = r; r = r2; r2 = t;
8507 if(--i < 0) { i = this.DB-1; --j; }
8508 }
8509 }
8510 return z.revert(r);
8511}
8512
8513// (public) gcd(this,a) (HAC 14.54)
8514function bnGCD(a) {
8515 var x = (this.s<0)?this.negate():this.clone();
8516 var y = (a.s<0)?a.negate():a.clone();
8517 if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
8518 var i = x.getLowestSetBit(), g = y.getLowestSetBit();
8519 if(g < 0) return x;
8520 if(i < g) g = i;
8521 if(g > 0) {
8522 x.rShiftTo(g,x);
8523 y.rShiftTo(g,y);
8524 }
8525 while(x.signum() > 0) {
8526 if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
8527 if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
8528 if(x.compareTo(y) >= 0) {
8529 x.subTo(y,x);
8530 x.rShiftTo(1,x);
8531 }
8532 else {
8533 y.subTo(x,y);
8534 y.rShiftTo(1,y);
8535 }
8536 }
8537 if(g > 0) y.lShiftTo(g,y);
8538 return y;
8539}
8540
8541// (protected) this % n, n < 2^26
8542function bnpModInt(n) {
8543 if(n <= 0) return 0;
8544 var d = this.DV%n, r = (this.s<0)?n-1:0;
8545 if(this.t > 0)
8546 if(d == 0) r = this[0]%n;
8547 else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
8548 return r;
8549}
8550
8551// (public) 1/this % m (HAC 14.61)
8552function bnModInverse(m) {
8553 var ac = m.isEven();
8554 if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
8555 var u = m.clone(), v = this.clone();
8556 var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
8557 while(u.signum() != 0) {
8558 while(u.isEven()) {
8559 u.rShiftTo(1,u);
8560 if(ac) {
8561 if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
8562 a.rShiftTo(1,a);
8563 }
8564 else if(!b.isEven()) b.subTo(m,b);
8565 b.rShiftTo(1,b);
8566 }
8567 while(v.isEven()) {
8568 v.rShiftTo(1,v);
8569 if(ac) {
8570 if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
8571 c.rShiftTo(1,c);
8572 }
8573 else if(!d.isEven()) d.subTo(m,d);
8574 d.rShiftTo(1,d);
8575 }
8576 if(u.compareTo(v) >= 0) {
8577 u.subTo(v,u);
8578 if(ac) a.subTo(c,a);
8579 b.subTo(d,b);
8580 }
8581 else {
8582 v.subTo(u,v);
8583 if(ac) c.subTo(a,c);
8584 d.subTo(b,d);
8585 }
8586 }
8587 if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
8588 if(d.compareTo(m) >= 0) return d.subtract(m);
8589 if(d.signum() < 0) d.addTo(m,d); else return d;
8590 if(d.signum() < 0) return d.add(m); else return d;
8591}
8592
8593var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
8594var lplim = (1<<26)/lowprimes[lowprimes.length-1];
8595
8596// (public) test primality with certainty >= 1-.5^t
8597function bnIsProbablePrime(t) {
8598 var i, x = this.abs();
8599 if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
8600 for(i = 0; i < lowprimes.length; ++i)
8601 if(x[0] == lowprimes[i]) return true;
8602 return false;
8603 }
8604 if(x.isEven()) return false;
8605 i = 1;
8606 while(i < lowprimes.length) {
8607 var m = lowprimes[i], j = i+1;
8608 while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
8609 m = x.modInt(m);
8610 while(i < j) if(m%lowprimes[i++] == 0) return false;
8611 }
8612 return x.millerRabin(t);
8613}
8614
8615// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
8616function bnpMillerRabin(t) {
8617 var n1 = this.subtract(BigInteger.ONE);
8618 var k = n1.getLowestSetBit();
8619 if(k <= 0) return false;
8620 var r = n1.shiftRight(k);
8621 t = (t+1)>>1;
8622 if(t > lowprimes.length) t = lowprimes.length;
8623 var a = nbi();
8624 for(var i = 0; i < t; ++i) {
8625 a.fromInt(lowprimes[i]);
8626 var y = a.modPow(r,this);
8627 if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
8628 var j = 1;
8629 while(j++ < k && y.compareTo(n1) != 0) {
8630 y = y.modPowInt(2,this);
8631 if(y.compareTo(BigInteger.ONE) == 0) return false;
8632 }
8633 if(y.compareTo(n1) != 0) return false;
8634 }
8635 }
8636 return true;
8637}
8638
8639// protected
8640BigInteger.prototype.chunkSize = bnpChunkSize;
8641BigInteger.prototype.toRadix = bnpToRadix;
8642BigInteger.prototype.fromRadix = bnpFromRadix;
8643BigInteger.prototype.fromNumber = bnpFromNumber;
8644BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
8645BigInteger.prototype.changeBit = bnpChangeBit;
8646BigInteger.prototype.addTo = bnpAddTo;
8647BigInteger.prototype.dMultiply = bnpDMultiply;
8648BigInteger.prototype.dAddOffset = bnpDAddOffset;
8649BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
8650BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
8651BigInteger.prototype.modInt = bnpModInt;
8652BigInteger.prototype.millerRabin = bnpMillerRabin;
8653
8654// public
8655BigInteger.prototype.clone = bnClone;
8656BigInteger.prototype.intValue = bnIntValue;
8657BigInteger.prototype.byteValue = bnByteValue;
8658BigInteger.prototype.shortValue = bnShortValue;
8659BigInteger.prototype.signum = bnSigNum;
8660BigInteger.prototype.toByteArray = bnToByteArray;
8661BigInteger.prototype.equals = bnEquals;
8662BigInteger.prototype.min = bnMin;
8663BigInteger.prototype.max = bnMax;
8664BigInteger.prototype.and = bnAnd;
8665BigInteger.prototype.or = bnOr;
8666BigInteger.prototype.xor = bnXor;
8667BigInteger.prototype.andNot = bnAndNot;
8668BigInteger.prototype.not = bnNot;
8669BigInteger.prototype.shiftLeft = bnShiftLeft;
8670BigInteger.prototype.shiftRight = bnShiftRight;
8671BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
8672BigInteger.prototype.bitCount = bnBitCount;
8673BigInteger.prototype.testBit = bnTestBit;
8674BigInteger.prototype.setBit = bnSetBit;
8675BigInteger.prototype.clearBit = bnClearBit;
8676BigInteger.prototype.flipBit = bnFlipBit;
8677BigInteger.prototype.add = bnAdd;
8678BigInteger.prototype.subtract = bnSubtract;
8679BigInteger.prototype.multiply = bnMultiply;
8680BigInteger.prototype.divide = bnDivide;
8681BigInteger.prototype.remainder = bnRemainder;
8682BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
8683BigInteger.prototype.modPow = bnModPow;
8684BigInteger.prototype.modInverse = bnModInverse;
8685BigInteger.prototype.pow = bnPow;
8686BigInteger.prototype.gcd = bnGCD;
8687BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
8688
8689// BigInteger interfaces not implemented in jsbn:
8690
8691// BigInteger(int signum, byte[] magnitude)
8692// double doubleValue()
8693// float floatValue()
8694// int hashCode()
8695// long longValue()
8696// static BigInteger valueOf(long val)
8697