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