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