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