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