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