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