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