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