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