blob: 39c76617fa1d9c8360e6e0ca238044faccc1be08 [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
Jeff Thompson6576bbb2012-10-28 22:20:02 -07002551 if (null == blob)
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002552 return;
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002553
2554 if(LOG>4) console.log('LENGTH OF XML_BLOB IS '+length);
2555
2556
2557 blobCopy = new Array(blob.Length);
2558 var i = 0;
2559 for( ;i<blob.length;i++) //in InStr.ToCharArray())
2560 {
2561 blobCopy[i] = blob[i];
2562 }
2563
2564 this.encodeTypeAndVal(XML_BLOB, length, ostream,offset);
2565
2566 if (null != blob) {
2567
2568 this.writeBlobArray(blobCopy,this.offset);
2569 this.offset += length;
2570 }
2571};
2572
2573var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
2574var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
2575var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
2576
2577BinaryXMLEncoder.prototype.numEncodingBytes = function(
2578 //long
2579 x) {
2580 if (x <= ENCODING_LIMIT_1_BYTE) return (1);
2581 if (x <= ENCODING_LIMIT_2_BYTES) return (2);
2582 if (x <= ENCODING_LIMIT_3_BYTES) return (3);
2583
2584 var numbytes = 1;
2585
2586 // Last byte gives you XML_TT_VAL_BITS
2587 // Remainder each give you XML_REG_VAL_BITS
2588 x = x >>> XML_TT_VAL_BITS;
2589 while (x != 0) {
2590 numbytes++;
2591 x = x >>> XML_REG_VAL_BITS;
2592 }
2593 return (numbytes);
2594};
2595
2596BinaryXMLEncoder.prototype.writeDateTime = function(
2597 //String
2598 tag,
2599 //CCNTime
2600 dateTime) {
2601
2602 if(LOG>4)console.log('ENCODING DATE with LONG VALUE');
2603 if(LOG>4)console.log(dateTime.msec);
2604
2605 //var binarydate = DataUtils.unsignedLongToByteArray( Math.round((dateTime.msec/1000) * 4096) );
2606
2607
2608 //parse to hex
2609 var binarydate = Math.round((dateTime.msec/1000) * 4096).toString(16) ;
2610
2611 //HACK
2612 var binarydate = DataUtils.toNumbers( '0'.concat(binarydate,'0')) ;
2613
2614
2615 if(LOG>4)console.log('ENCODING DATE with BINARY VALUE');
2616 if(LOG>4)console.log(binarydate);
2617
2618 if(LOG>4)console.log('ENCODING DATE with BINARY VALUE(HEX)');
2619 if(LOG>4)console.log(DataUtils.toHex(binarydate));
2620
2621
2622 this.writeElement(tag, binarydate);
2623
2624};
2625
2626BinaryXMLEncoder.prototype.writeString = function(
2627 //String
2628 input,
2629 //CCNTime
2630 offset) {
2631
2632 if(typeof input === 'string'){
2633 //console.log('went here');
2634 if(LOG>4) console.log('GOING TO WRITE A STRING');
2635 if(LOG>4) console.log(input);
2636
2637 for (var i = 0; i < input.length; i++) {
2638 if(LOG>4) console.log('input.charCodeAt(i)=' + input.charCodeAt(i));
2639 this.ostream[this.offset+i] = (input.charCodeAt(i));
2640 }
2641 }
2642
2643 else{
2644
2645 if(LOG>4) console.log('GOING TO WRITE A STRING IN BINARY FORM');
2646 if(LOG>4) console.log(input);
2647
2648 this.writeBlobArray(input);
2649
2650 }
2651 /*
2652 else if(typeof input === 'object'){
2653
2654 }
2655 */
2656};
2657
2658BinaryXMLEncoder.prototype.writeBlobArray = function(
2659 //String
2660 Blob,
2661 //CCNTime
2662 offset) {
2663
2664 if(LOG>4) console.log('GOING TO WRITE A BLOB');
2665
2666 for (var i = 0; i < Blob.length; i++) {
2667 this.ostream[this.offset+i] = Blob[i];
2668 }
2669
2670};
2671
2672
2673
2674BinaryXMLEncoder.prototype.getReducedOstream = function() {
2675
2676 return this.ostream.slice(0,this.offset);
2677
2678};
2679
2680
2681/*
Jeff Thompsondad617b2012-10-14 17:11:41 -07002682 * This class is used to decode ccnb binary elements (blob, type/value pairs).
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002683 *
2684 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07002685 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002686 */
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002687
2688var XML_EXT = 0x00;
2689
2690var XML_TAG = 0x01;
2691
2692var XML_DTAG = 0x02;
2693
2694var XML_ATTR = 0x03;
2695
2696var XML_DATTR = 0x04;
2697
2698var XML_BLOB = 0x05;
2699
2700var XML_UDATA = 0x06;
2701
2702var XML_CLOSE = 0x0;
2703
2704var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16;
2705
2706
2707var XML_TT_BITS = 3;
2708var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
2709var XML_TT_VAL_BITS = XML_TT_BITS + 1;
2710var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
2711var XML_REG_VAL_BITS = 7;
2712var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
2713var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
2714var BYTE_MASK = 0xFF;
2715var LONG_BYTES = 8;
2716var LONG_BITS = 64;
2717
2718var bits_11 = 0x0000007FF;
2719var bits_18 = 0x00003FFFF;
2720var bits_32 = 0x0FFFFFFFF;
2721
2722
2723
2724//returns a string
2725tagToString = function(/*long*/ tagVal) {
2726 if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
2727 return CCNProtocolDTagsStrings[tagVal];
2728 } else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
2729 return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
2730 }
2731 return null;
2732};
2733
2734//returns a Long
2735stringToTag = function(/*String*/ tagName) {
2736 // the slow way, but right now we don't care.... want a static lookup for the forward direction
2737 for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
2738 if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
2739 return i;
2740 }
2741 }
2742 if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
2743 return CCNProtocolDTags.CCNProtocolDataUnit;
2744 }
2745 return null;
2746};
2747
2748//console.log(stringToTag(64));
2749var BinaryXMLDecoder = function BinaryXMLDecoder(istream){
2750 var MARK_LEN=512;
2751 var DEBUG_MAX_LEN = 32768;
2752
2753 this.istream = istream;
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002754 this.offset = 0;
2755};
2756
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002757BinaryXMLDecoder.prototype.readAttributes = function(
2758 //TreeMap<String,String>
2759 attributes){
2760
2761 if (null == attributes) {
2762 return;
2763 }
2764
2765 try {
2766
2767 //this.TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07002768 nextTV = this.peekTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002769
2770 while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
2771 (XML_DATTR == nextTV.type()))) {
2772
2773 //this.TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07002774 thisTV = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002775
2776 var attributeName = null;
2777 if (XML_ATTR == thisTV.type()) {
2778
Jeff Thompsondad617b2012-10-14 17:11:41 -07002779 attributeName = this.decodeUString(thisTV.val()+1);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002780
2781 } else if (XML_DATTR == thisTV.type()) {
2782 // DKS TODO are attributes same or different dictionary?
2783 attributeName = tagToString(thisTV.val());
2784 if (null == attributeName) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -07002785 throw new ContentDecodingException(new Error("Unknown DATTR value" + thisTV.val()));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002786 }
2787 }
2788
Jeff Thompsondad617b2012-10-14 17:11:41 -07002789 var attributeValue = this.decodeUString();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002790
2791 attributes.put(attributeName, attributeValue);
2792
Jeff Thompsondad617b2012-10-14 17:11:41 -07002793 nextTV = this.peekTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002794 }
2795
2796 } catch ( e) {
2797
Jeff Thompsoncab74c32012-10-21 13:27:28 -07002798 throw new ContentDecodingException(new Error("readStartElement", e));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002799 }
2800};
2801
2802
2803BinaryXMLDecoder.prototype.initializeDecoding = function() {
2804 //if (!this.istream.markSupported()) {
2805 //throw new IllegalArgumentException(this.getClass().getName() + ": input stream must support marking!");
2806 //}
2807}
2808
2809BinaryXMLDecoder.prototype.readStartDocument = function(){
2810 // Currently no start document in binary encoding.
2811 }
2812
2813BinaryXMLDecoder.prototype.readEndDocument = function() {
2814 // Currently no end document in binary encoding.
2815 };
2816
2817BinaryXMLDecoder.prototype.readStartElement = function(
2818 //String
2819 startTag,
2820 //TreeMap<String, String>
2821 attributes) {
2822
2823
2824 //NOT SURE
2825 //if(typeof startTag == 'number')
2826 //startTag = tagToString(startTag);
2827
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002828 //TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07002829 tv = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002830
2831 if (null == tv) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -07002832 throw new ContentDecodingException(new Error("Expected start element: " + startTag + " got something not a tag."));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002833 }
2834
2835 //String
2836 decodedTag = null;
2837 //console.log(tv);
2838 //console.log(typeof tv);
2839
2840 //console.log(XML_TAG);
2841 if (tv.type() == XML_TAG) {
2842 //console.log('got here');
2843 //Log.info(Log.FAC_ENCODING, "Unexpected: got tag in readStartElement; looking for tag " + startTag + " got length: " + (int)tv.val()+1);
2844 // Tag value represents length-1 as tags can never be empty.
2845 var valval ;
2846 if(typeof tv.val() == 'string'){
2847 valval = (parseInt(tv.val())) + 1;
2848 }
2849 else
2850 valval = (tv.val())+ 1;
2851
2852 //console.log('valval is ' +valval);
2853
Jeff Thompsondad617b2012-10-14 17:11:41 -07002854 decodedTag = this.decodeUString(valval);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002855
2856 } else if (tv.type() == XML_DTAG) {
2857 //console.log('gothere');
2858 //console.log(tv.val());
2859 //decodedTag = tagToString(tv.val());
2860 //console.log()
2861 decodedTag = tv.val();
2862 }
2863
2864 //console.log(decodedTag);
2865 //console.log('startTag is '+startTag);
2866
2867
2868 if ((null == decodedTag) || decodedTag != startTag ) {
2869 console.log('expecting '+ startag + ' but got '+ decodedTag);
Jeff Thompsoncab74c32012-10-21 13:27:28 -07002870 throw new ContentDecodingException(new Error("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")"));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002871 }
2872
2873 // DKS: does not read attributes out of stream if caller doesn't
2874 // ask for them. Should possibly peek and skip over them regardless.
2875 // TODO: fix this
2876 if (null != attributes) {
2877 readAttributes(attributes);
2878 }
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002879 }
2880
2881
2882BinaryXMLDecoder.prototype.readAttributes = function(
2883 //TreeMap<String,String>
2884 attributes) {
2885
2886 if (null == attributes) {
2887 return;
2888 }
2889
2890 try {
2891 // Now need to get attributes.
2892 //TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07002893 nextTV = this.peekTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002894
2895 while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
2896 (XML_DATTR == nextTV.type()))) {
2897
2898 // Decode this attribute. First, really read the type and value.
2899 //this.TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07002900 thisTV = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002901
2902 //String
2903 attributeName = null;
2904 if (XML_ATTR == thisTV.type()) {
2905 // Tag value represents length-1 as attribute names cannot be empty.
2906 var valval ;
2907 if(typeof tv.val() == 'string'){
2908 valval = (parseInt(tv.val())) + 1;
2909 }
2910 else
2911 valval = (tv.val())+ 1;
2912
Jeff Thompsondad617b2012-10-14 17:11:41 -07002913 attributeName = this.decodeUString(valval);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002914
2915 } else if (XML_DATTR == thisTV.type()) {
2916 // DKS TODO are attributes same or different dictionary?
2917 attributeName = tagToString(thisTV.val());
2918 if (null == attributeName) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -07002919 throw new ContentDecodingException(new Error("Unknown DATTR value" + thisTV.val()));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002920 }
2921 }
2922 // Attribute values are always UDATA
2923 //String
Jeff Thompsondad617b2012-10-14 17:11:41 -07002924 attributeValue = this.decodeUString();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002925
2926 //
2927 attributes.push([attributeName, attributeValue]);
2928
Jeff Thompsondad617b2012-10-14 17:11:41 -07002929 nextTV = this.peekTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002930 }
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002931 } catch ( e) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -07002932 throw new ContentDecodingException(new Error("readStartElement", e));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002933 }
2934};
2935
2936//returns a string
2937BinaryXMLDecoder.prototype.peekStartElementAsString = function() {
2938 //this.istream.mark(MARK_LEN);
2939
2940 //String
2941 decodedTag = null;
2942 var previousOffset = this.offset;
2943 try {
2944 // Have to distinguish genuine errors from wrong tags. Could either use
2945 // a special exception subtype, or redo the work here.
2946 //this.TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07002947 tv = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002948
2949 if (null != tv) {
2950
2951 if (tv.type() == XML_TAG) {
2952 /*if (tv.val()+1 > DEBUG_MAX_LEN) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -07002953 throw new ContentDecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!")(;
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002954 }*/
2955
2956 // Tag value represents length-1 as tags can never be empty.
2957 var valval ;
2958 if(typeof tv.val() == 'string'){
2959 valval = (parseInt(tv.val())) + 1;
2960 }
2961 else
2962 valval = (tv.val())+ 1;
2963
Jeff Thompsondad617b2012-10-14 17:11:41 -07002964 decodedTag = this.decodeUString(valval);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002965
2966 //Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
2967
2968 } else if (tv.type() == XML_DTAG) {
2969 decodedTag = tagToString(tv.val());
2970 }
2971
2972 } // else, not a type and val, probably an end element. rewind and return false.
2973
2974 } catch ( e) {
2975
2976 } finally {
2977 try {
2978 this.offset = previousOffset;
2979 } catch ( e) {
2980 Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
Jeff Thompsoncab74c32012-10-21 13:27:28 -07002981 throw new ContentDecodingException(new Error("Cannot reset stream! " + e.getMessage(), e));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07002982 }
2983 }
2984 return decodedTag;
2985};
2986
2987BinaryXMLDecoder.prototype.peekStartElement = function(
2988 //String
2989 startTag) {
2990 //String
2991 if(typeof startTag == 'string'){
2992 decodedTag = this.peekStartElementAsString();
2993
2994 if ((null != decodedTag) && decodedTag == startTag) {
2995 return true;
2996 }
2997 return false;
2998 }
2999 else if(typeof startTag == 'number'){
3000 decodedTag = this.peekStartElementAsLong();
3001 if ((null != decodedTag) && decodedTag == startTag) {
3002 return true;
3003 }
3004 return false;
3005 }
3006 else{
Jeff Thompsoncab74c32012-10-21 13:27:28 -07003007 throw new ContentDecodingException(new Error("SHOULD BE STRING OR NUMBER"));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003008 }
3009}
3010//returns Long
3011BinaryXMLDecoder.prototype.peekStartElementAsLong = function() {
3012 //this.istream.mark(MARK_LEN);
3013
3014 //Long
3015 decodedTag = null;
3016
3017 var previousOffset = this.offset;
3018
3019 try {
3020 // Have to distinguish genuine errors from wrong tags. Could either use
3021 // a special exception subtype, or redo the work here.
3022 //this.TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07003023 tv = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003024
3025 if (null != tv) {
3026
3027 if (tv.type() == XML_TAG) {
3028 if (tv.val()+1 > DEBUG_MAX_LEN) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -07003029 throw new ContentDecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!"));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003030 }
3031
3032 var valval ;
3033 if(typeof tv.val() == 'string'){
3034 valval = (parseInt(tv.val())) + 1;
3035 }
3036 else
3037 valval = (tv.val())+ 1;
3038
3039 // Tag value represents length-1 as tags can never be empty.
3040 //String
Jeff Thompsondad617b2012-10-14 17:11:41 -07003041 strTag = this.decodeUString(valval);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003042
3043 decodedTag = stringToTag(strTag);
3044
3045 //Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
3046
3047 } else if (tv.type() == XML_DTAG) {
3048 decodedTag = tv.val();
3049 }
3050
3051 } // else, not a type and val, probably an end element. rewind and return false.
3052
3053 } catch ( e) {
3054
3055 } finally {
3056 try {
3057 //this.istream.reset();
3058 this.offset = previousOffset;
3059 } catch ( e) {
3060 Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
3061 throw new Error("Cannot reset stream! " + e.getMessage(), e);
3062 }
3063 }
3064 return decodedTag;
3065 };
3066
3067
3068// returns a byte[]
3069BinaryXMLDecoder.prototype.readBinaryElement = function(
3070 //long
3071 startTag,
3072 //TreeMap<String, String>
3073 attributes){
3074 //byte []
3075 blob = null;
3076
3077 this.readStartElement(startTag, attributes);
3078 blob = this.readBlob();
3079
3080
3081 return blob;
3082
3083};
3084
3085
3086BinaryXMLDecoder.prototype.readEndElement = function(){
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003087 if(LOG>4)console.log('this.offset is '+this.offset);
3088
3089 var next = this.istream[this.offset];
3090
3091 this.offset++;
3092 //read();
3093
3094 if(LOG>4)console.log('XML_CLOSE IS '+XML_CLOSE);
3095 if(LOG>4)console.log('next is '+next);
3096
3097 if (next != XML_CLOSE) {
3098 console.log("Expected end element, got: " + next);
Jeff Thompsoncab74c32012-10-21 13:27:28 -07003099 throw new ContentDecodingException(new Error("Expected end element, got: " + next));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003100 }
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003101 };
3102
3103
3104//String
3105BinaryXMLDecoder.prototype.readUString = function(){
3106 //String
Jeff Thompsondad617b2012-10-14 17:11:41 -07003107 ustring = this.decodeUString();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003108 this.readEndElement();
3109 return ustring;
3110
3111 };
3112
3113
3114//returns a byte[]
3115BinaryXMLDecoder.prototype.readBlob = function() {
3116 //byte []
3117
Jeff Thompsondad617b2012-10-14 17:11:41 -07003118 blob = this.decodeBlob();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003119 this.readEndElement();
3120 return blob;
3121
3122 };
3123
3124
3125//CCNTime
3126BinaryXMLDecoder.prototype.readDateTime = function(
3127 //long
3128 startTag) {
3129 //byte []
3130
3131 var byteTimestamp = this.readBinaryElement(startTag);
3132
3133 //var lontimestamp = DataUtils.byteArrayToUnsignedLong(byteTimestamp);
3134
3135 var byteTimestamp = DataUtils.toHex(byteTimestamp);
3136
3137
3138 var byteTimestamp = parseInt(byteTimestamp, 16);
3139
3140 lontimestamp = (byteTimestamp/ 4096) * 1000;
3141
3142 //if(lontimestamp<0) lontimestamp = - lontimestamp;
3143
3144 if(LOG>3) console.log('DECODED DATE WITH VALUE');
3145 if(LOG>3) console.log(lontimestamp);
3146
3147
3148 //CCNTime
3149 timestamp = new CCNTime(lontimestamp);
3150 //timestamp.setDateBinary(byteTimestamp);
3151
3152 if (null == timestamp) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -07003153 throw new ContentDecodingException(new Error("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp)));
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003154 }
3155 return timestamp;
3156};
3157
Jeff Thompsondad617b2012-10-14 17:11:41 -07003158BinaryXMLDecoder.prototype.decodeTypeAndVal = function() {
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003159
Jeff Thompson6576bbb2012-10-28 22:20:02 -07003160 /*int*/var type = -1;
3161 /*long*/var val = 0;
3162 /*boolean*/var more = true;
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003163
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003164 do {
3165
3166 var next = this.istream[this.offset ];
3167
3168
3169 if (next < 0) {
3170 return null;
3171 }
3172
3173 if ((0 == next) && (0 == val)) {
3174 return null;
3175 }
3176
3177 more = (0 == (next & XML_TT_NO_MORE));
3178
3179 if (more) {
3180 val = val << XML_REG_VAL_BITS;
3181 val |= (next & XML_REG_VAL_MASK);
3182 } else {
3183
3184 type = next & XML_TT_MASK;
3185 val = val << XML_TT_VAL_BITS;
3186 val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
3187 }
3188
3189 this.offset++;
3190
3191 } while (more);
3192
3193 if(LOG>3)console.log('TYPE is '+ type + ' VAL is '+ val);
3194
3195 return new TypeAndVal(type, val);
3196};
3197
3198
3199
3200//TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07003201BinaryXMLDecoder.peekTypeAndVal = function() {
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003202 //TypeAndVal
3203 tv = null;
3204
Jeff Thompsondad617b2012-10-14 17:11:41 -07003205 //this.istream.mark(LONG_BYTES*2);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003206
3207 var previousOffset = this.offset;
3208
3209 try {
Jeff Thompsondad617b2012-10-14 17:11:41 -07003210 tv = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003211 } finally {
Jeff Thompsondad617b2012-10-14 17:11:41 -07003212 //this.istream.reset();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003213 this.offset = previousOffset;
3214 }
3215
3216 return tv;
3217};
3218
3219
3220//byte[]
3221BinaryXMLDecoder.prototype.decodeBlob = function(
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003222 //int
3223 blobLength) {
3224
3225
3226 if(null == blobLength){
3227 //TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07003228 tv = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003229
3230 var valval ;
3231
3232 if(typeof tv.val() == 'string'){
3233 valval = (parseInt(tv.val()));
3234 }
3235 else
3236 valval = (tv.val());
3237
3238 //console.log('valval here is ' + valval);
Jeff Thompsondad617b2012-10-14 17:11:41 -07003239 return this.decodeBlob(valval);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003240 }
3241
3242 //
3243 //byte []
3244
Jeff Thompson6576bbb2012-10-28 22:20:02 -07003245 var bytes = this.istream.slice(this.offset, this.offset+ blobLength);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003246 this.offset += blobLength;
3247
3248 //int
3249 return bytes;
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003250};
3251
3252var count =0;
3253
3254//String
3255BinaryXMLDecoder.prototype.decodeUString = function(
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003256 //int
3257 byteLength) {
3258
3259 /*
3260 console.log('COUNT IS '+count);
3261 console.log('INPUT BYTELENGTH IS '+byteLength);
3262 count++;
3263 if(null == byteLength|| undefined == byteLength){
3264 console.log("!!!!");
Jeff Thompsondad617b2012-10-14 17:11:41 -07003265 tv = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003266 var valval ;
3267 if(typeof tv.val() == 'string'){
3268 valval = (parseInt(tv.val()));
3269 }
3270 else
3271 valval = (tv.val());
3272
3273 if(LOG>4) console.log('valval is ' + valval);
Jeff Thompsondad617b2012-10-14 17:11:41 -07003274 byteLength= this.decodeUString(valval);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003275
3276 //if(LOG>4) console.log('byte Length found in type val is '+ byteLength.charCodeAt(0));
3277 byteLength = parseInt(byteLength);
3278
3279
3280 //byteLength = byteLength.charCodeAt(0);
3281 //if(LOG>4) console.log('byte Length found in type val is '+ byteLength);
3282 }
3283 if(LOG>4)console.log('byteLength is '+byteLength);
3284 if(LOG>4)console.log('type of byteLength is '+typeof byteLength);
3285
Jeff Thompsondad617b2012-10-14 17:11:41 -07003286 stringBytes = this.decodeBlob(byteLength);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003287
3288 //console.log('String bytes are '+ stringBytes);
3289 //console.log('stringBytes);
3290
3291 if(LOG>4)console.log('byteLength is '+byteLength);
3292 if(LOG>4)console.log('this.offset is '+this.offset);
3293
3294 tempBuffer = this.istream.slice(this.offset, this.offset+byteLength);
3295 if(LOG>4)console.log('TEMPBUFFER IS' + tempBuffer);
3296 if(LOG>4)console.log( tempBuffer);
3297
3298 if(LOG>4)console.log('ADDING to offset value' + byteLength);
3299 this.offset+= byteLength;
3300 //if(LOG>3)console.log('read the String' + tempBuffer.toString('ascii'));
3301 //return tempBuffer.toString('ascii');//
3302
3303
3304 //if(LOG>3)console.log( 'STRING READ IS '+ DataUtils.getUTF8StringFromBytes(stringBytes) ) ;
3305 //if(LOG>3)console.log( 'STRING READ IS '+ DataUtils.getUTF8StringFromBytes(tempBuffer) ) ;
3306 //if(LOG>3)console.log(DataUtils.getUTF8StringFromBytes(tempBuffer) ) ;
3307 //return DataUtils.getUTF8StringFromBytes(tempBuffer);
3308
3309 if(LOG>3)console.log( 'STRING READ IS '+ DataUtils.toString(stringBytes) ) ;
3310 if(LOG>3)console.log( 'TYPE OF STRING READ IS '+ typeof DataUtils.toString(stringBytes) ) ;
3311
3312 return DataUtils.toString(stringBytes);*/
3313
3314 if(null == byteLength ){
3315 var tempStreamPosition = this.offset;
3316
3317 //TypeAndVal
Jeff Thompsondad617b2012-10-14 17:11:41 -07003318 tv = this.decodeTypeAndVal();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003319
3320 if(LOG>3)console.log('TV is '+tv);
3321 if(LOG>3)console.log(tv);
3322
3323 if(LOG>3)console.log('Type of TV is '+typeof tv);
3324
3325 if ((null == tv) || (XML_UDATA != tv.type())) { // if we just have closers left, will get back null
3326 //if (Log.isLoggable(Log.FAC_ENCODING, Level.FINEST))
3327 //Log.finest(Log.FAC_ENCODING, "Expected UDATA, got " + ((null == tv) ? " not a tag " : tv.type()) + ", assuming elided 0-length blob.");
3328
3329 this.offset = tempStreamPosition;
3330
3331 return "";
3332 }
3333
Jeff Thompsondad617b2012-10-14 17:11:41 -07003334 return this.decodeUString(tv.val());
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003335 }
3336 else{
3337 //byte []
Jeff Thompsondad617b2012-10-14 17:11:41 -07003338 stringBytes = this.decodeBlob(byteLength);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003339
3340 //return DataUtils.getUTF8StringFromBytes(stringBytes);
3341 return DataUtils.toString(stringBytes);
3342
3343 }
3344};
3345
3346
3347
3348
3349//OBject containg a pair of type and value
3350var TypeAndVal = function TypeAndVal(_type,_val) {
3351 this.t = _type;
3352 this.v = _val;
3353};
3354
3355TypeAndVal.prototype.type = function(){
3356 return this.t;
3357};
3358
3359TypeAndVal.prototype.val = function(){
3360 return this.v;
3361};
3362//TODO
3363
3364
3365
3366
3367
3368
3369BinaryXMLDecoder.prototype.readIntegerElement =function(
3370 //String
3371 startTag) {
3372
3373 //String
3374 if(LOG>4) console.log('READING INTEGER '+ startTag);
3375 if(LOG>4) console.log('TYPE OF '+ typeof startTag);
3376
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003377 strVal = this.readUTF8Element(startTag);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003378
3379 return parseInt(strVal);
3380};
3381
3382
3383BinaryXMLDecoder.prototype.readUTF8Element =function(
3384 //String
3385 startTag,
3386 //TreeMap<String, String>
3387 attributes) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -07003388 //throws Error where name == "ContentDecodingException"
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003389
3390 this.readStartElement(startTag, attributes); // can't use getElementText, can't get attributes
3391 //String
3392 strElementText = this.readUString();
3393 return strElementText;
3394};
3395
Jeff Thompsondad617b2012-10-14 17:11:41 -07003396/*
3397 * Set the offset into the input, used for the next read.
3398 */
3399BinaryXMLDecoder.prototype.seek = function(
3400 //int
3401 offset) {
3402 this.offset = offset;
3403}
3404
3405/*
Jeff Thompsoncab74c32012-10-21 13:27:28 -07003406 * Call with: throw new ContentDecodingException(new Error("message")).
3407 */
3408function ContentDecodingException(error) {
3409 this.message = error.message;
3410 // Copy lineNumber, etc. from where new Error was called.
3411 for (var prop in error)
3412 this[prop] = error[prop];
3413}
3414ContentDecodingException.prototype = new Error();
3415ContentDecodingException.prototype.name = "ContentDecodingException";
3416
3417
3418
3419/*
Jeff Thompsondad617b2012-10-14 17:11:41 -07003420 * This class uses BinaryXMLDecoder to follow the structure of a ccnb binary element to
3421 * determine its end.
3422 *
3423 * @author: ucla-cs
3424 * See COPYING for copyright and distribution information.
3425 */
3426
3427var BinaryXMLStructureDecoder = function BinaryXMLDecoder() {
3428 this.gotElementEnd = false;
3429 this.offset = 0;
3430 this.level = 0;
3431 this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
3432 this.headerStartOffset = 0;
3433 this.readBytesEndOffset = 0;
3434};
3435
3436BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE = 0;
3437BinaryXMLStructureDecoder.READ_BYTES = 1;
3438
3439/*
3440 * Continue scanning input starting from this.offset. If found the end of the element
3441 * which started at offset 0 then return true, else false.
3442 * If this returns false, you should read more into input and call again.
3443 * You have to pass in input each time because the array could be reallocated.
3444 * This throws an exception for badly formed ccnb.
3445 */
3446BinaryXMLStructureDecoder.prototype.findElementEnd = function(
3447 // byte array
3448 input)
3449{
3450 if (this.gotElementEnd)
3451 // Someone is calling when we already got the end.
3452 return true;
3453
3454 var decoder = new BinaryXMLDecoder(input);
3455
3456 while (true) {
3457 if (this.offset >= input.length)
3458 // All the cases assume we have some input.
3459 return false;
3460
3461 switch (this.state) {
3462 case BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE:
3463 // First check for XML_CLOSE.
3464 if (this.offset == this.headerStartOffset && input[this.offset] == XML_CLOSE) {
3465 ++this.offset;
3466 // Close the level.
3467 --this.level;
3468 if (this.level == 0)
3469 // Finished.
3470 return true;
3471 if (this.level < 0)
3472 throw new Error("BinaryXMLStructureDecoder: Unexepected close tag at offset " +
3473 (this.offset - 1));
3474
3475 // Get ready for the next header.
3476 this.headerStartOffset = this.offset;
3477 break;
3478 }
3479
3480 while (true) {
3481 if (this.offset >= input.length)
3482 return false;
3483 if (input[this.offset++] & XML_TT_NO_MORE)
3484 // Break and read the header.
3485 break;
3486 }
3487
3488 decoder.seek(this.headerStartOffset);
3489 var typeAndVal = decoder.decodeTypeAndVal();
3490 if (typeAndVal == null)
3491 throw new Error("BinaryXMLStructureDecoder: Can't read header starting at offset " +
3492 this.headerStartOffset);
3493
3494 // Set the next state based on the type.
3495 var type = typeAndVal.t;
3496 if (type == XML_DATTR)
3497 // We already consumed the item. READ_HEADER_OR_CLOSE again.
3498 // ccnb has rules about what must follow an attribute, but we are just scanning.
3499 this.headerStartOffset = this.offset;
3500 else if (type == XML_DTAG || type == XML_EXT) {
3501 // Start a new level and READ_HEADER_OR_CLOSE again.
3502 ++this.level;
3503 this.headerStartOffset = this.offset;
3504 }
3505 else if (type == XML_TAG || type == XML_ATTR) {
3506 if (type == XML_TAG)
3507 // Start a new level and read the tag.
3508 ++this.level;
3509 // Minimum tag or attribute length is 1.
3510 this.readBytesEndOffset = this.offset + typeAndVal.v + 1;
3511 this.state = BinaryXMLStructureDecoder.READ_BYTES;
3512 // ccnb has rules about what must follow an attribute, but we are just scanning.
3513 }
3514 else if (type == XML_BLOB || type == XML_UDATA) {
3515 this.readBytesEndOffset = this.offset + typeAndVal.v;
3516 this.state = BinaryXMLStructureDecoder.READ_BYTES;
3517 }
3518 else
3519 throw new Error("BinaryXMLStructureDecoder: Unrecognized header type " + type);
3520 break;
3521
3522 case BinaryXMLStructureDecoder.READ_BYTES:
3523 if (input.length < this.readBytesEndOffset) {
3524 // Need more.
3525 this.offset = input.length;
3526 return false;
3527 }
3528 // Got the bytes. Read a new header or close.
3529 this.offset = this.readBytesEndOffset;
3530 this.headerStartOffset = this.offset;
3531 this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
3532 break;
3533
3534 default:
3535 // We don't expect this to happen.
3536 throw new Error("BinaryXMLStructureDecoder: Unrecognized state " + this.state);
3537 }
3538 }
3539};
3540
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003541/*
3542 * This class contains utilities to help parse the data
3543 * author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07003544 * See COPYING for copyright and distribution information.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003545 */
3546
3547var DataUtils = function DataUtils(){
3548
3549
3550};
3551
3552
3553/*
3554 * NOTE THIS IS CURRENTLY NOT BEHING USED
3555 *
3556 */
3557
3558DataUtils.keyStr = "ABCDEFGHIJKLMNOP" +
3559 "QRSTUVWXYZabcdef" +
3560 "ghijklmnopqrstuv" +
3561 "wxyz0123456789+/" +
3562 "=";
3563
3564
3565/**
3566 * Raw String to Base 64
3567 */
3568DataUtils.stringtoBase64=function stringtoBase64(input) {
3569 input = escape(input);
3570 var output = "";
3571 var chr1, chr2, chr3 = "";
3572 var enc1, enc2, enc3, enc4 = "";
3573 var i = 0;
3574
3575 do {
3576 chr1 = input.charCodeAt(i++);
3577 chr2 = input.charCodeAt(i++);
3578 chr3 = input.charCodeAt(i++);
3579
3580 enc1 = chr1 >> 2;
3581 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
3582 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
3583 enc4 = chr3 & 63;
3584
3585 if (isNaN(chr2)) {
3586 enc3 = enc4 = 64;
3587 } else if (isNaN(chr3)) {
3588 enc4 = 64;
3589 }
3590
3591 output = output +
3592 DataUtils.keyStr.charAt(enc1) +
3593 DataUtils.keyStr.charAt(enc2) +
3594 DataUtils.keyStr.charAt(enc3) +
3595 DataUtils.keyStr.charAt(enc4);
3596 chr1 = chr2 = chr3 = "";
3597 enc1 = enc2 = enc3 = enc4 = "";
3598 } while (i < input.length);
3599
3600 return output;
3601 }
3602
3603/**
3604 * Base 64 to Raw String
3605 */
3606DataUtils.base64toString = function base64toString(input) {
3607 var output = "";
3608 var chr1, chr2, chr3 = "";
3609 var enc1, enc2, enc3, enc4 = "";
3610 var i = 0;
3611
3612 // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
3613 var base64test = /[^A-Za-z0-9\+\/\=]/g;
3614 /* Test for invalid characters. */
3615 if (base64test.exec(input)) {
3616 alert("There were invalid base64 characters in the input text.\n" +
3617 "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
3618 "Expect errors in decoding.");
3619 }
3620
3621 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
3622
3623 do {
3624 enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
3625 enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
3626 enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
3627 enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));
3628
3629 chr1 = (enc1 << 2) | (enc2 >> 4);
3630 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
3631 chr3 = ((enc3 & 3) << 6) | enc4;
3632
3633 output = output + String.fromCharCode(chr1);
3634
3635 if (enc3 != 64) {
3636 output = output + String.fromCharCode(chr2);
3637 }
3638 if (enc4 != 64) {
3639 output = output + String.fromCharCode(chr3);
3640 }
3641
3642 chr1 = chr2 = chr3 = "";
3643 enc1 = enc2 = enc3 = enc4 = "";
3644
3645 } while (i < input.length);
3646
3647 return unescape(output);
3648 };
3649
3650//byte []
3651
3652/**
3653 * NOT WORKING!!!!!
3654 *
3655 * Unsiged Long Number to Byte Array
3656 */
3657
3658 /*
3659DataUtils.unsignedLongToByteArray= function( value) {
3660
3661 if(LOG>4)console.log('INPUT IS '+value);
3662
3663 if( 0 == value )
3664 return [0];
3665
3666 if( 0 <= value && value <= 0x00FF ) {
3667 //byte []
3668 var bb = new Array(1);
3669 bb[0] = (value & 0x00FF);
3670 return bb;
3671 }
3672
3673 if(LOG>4) console.log('type of value is '+typeof value);
3674 if(LOG>4) console.log('value is '+value);
3675 //byte []
3676 var out = null;
3677 //int
3678 var offset = -1;
3679 for(var i = 7; i >=0; --i) {
3680 //byte
3681 console.log(i);
3682 console.log('value is '+value);
3683 console.log('(value >> (i * 8)) '+ (value >> (i * 8)) );
3684 console.log(' ((value >> (i * 8)) & 0xFF) '+ ((value >> (i * 8)) & 0xFF) );
3685
3686 var b = ((value >> (i * 8)) & 0xFF) ;
3687
3688 if(LOG>4) console.log('b is '+b);
3689
3690 if( out == null && b != 0 ) {
3691 //out = new byte[i+1];
3692 out = new Array(i+1);
3693 offset = i;
3694 }
3695
3696 if( out != null )
3697 out[ offset - i ] = b;
3698 }
3699 if(LOG>4)console.log('OUTPUT IS ');
3700 if(LOG>4)console.log(out);
3701 return out;
3702}
3703*/
3704
3705/**
3706 * NOT WORKING!!!!!
3707 *
3708 * Unsiged Long Number to Byte Array
3709 *//*
3710DataUtils.byteArrayToUnsignedLong = function(//final byte []
3711 src) {
3712 if(LOG>4) console.log('INPUT IS ');
3713 if(LOG>4) console.log(src);
3714
3715 var value = 0;
3716 for(var i = 0; i < src.length; i++) {
3717 value = value << 8;
3718 // Java will assume the byte is signed, so extend it and trim it.
3719
3720
3721 var b = ((src[i]) & 0xFF );
3722 value |= b;
3723 }
3724
3725 if(LOG>4) console.log('OUTPUT IS ');
3726
3727 if(LOG>4) console.log(value);
3728
3729 return value;
3730 }*/
3731
3732
3733/**
3734 * Hex String to Byte Array
3735 */
3736 //THIS IS NOT WORKING
3737/*
3738DataUtils.HexStringtoByteArray = function(str) {
3739 var byteArray = [];
3740 for (var i = 0; i < str.length; i++)
3741 if (str.charCodeAt(i) <= 0x7F)
3742 byteArray.push(str.charCodeAt(i));
3743 else {
3744 var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
3745 for (var j = 0; j < h.length; j++)
3746 byteArray.push(parseInt(h[j], 16));
3747 }
3748 return byteArray;
3749};
3750*/
3751
3752/**
3753 * Byte Array to Hex String
3754 */
3755DataUtils.byteArrayToHexString = function(byteArray) {
3756 var str = '';
3757 for (var i = 0; i < byteArray.length; i++)
3758 str += byteArray[i] <= 0x7F?
3759 byteArray[i] === 0x25 ? "%25" : // %
3760 String.fromCharCode(byteArray[i]) :
3761 "%" + byteArray[i].toString(16).toUpperCase();
3762 return decodeURIComponent(str);
3763};
3764
3765
3766/**
3767 * Byte array to Hex String
3768 */
3769//http://ejohn.org/blog/numbers-hex-and-colors/
3770DataUtils.toHex = function(arguments){
3771 if(LOG>4) console.log('ABOUT TO CONVERT '+ arguments);
3772 //console.log(arguments);
3773 var ret = "";
3774 for ( var i = 0; i < arguments.length; i++ )
3775 ret += (arguments[i] < 16 ? "0" : "") + arguments[i].toString(16);
3776 return ret; //.toUpperCase();
3777}
3778
3779/**
3780 * Raw string to hex string.
3781 */
3782DataUtils.stringToHex = function(arguments){
3783 var ret = "";
3784 for (var i = 0; i < arguments.length; ++i) {
3785 var value = arguments.charCodeAt(i);
3786 ret += (value < 16 ? "0" : "") + value.toString(16);
3787 }
3788 return ret;
3789}
3790
3791/**
3792 * Byte array to raw string
3793 */
3794//DOES NOT SEEM TO WORK
3795DataUtils.toString = function(arguments){
3796 //console.log(arguments);
3797 var ret = "";
3798 for ( var i = 0; i < arguments.length; i++ )
3799 ret += String.fromCharCode(arguments[i]);
3800 return ret;
3801}
3802
3803/**
3804 * Hex String to byte array
3805 */
3806DataUtils.toNumbers=function( str ){
3807 if(typeof str =='string'){
3808 var ret = [];
3809 str.replace(/(..)/g, function(str){
3810 ret.push( parseInt( str, 16 ) );
3811 });
3812 return ret;
3813 }
3814}
3815
3816/**
3817 * Hex String to raw string.
3818 */
3819DataUtils.hexToRawString = function(str) {
3820 if(typeof str =='string') {
3821 var ret = "";
3822 str.replace(/(..)/g, function(s) {
3823 ret += String.fromCharCode(parseInt(s, 16));
3824 });
3825 return ret;
3826 }
3827}
3828
3829/**
3830 * Raw String to Byte Array
3831 */
3832DataUtils.toNumbersFromString = function( str ){
3833 var bytes = new Array(str.length);
3834 for(var i=0;i<str.length;i++)
3835 bytes[i] = str.charCodeAt(i);
3836 return bytes;
3837}
3838
3839DataUtils.encodeUtf8 = function (string) {
3840 string = string.replace(/\r\n/g,"\n");
3841 var utftext = "";
3842
3843 for (var n = 0; n < string.length; n++) {
3844
3845 var c = string.charCodeAt(n);
3846
3847 if (c < 128) {
3848 utftext += String.fromCharCode(c);
3849 }
3850 else if((c > 127) && (c < 2048)) {
3851 utftext += String.fromCharCode((c >> 6) | 192);
3852 utftext += String.fromCharCode((c & 63) | 128);
3853 }
3854 else {
3855 utftext += String.fromCharCode((c >> 12) | 224);
3856 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
3857 utftext += String.fromCharCode((c & 63) | 128);
3858 }
3859
3860 }
3861
3862 return utftext;
3863 };
3864
3865 // public method for url decoding
3866DataUtils.decodeUtf8 = function (utftext) {
3867 var string = "";
3868 var i = 0;
Jeff Thompson10de4592012-10-21 23:54:18 -07003869 var c = 0;
3870 var c1 = 0;
3871 var c2 = 0;
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003872
3873 while ( i < utftext.length ) {
3874
3875 c = utftext.charCodeAt(i);
3876
3877 if (c < 128) {
3878 string += String.fromCharCode(c);
3879 i++;
3880 }
3881 else if((c > 191) && (c < 224)) {
3882 c2 = utftext.charCodeAt(i+1);
3883 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
3884 i += 2;
3885 }
3886 else {
3887 c2 = utftext.charCodeAt(i+1);
Jeff Thompson10de4592012-10-21 23:54:18 -07003888 var c3 = utftext.charCodeAt(i+2);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003889 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
3890 i += 3;
3891 }
3892
3893 }
3894
3895 return string;
3896 };
3897
3898 test = function(){
3899 console.log(DataUtils.decodeUtf8("HELLO.~"));
3900 return DataUtils.decodeUtf8("HELLO.~");
3901 }
3902
3903//NOT WORKING
3904/*
3905DataUtils.getUTF8StringFromBytes = function(bytes) {
3906
3907 bytes = toString(bytes);
3908
3909 var ix = 0;
3910
3911 if( bytes.slice(0,3) == "\xEF\xBB\xBF") {
3912 ix = 3;
3913 }
3914
3915 var string = "";
3916 for( ; ix < bytes.length; ix++ ) {
3917 var byte1 = bytes[ix].charCodeAt(0);
3918 if( byte1 < 0x80 ) {
3919 string += String.fromCharCode(byte1);
3920 } else if( byte1 >= 0xC2 && byte1 < 0xE0 ) {
3921 var byte2 = bytes[++ix].charCodeAt(0);
3922 string += String.fromCharCode(((byte1&0x1F)<<6) + (byte2&0x3F));
3923 } else if( byte1 >= 0xE0 && byte1 < 0xF0 ) {
3924 var byte2 = bytes[++ix].charCodeAt(0);
3925 var byte3 = bytes[++ix].charCodeAt(0);
3926 string += String.fromCharCode(((byte1&0xFF)<<12) + ((byte2&0x3F)<<6) + (byte3&0x3F));
3927 } else if( byte1 >= 0xF0 && byte1 < 0xF5) {
3928 var byte2 = bytes[++ix].charCodeAt(0);
3929 var byte3 = bytes[++ix].charCodeAt(0);
3930 var byte4 = bytes[++ix].charCodeAt(0);
3931 var codepoint = ((byte1&0x07)<<18) + ((byte2&0x3F)<<12)+ ((byte3&0x3F)<<6) + (byte4&0x3F);
3932 codepoint -= 0x10000;
3933 string += String.fromCharCode(
3934 (codepoint>>10) + 0xD800,
3935 (codepoint&0x3FF) + 0xDC00
3936 );
3937 }
3938 }
3939
3940 return string;
3941}*/
3942
3943/**
3944 * Return true if a1 and a2 are the same length with equal elements.
3945 */
3946DataUtils.arraysEqual = function(a1, a2){
3947 if (a1.length != a2.length)
3948 return false;
3949
3950 for (var i = 0; i < a1.length; ++i) {
3951 if (a1[i] != a2[i])
3952 return false;
3953 }
3954
3955 return true;
Jeff Thompson10de4592012-10-21 23:54:18 -07003956};
3957
3958/*
3959 * Convert the big endian byte array to an unsigned int.
3960 * Don't check for overflow.
3961 */
3962DataUtils.bigEndianToUnsignedInt = function(bytes) {
3963 var result = 0;
3964 for (var i = 0; i < bytes.length; ++i) {
3965 result <<= 8;
3966 result += bytes[i];
3967 }
3968 return result;
3969};
3970
3971/*
3972 * Convert the int value to a new big endian byte array and return.
3973 * If value is 0 or negative, return [].
3974 */
3975DataUtils.nonNegativeIntToBigEndian = function(value) {
3976 var result = [];
3977 if (value <= 0)
3978 return result;
3979
3980 while (value != 0) {
3981 result.unshift(value & 0xff);
3982 value >>= 8;
3983 }
3984 return result;
3985};
3986
Jeff Thompson745026e2012-10-13 12:49:20 -07003987/*
3988 * This file contains utilities to help encode and decode NDN objects.
3989 * author: ucla-cs
3990 * See COPYING for copyright and distribution information.
3991 */
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07003992
3993function encodeToHexInterest(interest){
3994
3995 var enc = new BinaryXMLEncoder();
3996
3997 interest.to_ccnb(enc);
3998
3999 var hex = DataUtils.toHex(enc.getReducedOstream());
4000
4001 return hex;
4002
4003
4004}
4005
4006
4007function encodeToHexContentObject(co){
4008 var enc = new BinaryXMLEncoder();
4009
4010 co.to_ccnb(enc);
4011
4012 var hex = DataUtils.toHex(enc.getReducedOstream());
4013
4014 return hex;
4015
4016
4017}
4018
4019function encodeToBinaryContentObject(co){
4020 var enc = new BinaryXMLEncoder();
4021
4022 co.to_ccnb(enc);
4023
4024 var hex = enc.getReducedOstream();
4025
4026 return hex;
4027
4028
4029}
4030
4031function encodeForwardingEntry(co){
4032 var enc = new BinaryXMLEncoder();
4033
4034 co.to_ccnb(enc);
4035
4036 var bytes = enc.getReducedOstream();
4037
4038 return bytes;
4039
4040
4041}
4042
4043
4044
4045function decodeHexFaceInstance(result){
4046
4047 var numbers = DataUtils.toNumbers(result);
4048
4049
4050 decoder = new BinaryXMLDecoder(numbers);
4051
4052 if(LOG>3)console.log('DECODING HEX FACE INSTANCE \n'+numbers);
4053
4054 var faceInstance = new FaceInstance();
4055
4056 faceInstance.from_ccnb(decoder);
4057
4058 return faceInstance;
4059
4060}
4061
4062function decodeHexInterest(result){
4063 var numbers = DataUtils.toNumbers(result);
4064
4065
4066 decoder = new BinaryXMLDecoder(numbers);
4067 if(LOG>3)console.log('DECODING HEX INTERST \n'+numbers);
4068
4069 var interest = new Interest();
4070
4071 interest.from_ccnb(decoder);
4072
4073 return interest;
4074
4075}
4076
4077
4078
4079function decodeHexContentObject(result){
4080 var numbers = DataUtils.toNumbers(result);
4081
4082 decoder = new BinaryXMLDecoder(numbers);
4083 if(LOG>3)console.log('DECODED HEX CONTENT OBJECT \n'+numbers);
4084
4085 co = new ContentObject();
4086
4087 co.from_ccnb(decoder);
4088
4089 return co;
4090
4091}
4092
4093
4094
4095function decodeHexForwardingEntry(result){
4096 var numbers = DataUtils.toNumbers(result);
4097
4098 decoder = new BinaryXMLDecoder(numbers);
4099
4100 if(LOG>3)console.log('DECODED HEX FORWARDING ENTRY \n'+numbers);
4101
4102 forwardingEntry = new ForwardingEntry();
4103
4104 forwardingEntry.from_ccnb(decoder);
4105
4106 return forwardingEntry;
4107
4108}
4109
4110/* Return a user friendly HTML string with the contents of co.
4111 This also outputs to console.log.
4112 */
4113function contentObjectToHtml(/* ContentObject */ co) {
4114 var output ="";
4115
4116 if(co==-1)
4117 output+= "NO CONTENT FOUND"
4118 else if (co==-2)
4119 output+= "CONTENT NAME IS EMPTY"
4120 else{
4121 if(co.name!=null && co.name.components!=null){
4122 output+= "NAME: ";
4123
4124 for(var i=0;i<co.name.components.length;i++){
4125 output+= "/"+ DataUtils.toString(co.name.components[i]);
4126 }
4127 output+= "<br />";
4128 output+= "<br />";
4129 }
4130
4131 if(co.content !=null){
4132 output += "CONTENT(ASCII): "+ DataUtils.toString(co.content);
4133
4134 output+= "<br />";
4135 output+= "<br />";
4136 }
4137 if(co.content !=null){
4138 output += "CONTENT(hex): "+ DataUtils.toHex(co.content);
4139
4140 output+= "<br />";
4141 output+= "<br />";
4142 }
4143 if(co.signature !=null && co.signature.signature!=null){
4144 output += "SIGNATURE(hex): "+ DataUtils.toHex(co.signature.signature);
4145
4146 output+= "<br />";
4147 output+= "<br />";
4148 }
4149 if(co.signedInfo !=null && co.signedInfo.publisher!=null && co.signedInfo.publisher.publisherPublicKeyDigest!=null){
4150 output += "Publisher Public Key Digest(hex): "+ DataUtils.toHex(co.signedInfo.publisher.publisherPublicKeyDigest);
4151
4152 output+= "<br />";
4153 output+= "<br />";
4154 }
4155 if(co.signedInfo !=null && co.signedInfo.timestamp!=null){
4156 var d = new Date();
4157 d.setTime( co.signedInfo.timestamp.msec );
4158
4159 var bytes = [217, 185, 12, 225, 217, 185, 12, 225];
4160
4161 output += "TimeStamp: "+d;
4162 output+= "<br />";
4163 output += "TimeStamp(number): "+ co.signedInfo.timestamp.msec;
4164
4165 output+= "<br />";
4166 }
Jeff Thompson34419762012-10-15 22:24:12 -07004167 if(co.signedInfo !=null && co.signedInfo.finalBlockID!=null){
4168 output += "FinalBlockID: "+ DataUtils.toHex(co.signedInfo.finalBlockID);
4169 output+= "<br />";
4170 }
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07004171 if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.certificate!=null){
4172 var tmp = DataUtils.toString(co.signedInfo.locator.certificate);
4173 var publickey = rstr2b64(tmp);
4174 var publickeyHex = DataUtils.toHex(co.signedInfo.locator.certificate).toLowerCase();
4175 var publickeyString = DataUtils.toString(co.signedInfo.locator.certificate);
4176 var signature = DataUtils.toHex(co.signature.signature).toLowerCase();
4177 var input = DataUtils.toString(co.rawSignatureData);
4178
4179 output += "DER Certificate: "+publickey ;
4180
4181 output+= "<br />";
4182 output+= "<br />";
4183
4184 if(LOG>2) console.log(" ContentName + SignedInfo + Content = "+input);
4185
4186 if(LOG>2) console.log("HEX OF ContentName + SignedInfo + Content = ");
4187 if(LOG>2) console.log(DataUtils.stringtoBase64(input));
4188
4189 if(LOG>2) console.log(" PublicKey = "+publickey );
4190 if(LOG>2) console.log(" PublicKeyHex = "+publickeyHex );
4191 if(LOG>2) console.log(" PublicKeyString = "+publickeyString );
4192
4193 if(LOG>2) console.log(" Signature is");
4194 if(LOG>2) console.log( signature );
4195 //if(LOG>2) console.log(" Signature NOW IS" );
4196 //if(LOG>2) console.log(co.signature.signature);
4197
4198 var x509 = new X509();
4199 x509.readCertPEM(publickey);
4200
4201 //x509.readCertPEMWithoutRSAInit(publickey);
4202
4203 var result = x509.subjectPublicKeyRSA.verifyByteArray(co.rawSignatureData, signature);
4204 if(LOG>2) console.log('result is '+result);
4205
4206 var n = x509.subjectPublicKeyRSA.n;
4207 var e = x509.subjectPublicKeyRSA.e;
4208
4209 if(LOG>2) console.log('PUBLIC KEY n after is ');
4210 if(LOG>2) console.log(n);
4211
4212 if(LOG>2) console.log('EXPONENT e after is ');
4213 if(LOG>2) console.log(e);
4214
4215 /*var rsakey = new RSAKey();
4216
4217 var kp = publickeyHex.slice(56,314);
4218
4219 output += "PUBLISHER KEY(hex): "+kp ;
4220
4221 output+= "<br />";
4222 output+= "<br />";
4223
4224 console.log('kp is '+kp);
4225
4226 var exp = publickeyHex.slice(318,324);
4227
4228 console.log('kp size is '+kp.length );
4229 output += "exponent: "+exp ;
4230
4231 output+= "<br />";
4232 output+= "<br />";
4233
4234 console.log('exp is '+exp);
4235
4236 rsakey.setPublic(kp,exp);
4237
4238 var result = rsakey.verifyString(input, signature);*/
4239
4240 if(result)
4241 output += 'SIGNATURE VALID';
4242 else
4243 output += 'SIGNATURE INVALID';
4244
4245 //output += "VALID: "+ toHex(co.signedInfo.locator.publicKey);
4246
4247 output+= "<br />";
4248 output+= "<br />";
4249
4250 //if(LOG>4) console.log('str'[1]);
4251 }
4252 if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.publicKey!=null){
4253 var publickey = rstr2b64(DataUtils.toString(co.signedInfo.locator.publicKey));
4254 var publickeyHex = DataUtils.toHex(co.signedInfo.locator.publicKey).toLowerCase();
4255 var publickeyString = DataUtils.toString(co.signedInfo.locator.publicKey);
4256 var signature = DataUtils.toHex(co.signature.signature).toLowerCase();
4257 var input = DataUtils.toString(co.rawSignatureData);
4258
4259 output += "DER Certificate: "+publickey ;
4260
4261 output+= "<br />";
4262 output+= "<br />";
4263
4264 if(LOG>2) console.log(" ContentName + SignedInfo + Content = "+input);
4265 if(LOG>2) console.log(" PublicKey = "+publickey );
4266 if(LOG>2) console.log(" PublicKeyHex = "+publickeyHex );
4267 if(LOG>2) console.log(" PublicKeyString = "+publickeyString );
4268
4269 if(LOG>2) console.log(" Signature "+signature );
4270
4271 if(LOG>2) console.log(" Signature NOW IS" );
4272
4273 if(LOG>2) console.log(co.signature.signature);
4274
4275 /*var x509 = new X509();
4276
4277 x509.readCertPEM(publickey);
4278
4279
4280 //x509.readCertPEMWithoutRSAInit(publickey);
4281
4282 var result = x509.subjectPublicKeyRSA.verifyString(input, signature);*/
4283 //console.log('result is '+result);
4284
4285 var kp = publickeyHex.slice(56,314);
4286
4287 output += "PUBLISHER KEY(hex): "+kp ;
4288
4289 output+= "<br />";
4290 output+= "<br />";
4291
4292 console.log('PUBLIC KEY IN HEX is ');
4293 console.log(kp);
4294
4295 var exp = publickeyHex.slice(318,324);
4296
4297 console.log('kp size is '+kp.length );
4298 output += "exponent: "+exp ;
4299
4300 output+= "<br />";
4301 output+= "<br />";
4302
4303 console.log('EXPONENT is ');
4304 console.log(exp);
4305
4306 /*var c1 = hex_sha256(input);
4307 var c2 = signature;
4308
4309 if(LOG>4)console.log('input is ');
4310 if(LOG>4)console.log(input);
4311 if(LOG>4)console.log('C1 is ');
4312 if(LOG>4)console.log(c1);
4313 if(LOG>4)console.log('C2 is ');
4314 if(LOG>4)console.log(c2);
4315 var result = c1 == c2;*/
4316
4317 var rsakey = new RSAKey();
4318
4319 rsakey.setPublic(kp,exp);
4320
4321 var result = rsakey.verifyByteArray(co.rawSignatureData,signature);
4322 // var result = rsakey.verifyString(input, signature);
4323
4324 console.log('PUBLIC KEY n after is ');
4325 console.log(rsakey.n);
4326
4327 console.log('EXPONENT e after is ');
4328 console.log(rsakey.e);
4329
4330 if(result)
4331 output += 'SIGNATURE VALID';
4332 else
4333 output += 'SIGNATURE INVALID';
4334
4335 //output += "VALID: "+ toHex(co.signedInfo.locator.publicKey);
4336
4337 output+= "<br />";
4338 output+= "<br />";
4339
4340 //if(LOG>4) console.log('str'[1]);
4341 }
4342 }
4343
4344 return output;
4345}
4346
Jeff Thompson745026e2012-10-13 12:49:20 -07004347/*
4348 * @author: ucla-cs
4349 * See COPYING for copyright and distribution information.
4350 */
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07004351
4352var KeyManager = function KeyManager(){
4353
4354
4355//Certificate from CCNx
4356
4357this.certificate = 'MIIBmzCCAQQCCQC32FyQa61S7jANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwd'+
4358
4359'heGVsY2R2MB4XDTEyMDQyODIzNDQzN1oXDTEyMDUyODIzNDQzN1owEjEQMA4GA1'+
4360
4361'UEAxMHYXhlbGNkdjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4X0wp9goq'+
4362
4363'xuECxdULcr2IHr9Ih4Iaypg0Wy39URIup8/CLzQmdsh3RYqd55hqonu5VTTpH3i'+
4364
4365'MLx6xZDVJAZ8OJi7pvXcQ2C4Re2kjL2c8SanI0RfDhlS1zJadfr1VhRPmpivcYa'+
4366
4367'wJ4aFuOLAi+qHFxtN7lhcGCgpW1OV60oXd58CAwEAATANBgkqhkiG9w0BAQUFAA'+
4368
4369'OBgQDLOrA1fXzSrpftUB5Ro6DigX1Bjkf7F5Bkd69hSVp+jYeJFBBlsILQAfSxU'+
4370
4371'ZPQtD+2Yc3iCmSYNyxqu9PcufDRJlnvB7PG29+L3y9lR37tetzUV9eTscJ7rdp8'+
4372
4373'Wt6AzpW32IJ/54yKNfP7S6ZIoIG+LP6EIxq6s8K1MXRt8uBJKw==';
4374
4375
4376//this.publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQAB';
4377this.publicKey ='30819F300D06092A864886F70D010101050003818D0030818902818100E17D30A7D828AB1B840B17542DCAF6207AFD221E086B2A60D16CB7F54448BA9F3F08BCD099DB21DD162A779E61AA89EEE554D3A47DE230BC7AC590D524067C3898BBA6F5DC4360B845EDA48CBD9CF126A723445F0E1952D7325A75FAF556144F9A98AF7186B0278685B8E2C08BEA87171B4DEE585C1828295B5395EB4A17779F0203010001';
4378//Private Key from CCNx
4379
4380this.privateKey ='MIICXQIBAAKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQABAoGAGkv6T6jC3WmhFZYL6CdCWvlc6gysmKrhjarrLTxgavtFY6R5g2ft5BXAsCCVbUkWxkIFSKqxpVNl0gKZCNGEzPDN6mHJOQI/h0rlxNIHAuGfoAbCzALnqmyZivhJAPGijAyKuU9tczsst5+Kpn+bn7ehzHQuj7iwJonS5WbojqECQQD851K8TpW2GrRizNgG4dx6orZxAaon/Jnl8lS7soXhllQty7qG+oDfzznmdMsiznCqEABzHUUKOVGE9RWPN3aRAkEA5D/w9N55d0ibnChFJlc8cUAoaqH+w+U3oQP2Lb6AZHJpLptN4y4b/uf5d4wYU5/i/gC7SSBH3wFhh9bjRLUDLwJAVOx8vN0Kqt7myfKNbCo19jxjVSlA8TKCn1Oznl/BU1I+rC4oUaEW25DjmX6IpAR8kq7S59ThVSCQPjxqY/A08QJBAIRaF2zGPITQk3r/VumemCvLWiRK/yG0noc9dtibqHOWbCtcXtOm/xDWjq+lis2i3ssOvYrvrv0/HcDY+Dv1An0CQQCLJtMsfSg4kvG/FRY5UMhtMuwo8ovYcMXt4Xv/LWaMhndD67b2UGawQCRqr5ghRTABWdDD/HuuMBjrkPsX0861';
4381
4382
4383/*
4384 this.certificate =
4385 'MIIBvTCCASYCCQD55fNzc0WF7TANBgkqhkiG9w0BAQUFADAjMQswCQYDVQQGEwJK'+
4386 'UDEUMBIGA1UEChMLMDAtVEVTVC1SU0EwHhcNMTAwNTI4MDIwODUxWhcNMjAwNTI1'+
4387 'MDIwODUxWjAjMQswCQYDVQQGEwJKUDEUMBIGA1UEChMLMDAtVEVTVC1SU0EwgZ8w'+
4388 'DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANGEYXtfgDRlWUSDn3haY4NVVQiKI9Cz'+
4389 'Thoua9+DxJuiseyzmBBe7Roh1RPqdvmtOHmEPbJ+kXZYhbozzPRbFGHCJyBfCLzQ'+
4390 'fVos9/qUQ88u83b0SFA2MGmQWQAlRtLy66EkR4rDRwTj2DzR4EEXgEKpIvo8VBs/'+
4391 '3+sHLF3ESgAhAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAEZ6mXFFq3AzfaqWHmCy1'+
4392 'ARjlauYAa8ZmUFnLm0emg9dkVBJ63aEqARhtok6bDQDzSJxiLpCEF6G4b/Nv/M/M'+
4393 'LyhP+OoOTmETMegAVQMq71choVJyOFE5BtQa6M/lCHEOya5QUfoRF2HF9EjRF44K'+
4394 '3OK+u3ivTSj3zwjtpudY5Xo=';
4395
4396 this.privateKey =
4397 'MIICWwIBAAKBgQDRhGF7X4A0ZVlEg594WmODVVUIiiPQs04aLmvfg8SborHss5gQ'+
4398 'Xu0aIdUT6nb5rTh5hD2yfpF2WIW6M8z0WxRhwicgXwi80H1aLPf6lEPPLvN29EhQ'+
4399 'NjBpkFkAJUbS8uuhJEeKw0cE49g80eBBF4BCqSL6PFQbP9/rByxdxEoAIQIDAQAB'+
4400 'AoGAA9/q3Zk6ib2GFRpKDLO/O2KMnAfR+b4XJ6zMGeoZ7Lbpi3MW0Nawk9ckVaX0'+
4401 'ZVGqxbSIX5Cvp/yjHHpww+QbUFrw/gCjLiiYjM9E8C3uAF5AKJ0r4GBPl4u8K4bp'+
4402 'bXeSxSB60/wPQFiQAJVcA5xhZVzqNuF3EjuKdHsw+dk+dPECQQDubX/lVGFgD/xY'+
4403 'uchz56Yc7VHX+58BUkNSewSzwJRbcueqknXRWwj97SXqpnYfKqZq78dnEF10SWsr'+
4404 '/NMKi+7XAkEA4PVqDv/OZAbWr4syXZNv/Mpl4r5suzYMMUD9U8B2JIRnrhmGZPzL'+
4405 'x23N9J4hEJ+Xh8tSKVc80jOkrvGlSv+BxwJAaTOtjA3YTV+gU7Hdza53sCnSw/8F'+
4406 'YLrgc6NOJtYhX9xqdevbyn1lkU0zPr8mPYg/F84m6MXixm2iuSz8HZoyzwJARi2p'+
4407 'aYZ5/5B2lwroqnKdZBJMGKFpUDn7Mb5hiSgocxnvMkv6NjT66Xsi3iYakJII9q8C'+
4408 'Ma1qZvT/cigmdbAh7wJAQNXyoizuGEltiSaBXx4H29EdXNYWDJ9SS5f070BRbAIl'+
4409 'dqRh3rcNvpY6BKJqFapda1DjdcncZECMizT/GMrc1w==';
4410
4411 */
4412};
4413
4414
4415KeyManager.prototype.verify = function verify(message,signature){
4416
4417 var input = message;
4418
4419 var _PEM_X509CERT_STRING_ = this.certificate;
4420
4421 var x509 = new X509();
4422
4423 x509.readCertPEM(_PEM_X509CERT_STRING_);
4424
4425 var result = x509.subjectPublicKeyRSA.verifyString(input, signature);
4426
4427 return result;
4428};
4429
4430KeyManager.prototype.sign= function sign(message){
4431
4432 var input = message;
4433
4434 var _PEM_PRIVATE_KEY_STRING_ = this.privateKey;
4435
4436 var rsa = new RSAKey();
4437
4438 rsa.readPrivateKeyFromPEMString(_PEM_PRIVATE_KEY_STRING_);
4439
4440 var hSig = rsa.signString(input, "sha256");
4441
4442 return hSig;
4443
4444};
4445
4446
4447
4448var globalKeyManager = new KeyManager();
4449//var KeyPair = { "public" : "PUBLIC KEY" , "private" : "PRIVATE KEY" };
4450
4451
4452
4453/*
4454 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
4455 * in FIPS 180-1
4456 * Version 2.2 Copyright Paul Johnston 2000 - 2009.
4457 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
4458 * Distributed under the BSD License
4459 * See http://pajhome.org.uk/crypt/md5 for details.
4460 */
4461
4462/*
4463 * Configurable variables. You may need to tweak these to be compatible with
4464 * the server-side, but the defaults work in most cases.
4465 */
4466var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
4467var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
4468
4469/**
4470 * These are the functions you'll usually want to call
4471 * They take string arguments and return either hex or base-64 encoded strings
4472 */
4473function hex_sha1(s) { return rstr2hex(rstr_sha1(str2rstr_utf8(s))); }
4474function b64_sha1(s) { return rstr2b64(rstr_sha1(str2rstr_utf8(s))); }
4475function any_sha1(s, e) { return rstr2any(rstr_sha1(str2rstr_utf8(s)), e); }
4476function hex_hmac_sha1(k, d)
4477 { return rstr2hex(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); }
4478function b64_hmac_sha1(k, d)
4479 { return rstr2b64(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); }
4480function any_hmac_sha1(k, d, e)
4481 { return rstr2any(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
4482
4483/**
4484 * Perform a simple self-test to see if the VM is working
4485 */
4486function sha1_vm_test()
4487{
4488 return hex_sha1("abc").toLowerCase() == "a9993e364706816aba3e25717850c26c9cd0d89d";
4489}
4490
4491/**
4492 * Calculate the SHA1 of a raw string
4493 */
4494function rstr_sha1(s)
4495{
4496 return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8));
4497}
4498
4499/**
4500 * Calculate the HMAC-SHA1 of a key and some data (raw strings)
4501 */
4502function rstr_hmac_sha1(key, data)
4503{
4504 var bkey = rstr2binb(key);
4505 if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8);
4506
4507 var ipad = Array(16), opad = Array(16);
4508 for(var i = 0; i < 16; i++)
4509 {
4510 ipad[i] = bkey[i] ^ 0x36363636;
4511 opad[i] = bkey[i] ^ 0x5C5C5C5C;
4512 }
4513
4514 var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
4515 return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160));
4516}
4517
4518/**
4519 * Convert a raw string to a hex string
4520 */
4521function rstr2hex(input)
4522{
4523 try { hexcase } catch(e) { hexcase=0; }
4524 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
4525 var output = "";
4526 var x;
4527 for(var i = 0; i < input.length; i++)
4528 {
4529 x = input.charCodeAt(i);
4530 output += hex_tab.charAt((x >>> 4) & 0x0F)
4531 + hex_tab.charAt( x & 0x0F);
4532 }
4533 return output;
4534}
4535
4536/**
4537 * Convert a raw string to a base-64 string
4538 */
4539function rstr2b64(input)
4540{
4541 try { b64pad } catch(e) { b64pad=''; }
4542 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4543 var output = "";
4544 var len = input.length;
4545 for(var i = 0; i < len; i += 3)
4546 {
4547 var triplet = (input.charCodeAt(i) << 16)
4548 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
4549 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
4550 for(var j = 0; j < 4; j++)
4551 {
4552 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
4553 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
4554 }
4555 }
4556 return output;
4557}
4558
4559/**
4560 * Convert a raw string to an arbitrary string encoding
4561 */
4562function rstr2any(input, encoding)
4563{
4564 var divisor = encoding.length;
4565 var remainders = Array();
4566 var i, q, x, quotient;
4567
4568 /* Convert to an array of 16-bit big-endian values, forming the dividend */
4569 var dividend = Array(Math.ceil(input.length / 2));
4570 for(i = 0; i < dividend.length; i++)
4571 {
4572 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
4573 }
4574
4575 /*
4576 * Repeatedly perform a long division. The binary array forms the dividend,
4577 * the length of the encoding is the divisor. Once computed, the quotient
4578 * forms the dividend for the next step. We stop when the dividend is zero.
4579 * All remainders are stored for later use.
4580 */
4581 while(dividend.length > 0)
4582 {
4583 quotient = Array();
4584 x = 0;
4585 for(i = 0; i < dividend.length; i++)
4586 {
4587 x = (x << 16) + dividend[i];
4588 q = Math.floor(x / divisor);
4589 x -= q * divisor;
4590 if(quotient.length > 0 || q > 0)
4591 quotient[quotient.length] = q;
4592 }
4593 remainders[remainders.length] = x;
4594 dividend = quotient;
4595 }
4596
4597 /* Convert the remainders to the output string */
4598 var output = "";
4599 for(i = remainders.length - 1; i >= 0; i--)
4600 output += encoding.charAt(remainders[i]);
4601
4602 /* Append leading zero equivalents */
4603 var full_length = Math.ceil(input.length * 8 /
4604 (Math.log(encoding.length) / Math.log(2)));
4605 for(i = output.length; i < full_length; i++)
4606 output = encoding[0] + output;
4607
4608 return output;
4609}
4610
4611/**
4612 * Encode a string as utf-8.
4613 * For efficiency, this assumes the input is valid utf-16.
4614 */
4615function str2rstr_utf8(input)
4616{
4617 var output = "";
4618 var i = -1;
4619 var x, y;
4620
4621 while(++i < input.length)
4622 {
4623 /* Decode utf-16 surrogate pairs */
4624 x = input.charCodeAt(i);
4625 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
4626 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
4627 {
4628 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
4629 i++;
4630 }
4631
4632 /* Encode output as utf-8 */
4633 if(x <= 0x7F)
4634 output += String.fromCharCode(x);
4635 else if(x <= 0x7FF)
4636 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
4637 0x80 | ( x & 0x3F));
4638 else if(x <= 0xFFFF)
4639 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
4640 0x80 | ((x >>> 6 ) & 0x3F),
4641 0x80 | ( x & 0x3F));
4642 else if(x <= 0x1FFFFF)
4643 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
4644 0x80 | ((x >>> 12) & 0x3F),
4645 0x80 | ((x >>> 6 ) & 0x3F),
4646 0x80 | ( x & 0x3F));
4647 }
4648 return output;
4649}
4650
4651/**
4652 * Encode a string as utf-16
4653 */
4654function str2rstr_utf16le(input)
4655{
4656 var output = "";
4657 for(var i = 0; i < input.length; i++)
4658 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
4659 (input.charCodeAt(i) >>> 8) & 0xFF);
4660 return output;
4661}
4662
4663function str2rstr_utf16be(input)
4664{
4665 var output = "";
4666 for(var i = 0; i < input.length; i++)
4667 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
4668 input.charCodeAt(i) & 0xFF);
4669 return output;
4670}
4671
4672/**
4673 * Convert a raw string to an array of big-endian words
4674 * Characters >255 have their high-byte silently ignored.
4675 */
4676function rstr2binb(input)
4677{
4678 var output = Array(input.length >> 2);
4679 for(var i = 0; i < output.length; i++)
4680 output[i] = 0;
4681 for(var i = 0; i < input.length * 8; i += 8)
4682 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
4683 return output;
4684}
4685
4686/**
4687 * Convert an array of big-endian words to a string
4688 */
4689function binb2rstr(input)
4690{
4691 var output = "";
4692 for(var i = 0; i < input.length * 32; i += 8)
4693 output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
4694 return output;
4695}
4696
4697/**
4698 * Calculate the SHA-1 of an array of big-endian words, and a bit length
4699 */
4700function binb_sha1(x, len)
4701{
4702 /* append padding */
4703 x[len >> 5] |= 0x80 << (24 - len % 32);
4704 x[((len + 64 >> 9) << 4) + 15] = len;
4705
4706 var w = Array(80);
4707 var a = 1732584193;
4708 var b = -271733879;
4709 var c = -1732584194;
4710 var d = 271733878;
4711 var e = -1009589776;
4712
4713 for(var i = 0; i < x.length; i += 16)
4714 {
4715 var olda = a;
4716 var oldb = b;
4717 var oldc = c;
4718 var oldd = d;
4719 var olde = e;
4720
4721 for(var j = 0; j < 80; j++)
4722 {
4723 if(j < 16) w[j] = x[i + j];
4724 else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
4725 var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
4726 safe_add(safe_add(e, w[j]), sha1_kt(j)));
4727 e = d;
4728 d = c;
4729 c = bit_rol(b, 30);
4730 b = a;
4731 a = t;
4732 }
4733
4734 a = safe_add(a, olda);
4735 b = safe_add(b, oldb);
4736 c = safe_add(c, oldc);
4737 d = safe_add(d, oldd);
4738 e = safe_add(e, olde);
4739 }
4740 return Array(a, b, c, d, e);
4741
4742}
4743
4744/**
4745 * Perform the appropriate triplet combination function for the current
4746 * iteration
4747 */
4748function sha1_ft(t, b, c, d)
4749{
4750 if(t < 20) return (b & c) | ((~b) & d);
4751 if(t < 40) return b ^ c ^ d;
4752 if(t < 60) return (b & c) | (b & d) | (c & d);
4753 return b ^ c ^ d;
4754}
4755
4756/**
4757 * Determine the appropriate additive constant for the current iteration
4758 */
4759function sha1_kt(t)
4760{
4761 return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
4762 (t < 60) ? -1894007588 : -899497514;
4763}
4764
4765/**
4766 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
4767 * to work around bugs in some JS interpreters.
4768 */
4769function safe_add(x, y)
4770{
4771 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
4772 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
4773 return (msw << 16) | (lsw & 0xFFFF);
4774}
4775
4776/**
4777 * Bitwise rotate a 32-bit number to the left.
4778 */
4779function bit_rol(num, cnt)
4780{
4781 return (num << cnt) | (num >>> (32 - cnt));
4782}
4783
4784/*
4785 * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
4786 * in FIPS 180-2
4787 * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
4788 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
4789 * Distributed under the BSD License
4790 * See http://pajhome.org.uk/crypt/md5 for details.
4791 * Also http://anmar.eu.org/projects/jssha2/
4792 */
4793
4794/*
4795 * Configurable variables. You may need to tweak these to be compatible with
4796 * the server-side, but the defaults work in most cases.
4797 */
4798var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
4799var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
4800
4801/*
4802 * These are the functions you'll usually want to call
4803 * They take string arguments and return either hex or base-64 encoded strings
4804 */
4805
4806//@author axelcdv
4807/**
4808 * Computes the Sha-256 hash of the given byte array
4809 * @param {byte[]}
4810 * @return the hex string corresponding to the Sha-256 hash of the byte array
4811 */
4812function hex_sha256_from_bytes(byteArray){
4813 return rstr2hex(binb2rstr(binb_sha256( byteArray2binb(byteArray), byteArray.length * 8)));
4814}
4815
4816function hex_sha256(s) { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); }
4817function b64_sha256(s) { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); }
4818function any_sha256(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); }
4819function hex_hmac_sha256(k, d)
4820 { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
4821function b64_hmac_sha256(k, d)
4822 { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
4823function any_hmac_sha256(k, d, e)
4824 { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
4825
4826
4827/*
4828 function hex_sha256(s) { return rstr2hex(rstr_sha256(s)); }
4829function b64_sha256(s) { return rstr2b64(rstr_sha256(s)); }
4830function any_sha256(s, e) { return rstr2any(rstr_sha256(s), e); }
4831function hex_hmac_sha256(k, d)
4832 { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), d)); }
4833function b64_hmac_sha256(k, d)
4834 { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), d)); }
4835function any_hmac_sha256(k, d, e)
4836 { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), d), e); }
4837*/
4838
4839/*
4840 * Perform a simple self-test to see if the VM is working
4841 */
4842function sha256_vm_test()
4843{
4844 return hex_sha256("abc").toLowerCase() ==
4845 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
4846}
4847
4848/**
4849 * Calculate the sha256 of a raw string
4850 * @param s: the raw string
4851 */
4852function rstr_sha256(s)
4853{
4854 return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8));
4855}
4856
4857/**
4858 * Calculate the HMAC-sha256 of a key and some data (raw strings)
4859 */
4860function rstr_hmac_sha256(key, data)
4861{
4862 var bkey = rstr2binb(key);
4863 if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8);
4864
4865 var ipad = Array(16), opad = Array(16);
4866 for(var i = 0; i < 16; i++)
4867 {
4868 ipad[i] = bkey[i] ^ 0x36363636;
4869 opad[i] = bkey[i] ^ 0x5C5C5C5C;
4870 }
4871
4872 var hash = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
4873 return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256));
4874}
4875
4876/**
4877 * Convert a raw string to a hex string
4878 */
4879function rstr2hex(input)
4880{
4881 try { hexcase } catch(e) { hexcase=0; }
4882 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
4883 var output = "";
4884 var x;
4885 for(var i = 0; i < input.length; i++)
4886 {
4887 x = input.charCodeAt(i);
4888 output += hex_tab.charAt((x >>> 4) & 0x0F)
4889 + hex_tab.charAt( x & 0x0F);
4890 }
4891 return output;
4892}
4893
4894/*
4895 * Convert a raw string to a base-64 string
4896 */
4897function rstr2b64(input)
4898{
4899 try { b64pad } catch(e) { b64pad=''; }
4900 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4901 var output = "";
4902 var len = input.length;
4903 for(var i = 0; i < len; i += 3)
4904 {
4905 var triplet = (input.charCodeAt(i) << 16)
4906 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
4907 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
4908 for(var j = 0; j < 4; j++)
4909 {
4910 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
4911 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
4912 }
4913 }
4914 return output;
4915}
4916
4917/*
4918 * Convert a raw string to an arbitrary string encoding
4919 */
4920function rstr2any(input, encoding)
4921{
4922 var divisor = encoding.length;
4923 var remainders = Array();
4924 var i, q, x, quotient;
4925
4926 /* Convert to an array of 16-bit big-endian values, forming the dividend */
4927 var dividend = Array(Math.ceil(input.length / 2));
4928 for(i = 0; i < dividend.length; i++)
4929 {
4930 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
4931 }
4932
4933 /*
4934 * Repeatedly perform a long division. The binary array forms the dividend,
4935 * the length of the encoding is the divisor. Once computed, the quotient
4936 * forms the dividend for the next step. We stop when the dividend is zero.
4937 * All remainders are stored for later use.
4938 */
4939 while(dividend.length > 0)
4940 {
4941 quotient = Array();
4942 x = 0;
4943 for(i = 0; i < dividend.length; i++)
4944 {
4945 x = (x << 16) + dividend[i];
4946 q = Math.floor(x / divisor);
4947 x -= q * divisor;
4948 if(quotient.length > 0 || q > 0)
4949 quotient[quotient.length] = q;
4950 }
4951 remainders[remainders.length] = x;
4952 dividend = quotient;
4953 }
4954
4955 /* Convert the remainders to the output string */
4956 var output = "";
4957 for(i = remainders.length - 1; i >= 0; i--)
4958 output += encoding.charAt(remainders[i]);
4959
4960 /* Append leading zero equivalents */
4961 var full_length = Math.ceil(input.length * 8 /
4962 (Math.log(encoding.length) / Math.log(2)))
4963 for(i = output.length; i < full_length; i++)
4964 output = encoding[0] + output;
4965
4966 return output;
4967}
4968
4969/*
4970 * Encode a string as utf-8.
4971 * For efficiency, this assumes the input is valid utf-16.
4972 */
4973function str2rstr_utf8(input)
4974{
4975 var output = "";
4976 var i = -1;
4977 var x, y;
4978
4979 while(++i < input.length)
4980 {
4981 /* Decode utf-16 surrogate pairs */
4982 x = input.charCodeAt(i);
4983 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
4984 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
4985 {
4986 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
4987 i++;
4988 }
4989
4990 /* Encode output as utf-8 */
4991 if(x <= 0x7F)
4992 output += String.fromCharCode(x);
4993 else if(x <= 0x7FF)
4994 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
4995 0x80 | ( x & 0x3F));
4996 else if(x <= 0xFFFF)
4997 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
4998 0x80 | ((x >>> 6 ) & 0x3F),
4999 0x80 | ( x & 0x3F));
5000 else if(x <= 0x1FFFFF)
5001 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
5002 0x80 | ((x >>> 12) & 0x3F),
5003 0x80 | ((x >>> 6 ) & 0x3F),
5004 0x80 | ( x & 0x3F));
5005 }
5006 return output;
5007}
5008
5009/*
5010 * Encode a string as utf-16
5011 */
5012function str2rstr_utf16le(input)
5013{
5014 var output = "";
5015 for(var i = 0; i < input.length; i++)
5016 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
5017 (input.charCodeAt(i) >>> 8) & 0xFF);
5018 return output;
5019}
5020
5021function str2rstr_utf16be(input)
5022{
5023 var output = "";
5024 for(var i = 0; i < input.length; i++)
5025 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
5026 input.charCodeAt(i) & 0xFF);
5027 return output;
5028}
5029
5030/**
5031 * Convert a raw string to an array of big-endian words
5032 * Characters >255 have their high-byte silently ignored.
5033 */
5034function rstr2binb(input)
5035{
5036 console.log('Raw string comming is '+input);
5037 var output = Array(input.length >> 2);
5038 for(var i = 0; i < output.length; i++)
5039 output[i] = 0;
5040 for(var i = 0; i < input.length * 8; i += 8)
5041 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
5042 return output;
5043}
5044
5045/**
5046 * @author axelcdv
5047 * Convert a byte array to an array of big-endian words
5048 * @param {byte[]} input
5049 * @return the array of big-endian words
5050 */
5051function byteArray2binb(input){
5052 console.log("Byte array coming is " + input);
5053 var output = Array(input.length >> 2);
5054 for(var i = 0; i < output.length; i++)
5055 output[i] = 0;
5056 for(var i = 0; i < input.length * 8; i += 8)
5057 output[i>>5] |= (input[i / 8] & 0xFF) << (24 - i % 32);
5058 return output;
5059}
5060
5061/*
5062 * Convert an array of big-endian words to a string
5063 */
5064function binb2rstr(input)
5065{
5066 var output = "";
5067 for(var i = 0; i < input.length * 32; i += 8)
5068 output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
5069 return output;
5070}
5071
5072/*
5073 * Main sha256 function, with its support functions
5074 */
5075function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
5076function sha256_R (X, n) {return ( X >>> n );}
5077function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
5078function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
5079function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
5080function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
5081function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
5082function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
5083function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
5084function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
5085function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
5086function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
5087
5088var sha256_K = new Array
5089(
5090 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,
5091 -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
5092 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
5093 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,
5094 -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
5095 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
5096 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,
5097 -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
5098 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
5099 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,
5100 -1866530822, -1538233109, -1090935817, -965641998
5101);
5102
5103function binb_sha256(m, l)
5104{
5105 var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534,
5106 1359893119, -1694144372, 528734635, 1541459225);
5107 var W = new Array(64);
5108 var a, b, c, d, e, f, g, h;
5109 var i, j, T1, T2;
5110
5111 /* append padding */
5112 m[l >> 5] |= 0x80 << (24 - l % 32);
5113 m[((l + 64 >> 9) << 4) + 15] = l;
5114
5115 for(i = 0; i < m.length; i += 16)
5116 {
5117 a = HASH[0];
5118 b = HASH[1];
5119 c = HASH[2];
5120 d = HASH[3];
5121 e = HASH[4];
5122 f = HASH[5];
5123 g = HASH[6];
5124 h = HASH[7];
5125
5126 for(j = 0; j < 64; j++)
5127 {
5128 if (j < 16) W[j] = m[j + i];
5129 else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
5130 sha256_Gamma0256(W[j - 15])), W[j - 16]);
5131
5132 T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
5133 sha256_K[j]), W[j]);
5134 T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
5135 h = g;
5136 g = f;
5137 f = e;
5138 e = safe_add(d, T1);
5139 d = c;
5140 c = b;
5141 b = a;
5142 a = safe_add(T1, T2);
5143 }
5144
5145 HASH[0] = safe_add(a, HASH[0]);
5146 HASH[1] = safe_add(b, HASH[1]);
5147 HASH[2] = safe_add(c, HASH[2]);
5148 HASH[3] = safe_add(d, HASH[3]);
5149 HASH[4] = safe_add(e, HASH[4]);
5150 HASH[5] = safe_add(f, HASH[5]);
5151 HASH[6] = safe_add(g, HASH[6]);
5152 HASH[7] = safe_add(h, HASH[7]);
5153 }
5154 return HASH;
5155}
5156
5157function safe_add (x, y)
5158{
5159 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
5160 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
5161 return (msw << 16) | (lsw & 0xFFFF);
5162}
5163
5164/*
5165 * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined
5166 * in FIPS 180-2
5167 * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
5168 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
5169 * Distributed under the BSD License
5170 * See http://pajhome.org.uk/crypt/md5 for details.
5171 */
5172
5173/*
5174 * Configurable variables. You may need to tweak these to be compatible with
5175 * the server-side, but the defaults work in most cases.
5176 */
5177var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
5178var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
5179
5180/*
5181 * These are the functions you'll usually want to call
5182 * They take string arguments and return either hex or base-64 encoded strings
5183 */
5184function hex_sha512(s) { return rstr2hex(rstr_sha512(str2rstr_utf8(s))); }
5185function b64_sha512(s) { return rstr2b64(rstr_sha512(str2rstr_utf8(s))); }
5186function any_sha512(s, e) { return rstr2any(rstr_sha512(str2rstr_utf8(s)), e);}
5187function hex_hmac_sha512(k, d)
5188 { return rstr2hex(rstr_hmac_sha512(str2rstr_utf8(k), str2rstr_utf8(d))); }
5189function b64_hmac_sha512(k, d)
5190 { return rstr2b64(rstr_hmac_sha512(str2rstr_utf8(k), str2rstr_utf8(d))); }
5191function any_hmac_sha512(k, d, e)
5192 { return rstr2any(rstr_hmac_sha512(str2rstr_utf8(k), str2rstr_utf8(d)), e);}
5193
5194/*
5195 * Perform a simple self-test to see if the VM is working
5196 */
5197function sha512_vm_test()
5198{
5199 return hex_sha512("abc").toLowerCase() ==
5200 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
5201 "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
5202}
5203
5204/*
5205 * Calculate the SHA-512 of a raw string
5206 */
5207function rstr_sha512(s)
5208{
5209 return binb2rstr(binb_sha512(rstr2binb(s), s.length * 8));
5210}
5211
5212/*
5213 * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
5214 */
5215function rstr_hmac_sha512(key, data)
5216{
5217 var bkey = rstr2binb(key);
5218 if(bkey.length > 32) bkey = binb_sha512(bkey, key.length * 8);
5219
5220 var ipad = Array(32), opad = Array(32);
5221 for(var i = 0; i < 32; i++)
5222 {
5223 ipad[i] = bkey[i] ^ 0x36363636;
5224 opad[i] = bkey[i] ^ 0x5C5C5C5C;
5225 }
5226
5227 var hash = binb_sha512(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
5228 return binb2rstr(binb_sha512(opad.concat(hash), 1024 + 512));
5229}
5230
5231/*
5232 * Convert a raw string to a hex string
5233 */
5234function rstr2hex(input)
5235{
5236 try { hexcase } catch(e) { hexcase=0; }
5237 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
5238 var output = "";
5239 var x;
5240 for(var i = 0; i < input.length; i++)
5241 {
5242 x = input.charCodeAt(i);
5243 output += hex_tab.charAt((x >>> 4) & 0x0F)
5244 + hex_tab.charAt( x & 0x0F);
5245 }
5246 return output;
5247}
5248
5249/*
5250 * Convert a raw string to a base-64 string
5251 */
5252function rstr2b64(input)
5253{
5254 try { b64pad } catch(e) { b64pad=''; }
5255 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5256 var output = "";
5257 var len = input.length;
5258 for(var i = 0; i < len; i += 3)
5259 {
5260 var triplet = (input.charCodeAt(i) << 16)
5261 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
5262 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
5263 for(var j = 0; j < 4; j++)
5264 {
5265 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
5266 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
5267 }
5268 }
5269 return output;
5270}
5271
5272/*
5273 * Convert a raw string to an arbitrary string encoding
5274 */
5275function rstr2any(input, encoding)
5276{
5277 var divisor = encoding.length;
5278 var i, j, q, x, quotient;
5279
5280 /* Convert to an array of 16-bit big-endian values, forming the dividend */
5281 var dividend = Array(Math.ceil(input.length / 2));
5282 for(i = 0; i < dividend.length; i++)
5283 {
5284 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
5285 }
5286
5287 /*
5288 * Repeatedly perform a long division. The binary array forms the dividend,
5289 * the length of the encoding is the divisor. Once computed, the quotient
5290 * forms the dividend for the next step. All remainders are stored for later
5291 * use.
5292 */
5293 var full_length = Math.ceil(input.length * 8 /
5294 (Math.log(encoding.length) / Math.log(2)));
5295 var remainders = Array(full_length);
5296 for(j = 0; j < full_length; j++)
5297 {
5298 quotient = Array();
5299 x = 0;
5300 for(i = 0; i < dividend.length; i++)
5301 {
5302 x = (x << 16) + dividend[i];
5303 q = Math.floor(x / divisor);
5304 x -= q * divisor;
5305 if(quotient.length > 0 || q > 0)
5306 quotient[quotient.length] = q;
5307 }
5308 remainders[j] = x;
5309 dividend = quotient;
5310 }
5311
5312 /* Convert the remainders to the output string */
5313 var output = "";
5314 for(i = remainders.length - 1; i >= 0; i--)
5315 output += encoding.charAt(remainders[i]);
5316
5317 return output;
5318}
5319
5320/*
5321 * Encode a string as utf-8.
5322 * For efficiency, this assumes the input is valid utf-16.
5323 */
5324function str2rstr_utf8(input)
5325{
5326 var output = "";
5327 var i = -1;
5328 var x, y;
5329
5330 while(++i < input.length)
5331 {
5332 /* Decode utf-16 surrogate pairs */
5333 x = input.charCodeAt(i);
5334 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
5335 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
5336 {
5337 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
5338 i++;
5339 }
5340
5341 /* Encode output as utf-8 */
5342 if(x <= 0x7F)
5343 output += String.fromCharCode(x);
5344 else if(x <= 0x7FF)
5345 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
5346 0x80 | ( x & 0x3F));
5347 else if(x <= 0xFFFF)
5348 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
5349 0x80 | ((x >>> 6 ) & 0x3F),
5350 0x80 | ( x & 0x3F));
5351 else if(x <= 0x1FFFFF)
5352 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
5353 0x80 | ((x >>> 12) & 0x3F),
5354 0x80 | ((x >>> 6 ) & 0x3F),
5355 0x80 | ( x & 0x3F));
5356 }
5357 return output;
5358}
5359
5360/*
5361 * Encode a string as utf-16
5362 */
5363function str2rstr_utf16le(input)
5364{
5365 var output = "";
5366 for(var i = 0; i < input.length; i++)
5367 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
5368 (input.charCodeAt(i) >>> 8) & 0xFF);
5369 return output;
5370}
5371
5372function str2rstr_utf16be(input)
5373{
5374 var output = "";
5375 for(var i = 0; i < input.length; i++)
5376 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
5377 input.charCodeAt(i) & 0xFF);
5378 return output;
5379}
5380
5381/*
5382 * Convert a raw string to an array of big-endian words
5383 * Characters >255 have their high-byte silently ignored.
5384 */
5385function rstr2binb(input)
5386{
5387 var output = Array(input.length >> 2);
5388 for(var i = 0; i < output.length; i++)
5389 output[i] = 0;
5390 for(var i = 0; i < input.length * 8; i += 8)
5391 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
5392 return output;
5393}
5394
5395/*
5396 * Convert an array of big-endian words to a string
5397 */
5398function binb2rstr(input)
5399{
5400 var output = "";
5401 for(var i = 0; i < input.length * 32; i += 8)
5402 output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
5403 return output;
5404}
5405
5406/*
5407 * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
5408 */
5409var sha512_k;
5410function binb_sha512(x, len)
5411{
5412 if(sha512_k == undefined)
5413 {
5414 //SHA512 constants
5415 sha512_k = new Array(
5416new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
5417new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
5418new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
5419new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
5420new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
5421new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
5422new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
5423new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
5424new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
5425new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
5426new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
5427new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
5428new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
5429new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
5430new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
5431new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
5432new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
5433new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
5434new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
5435new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
5436new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
5437new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
5438new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
5439new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
5440new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
5441new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
5442new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
5443new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
5444new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
5445new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
5446new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
5447new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
5448new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
5449new int64(-354779690, -840897762), new int64(-176337025, -294727304),
5450new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
5451new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
5452new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
5453new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
5454new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
5455new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817));
5456 }
5457
5458 //Initial hash values
5459 var H = new Array(
5460new int64(0x6a09e667, -205731576),
5461new int64(-1150833019, -2067093701),
5462new int64(0x3c6ef372, -23791573),
5463new int64(-1521486534, 0x5f1d36f1),
5464new int64(0x510e527f, -1377402159),
5465new int64(-1694144372, 0x2b3e6c1f),
5466new int64(0x1f83d9ab, -79577749),
5467new int64(0x5be0cd19, 0x137e2179));
5468
5469 var T1 = new int64(0, 0),
5470 T2 = new int64(0, 0),
5471 a = new int64(0,0),
5472 b = new int64(0,0),
5473 c = new int64(0,0),
5474 d = new int64(0,0),
5475 e = new int64(0,0),
5476 f = new int64(0,0),
5477 g = new int64(0,0),
5478 h = new int64(0,0),
5479 //Temporary variables not specified by the document
5480 s0 = new int64(0, 0),
5481 s1 = new int64(0, 0),
5482 Ch = new int64(0, 0),
5483 Maj = new int64(0, 0),
5484 r1 = new int64(0, 0),
5485 r2 = new int64(0, 0),
5486 r3 = new int64(0, 0);
5487 var j, i;
5488 var W = new Array(80);
5489 for(i=0; i<80; i++)
5490 W[i] = new int64(0, 0);
5491
5492 // append padding to the source string. The format is described in the FIPS.
5493 x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
5494 x[((len + 128 >> 10)<< 5) + 31] = len;
5495
5496 for(i = 0; i<x.length; i+=32) //32 dwords is the block size
5497 {
5498 int64copy(a, H[0]);
5499 int64copy(b, H[1]);
5500 int64copy(c, H[2]);
5501 int64copy(d, H[3]);
5502 int64copy(e, H[4]);
5503 int64copy(f, H[5]);
5504 int64copy(g, H[6]);
5505 int64copy(h, H[7]);
5506
5507 for(j=0; j<16; j++)
5508 {
5509 W[j].h = x[i + 2*j];
5510 W[j].l = x[i + 2*j + 1];
5511 }
5512
5513 for(j=16; j<80; j++)
5514 {
5515 //sigma1
5516 int64rrot(r1, W[j-2], 19);
5517 int64revrrot(r2, W[j-2], 29);
5518 int64shr(r3, W[j-2], 6);
5519 s1.l = r1.l ^ r2.l ^ r3.l;
5520 s1.h = r1.h ^ r2.h ^ r3.h;
5521 //sigma0
5522 int64rrot(r1, W[j-15], 1);
5523 int64rrot(r2, W[j-15], 8);
5524 int64shr(r3, W[j-15], 7);
5525 s0.l = r1.l ^ r2.l ^ r3.l;
5526 s0.h = r1.h ^ r2.h ^ r3.h;
5527
5528 int64add4(W[j], s1, W[j-7], s0, W[j-16]);
5529 }
5530
5531 for(j = 0; j < 80; j++)
5532 {
5533 //Ch
5534 Ch.l = (e.l & f.l) ^ (~e.l & g.l);
5535 Ch.h = (e.h & f.h) ^ (~e.h & g.h);
5536
5537 //Sigma1
5538 int64rrot(r1, e, 14);
5539 int64rrot(r2, e, 18);
5540 int64revrrot(r3, e, 9);
5541 s1.l = r1.l ^ r2.l ^ r3.l;
5542 s1.h = r1.h ^ r2.h ^ r3.h;
5543
5544 //Sigma0
5545 int64rrot(r1, a, 28);
5546 int64revrrot(r2, a, 2);
5547 int64revrrot(r3, a, 7);
5548 s0.l = r1.l ^ r2.l ^ r3.l;
5549 s0.h = r1.h ^ r2.h ^ r3.h;
5550
5551 //Maj
5552 Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
5553 Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
5554
5555 int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
5556 int64add(T2, s0, Maj);
5557
5558 int64copy(h, g);
5559 int64copy(g, f);
5560 int64copy(f, e);
5561 int64add(e, d, T1);
5562 int64copy(d, c);
5563 int64copy(c, b);
5564 int64copy(b, a);
5565 int64add(a, T1, T2);
5566 }
5567 int64add(H[0], H[0], a);
5568 int64add(H[1], H[1], b);
5569 int64add(H[2], H[2], c);
5570 int64add(H[3], H[3], d);
5571 int64add(H[4], H[4], e);
5572 int64add(H[5], H[5], f);
5573 int64add(H[6], H[6], g);
5574 int64add(H[7], H[7], h);
5575 }
5576
5577 //represent the hash as an array of 32-bit dwords
5578 var hash = new Array(16);
5579 for(i=0; i<8; i++)
5580 {
5581 hash[2*i] = H[i].h;
5582 hash[2*i + 1] = H[i].l;
5583 }
5584 return hash;
5585}
5586
5587//A constructor for 64-bit numbers
5588function int64(h, l)
5589{
5590 this.h = h;
5591 this.l = l;
5592 //this.toString = int64toString;
5593}
5594
5595//Copies src into dst, assuming both are 64-bit numbers
5596function int64copy(dst, src)
5597{
5598 dst.h = src.h;
5599 dst.l = src.l;
5600}
5601
5602//Right-rotates a 64-bit number by shift
5603//Won't handle cases of shift>=32
5604//The function revrrot() is for that
5605function int64rrot(dst, x, shift)
5606{
5607 dst.l = (x.l >>> shift) | (x.h << (32-shift));
5608 dst.h = (x.h >>> shift) | (x.l << (32-shift));
5609}
5610
5611//Reverses the dwords of the source and then rotates right by shift.
5612//This is equivalent to rotation by 32+shift
5613function int64revrrot(dst, x, shift)
5614{
5615 dst.l = (x.h >>> shift) | (x.l << (32-shift));
5616 dst.h = (x.l >>> shift) | (x.h << (32-shift));
5617}
5618
5619//Bitwise-shifts right a 64-bit number by shift
5620//Won't handle shift>=32, but it's never needed in SHA512
5621function int64shr(dst, x, shift)
5622{
5623 dst.l = (x.l >>> shift) | (x.h << (32-shift));
5624 dst.h = (x.h >>> shift);
5625}
5626
5627//Adds two 64-bit numbers
5628//Like the original implementation, does not rely on 32-bit operations
5629function int64add(dst, x, y)
5630{
5631 var w0 = (x.l & 0xffff) + (y.l & 0xffff);
5632 var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
5633 var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
5634 var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
5635 dst.l = (w0 & 0xffff) | (w1 << 16);
5636 dst.h = (w2 & 0xffff) | (w3 << 16);
5637}
5638
5639//Same, except with 4 addends. Works faster than adding them one by one.
5640function int64add4(dst, a, b, c, d)
5641{
5642 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
5643 var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
5644 var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
5645 var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
5646 dst.l = (w0 & 0xffff) | (w1 << 16);
5647 dst.h = (w2 & 0xffff) | (w3 << 16);
5648}
5649
5650//Same, except with 5 addends
5651function int64add5(dst, a, b, c, d, e)
5652{
5653 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff);
5654 var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16);
5655 var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16);
5656 var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
5657 dst.l = (w0 & 0xffff) | (w1 << 16);
5658 dst.h = (w2 & 0xffff) | (w3 << 16);
5659}
5660
5661/*
5662 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
5663 * Digest Algorithm, as defined in RFC 1321.
5664 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
5665 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
5666 * Distributed under the BSD License
5667 * See http://pajhome.org.uk/crypt/md5 for more info.
5668 */
5669
5670/*
5671 * Configurable variables. You may need to tweak these to be compatible with
5672 * the server-side, but the defaults work in most cases.
5673 */
5674var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
5675var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
5676
5677/*
5678 * These are the functions you'll usually want to call
5679 * They take string arguments and return either hex or base-64 encoded strings
5680 */
5681function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
5682function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
5683function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
5684function hex_hmac_md5(k, d)
5685 { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
5686function b64_hmac_md5(k, d)
5687 { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
5688function any_hmac_md5(k, d, e)
5689 { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
5690
5691/*
5692 * Perform a simple self-test to see if the VM is working
5693 */
5694function md5_vm_test()
5695{
5696 return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
5697}
5698
5699/*
5700 * Calculate the MD5 of a raw string
5701 */
5702function rstr_md5(s)
5703{
5704 return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
5705}
5706
5707/*
5708 * Calculate the HMAC-MD5, of a key and some data (raw strings)
5709 */
5710function rstr_hmac_md5(key, data)
5711{
5712 var bkey = rstr2binl(key);
5713 if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
5714
5715 var ipad = Array(16), opad = Array(16);
5716 for(var i = 0; i < 16; i++)
5717 {
5718 ipad[i] = bkey[i] ^ 0x36363636;
5719 opad[i] = bkey[i] ^ 0x5C5C5C5C;
5720 }
5721
5722 var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
5723 return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
5724}
5725
5726/*
5727 * Convert a raw string to a hex string
5728 */
5729function rstr2hex(input)
5730{
5731 try { hexcase } catch(e) { hexcase=0; }
5732 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
5733 var output = "";
5734 var x;
5735 for(var i = 0; i < input.length; i++)
5736 {
5737 x = input.charCodeAt(i);
5738 output += hex_tab.charAt((x >>> 4) & 0x0F)
5739 + hex_tab.charAt( x & 0x0F);
5740 }
5741 return output;
5742}
5743
5744/*
5745 * Convert a raw string to a base-64 string
5746 */
5747function rstr2b64(input)
5748{
5749 try { b64pad } catch(e) { b64pad=''; }
5750 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5751 var output = "";
5752 var len = input.length;
5753 for(var i = 0; i < len; i += 3)
5754 {
5755 var triplet = (input.charCodeAt(i) << 16)
5756 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
5757 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
5758 for(var j = 0; j < 4; j++)
5759 {
5760 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
5761 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
5762 }
5763 }
5764 return output;
5765}
5766
5767/*
5768 * Convert a raw string to an arbitrary string encoding
5769 */
5770function rstr2any(input, encoding)
5771{
5772 var divisor = encoding.length;
5773 var i, j, q, x, quotient;
5774
5775 /* Convert to an array of 16-bit big-endian values, forming the dividend */
5776 var dividend = Array(Math.ceil(input.length / 2));
5777 for(i = 0; i < dividend.length; i++)
5778 {
5779 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
5780 }
5781
5782 /*
5783 * Repeatedly perform a long division. The binary array forms the dividend,
5784 * the length of the encoding is the divisor. Once computed, the quotient
5785 * forms the dividend for the next step. All remainders are stored for later
5786 * use.
5787 */
5788 var full_length = Math.ceil(input.length * 8 /
5789 (Math.log(encoding.length) / Math.log(2)));
5790 var remainders = Array(full_length);
5791 for(j = 0; j < full_length; j++)
5792 {
5793 quotient = Array();
5794 x = 0;
5795 for(i = 0; i < dividend.length; i++)
5796 {
5797 x = (x << 16) + dividend[i];
5798 q = Math.floor(x / divisor);
5799 x -= q * divisor;
5800 if(quotient.length > 0 || q > 0)
5801 quotient[quotient.length] = q;
5802 }
5803 remainders[j] = x;
5804 dividend = quotient;
5805 }
5806
5807 /* Convert the remainders to the output string */
5808 var output = "";
5809 for(i = remainders.length - 1; i >= 0; i--)
5810 output += encoding.charAt(remainders[i]);
5811
5812 return output;
5813}
5814
5815/*
5816 * Encode a string as utf-8.
5817 * For efficiency, this assumes the input is valid utf-16.
5818 */
5819function str2rstr_utf8(input)
5820{
5821 var output = "";
5822 var i = -1;
5823 var x, y;
5824
5825 while(++i < input.length)
5826 {
5827 /* Decode utf-16 surrogate pairs */
5828 x = input.charCodeAt(i);
5829 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
5830 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
5831 {
5832 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
5833 i++;
5834 }
5835
5836 /* Encode output as utf-8 */
5837 if(x <= 0x7F)
5838 output += String.fromCharCode(x);
5839 else if(x <= 0x7FF)
5840 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
5841 0x80 | ( x & 0x3F));
5842 else if(x <= 0xFFFF)
5843 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
5844 0x80 | ((x >>> 6 ) & 0x3F),
5845 0x80 | ( x & 0x3F));
5846 else if(x <= 0x1FFFFF)
5847 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
5848 0x80 | ((x >>> 12) & 0x3F),
5849 0x80 | ((x >>> 6 ) & 0x3F),
5850 0x80 | ( x & 0x3F));
5851 }
5852 return output;
5853}
5854
5855/*
5856 * Encode a string as utf-16
5857 */
5858function str2rstr_utf16le(input)
5859{
5860 var output = "";
5861 for(var i = 0; i < input.length; i++)
5862 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
5863 (input.charCodeAt(i) >>> 8) & 0xFF);
5864 return output;
5865}
5866
5867function str2rstr_utf16be(input)
5868{
5869 var output = "";
5870 for(var i = 0; i < input.length; i++)
5871 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
5872 input.charCodeAt(i) & 0xFF);
5873 return output;
5874}
5875
5876/*
5877 * Convert a raw string to an array of little-endian words
5878 * Characters >255 have their high-byte silently ignored.
5879 */
5880function rstr2binl(input)
5881{
5882 var output = Array(input.length >> 2);
5883 for(var i = 0; i < output.length; i++)
5884 output[i] = 0;
5885 for(var i = 0; i < input.length * 8; i += 8)
5886 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
5887 return output;
5888}
5889
5890/*
5891 * Convert an array of little-endian words to a string
5892 */
5893function binl2rstr(input)
5894{
5895 var output = "";
5896 for(var i = 0; i < input.length * 32; i += 8)
5897 output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
5898 return output;
5899}
5900
5901/*
5902 * Calculate the MD5 of an array of little-endian words, and a bit length.
5903 */
5904function binl_md5(x, len)
5905{
5906 /* append padding */
5907 x[len >> 5] |= 0x80 << ((len) % 32);
5908 x[(((len + 64) >>> 9) << 4) + 14] = len;
5909
5910 var a = 1732584193;
5911 var b = -271733879;
5912 var c = -1732584194;
5913 var d = 271733878;
5914
5915 for(var i = 0; i < x.length; i += 16)
5916 {
5917 var olda = a;
5918 var oldb = b;
5919 var oldc = c;
5920 var oldd = d;
5921
5922 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
5923 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
5924 c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
5925 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
5926 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
5927 d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
5928 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
5929 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
5930 a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
5931 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
5932 c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
5933 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
5934 a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
5935 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
5936 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
5937 b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
5938
5939 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
5940 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
5941 c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
5942 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
5943 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
5944 d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
5945 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
5946 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
5947 a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
5948 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
5949 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
5950 b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
5951 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
5952 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
5953 c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
5954 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
5955
5956 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
5957 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
5958 c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
5959 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
5960 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
5961 d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
5962 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
5963 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
5964 a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
5965 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
5966 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
5967 b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
5968 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
5969 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
5970 c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
5971 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
5972
5973 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
5974 d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
5975 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
5976 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
5977 a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
5978 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
5979 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
5980 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
5981 a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
5982 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
5983 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
5984 b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
5985 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
5986 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
5987 c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
5988 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
5989
5990 a = safe_add(a, olda);
5991 b = safe_add(b, oldb);
5992 c = safe_add(c, oldc);
5993 d = safe_add(d, oldd);
5994 }
5995 return Array(a, b, c, d);
5996}
5997
5998/*
5999 * These functions implement the four basic operations the algorithm uses.
6000 */
6001function md5_cmn(q, a, b, x, s, t)
6002{
6003 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
6004}
6005function md5_ff(a, b, c, d, x, s, t)
6006{
6007 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
6008}
6009function md5_gg(a, b, c, d, x, s, t)
6010{
6011 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
6012}
6013function md5_hh(a, b, c, d, x, s, t)
6014{
6015 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
6016}
6017function md5_ii(a, b, c, d, x, s, t)
6018{
6019 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
6020}
6021
6022/*
6023 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
6024 * to work around bugs in some JS interpreters.
6025 */
6026function safe_add(x, y)
6027{
6028 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
6029 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
6030 return (msw << 16) | (lsw & 0xFFFF);
6031}
6032
6033/*
6034 * Bitwise rotate a 32-bit number to the left.
6035 */
6036function bit_rol(num, cnt)
6037{
6038 return (num << cnt) | (num >>> (32 - cnt));
6039}
6040
6041/*
6042 * A JavaScript implementation of the RIPEMD-160 Algorithm
6043 * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
6044 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6045 * Distributed under the BSD License
6046 * See http://pajhome.org.uk/crypt/md5 for details.
6047 * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
6048 */
6049
6050/*
6051 * Configurable variables. You may need to tweak these to be compatible with
6052 * the server-side, but the defaults work in most cases.
6053 */
6054var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
6055var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
6056
6057/*
6058 * These are the functions you'll usually want to call
6059 * They take string arguments and return either hex or base-64 encoded strings
6060 */
6061function hex_rmd160(s) { return rstr2hex(rstr_rmd160(str2rstr_utf8(s))); }
6062function b64_rmd160(s) { return rstr2b64(rstr_rmd160(str2rstr_utf8(s))); }
6063function any_rmd160(s, e) { return rstr2any(rstr_rmd160(str2rstr_utf8(s)), e); }
6064function hex_hmac_rmd160(k, d)
6065 { return rstr2hex(rstr_hmac_rmd160(str2rstr_utf8(k), str2rstr_utf8(d))); }
6066function b64_hmac_rmd160(k, d)
6067 { return rstr2b64(rstr_hmac_rmd160(str2rstr_utf8(k), str2rstr_utf8(d))); }
6068function any_hmac_rmd160(k, d, e)
6069 { return rstr2any(rstr_hmac_rmd160(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
6070
6071/*
6072 * Perform a simple self-test to see if the VM is working
6073 */
6074function rmd160_vm_test()
6075{
6076 return hex_rmd160("abc").toLowerCase() == "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc";
6077}
6078
6079/*
6080 * Calculate the rmd160 of a raw string
6081 */
6082function rstr_rmd160(s)
6083{
6084 return binl2rstr(binl_rmd160(rstr2binl(s), s.length * 8));
6085}
6086
6087/*
6088 * Calculate the HMAC-rmd160 of a key and some data (raw strings)
6089 */
6090function rstr_hmac_rmd160(key, data)
6091{
6092 var bkey = rstr2binl(key);
6093 if(bkey.length > 16) bkey = binl_rmd160(bkey, key.length * 8);
6094
6095 var ipad = Array(16), opad = Array(16);
6096 for(var i = 0; i < 16; i++)
6097 {
6098 ipad[i] = bkey[i] ^ 0x36363636;
6099 opad[i] = bkey[i] ^ 0x5C5C5C5C;
6100 }
6101
6102 var hash = binl_rmd160(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
6103 return binl2rstr(binl_rmd160(opad.concat(hash), 512 + 160));
6104}
6105
6106/*
6107 * Convert a raw string to a hex string
6108 */
6109function rstr2hex(input)
6110{
6111 try { hexcase } catch(e) { hexcase=0; }
6112 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
6113 var output = "";
6114 var x;
6115 for(var i = 0; i < input.length; i++)
6116 {
6117 x = input.charCodeAt(i);
6118 output += hex_tab.charAt((x >>> 4) & 0x0F)
6119 + hex_tab.charAt( x & 0x0F);
6120 }
6121 return output;
6122}
6123
6124/*
6125 * Convert a raw string to a base-64 string
6126 */
6127function rstr2b64(input)
6128{
6129 try { b64pad } catch(e) { b64pad=''; }
6130 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6131 var output = "";
6132 var len = input.length;
6133 for(var i = 0; i < len; i += 3)
6134 {
6135 var triplet = (input.charCodeAt(i) << 16)
6136 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
6137 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
6138 for(var j = 0; j < 4; j++)
6139 {
6140 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
6141 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
6142 }
6143 }
6144 return output;
6145}
6146
6147/*
6148 * Convert a raw string to an arbitrary string encoding
6149 */
6150function rstr2any(input, encoding)
6151{
6152 var divisor = encoding.length;
6153 var remainders = Array();
6154 var i, q, x, quotient;
6155
6156 /* Convert to an array of 16-bit big-endian values, forming the dividend */
6157 var dividend = Array(Math.ceil(input.length / 2));
6158 for(i = 0; i < dividend.length; i++)
6159 {
6160 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
6161 }
6162
6163 /*
6164 * Repeatedly perform a long division. The binary array forms the dividend,
6165 * the length of the encoding is the divisor. Once computed, the quotient
6166 * forms the dividend for the next step. We stop when the dividend is zero.
6167 * All remainders are stored for later use.
6168 */
6169 while(dividend.length > 0)
6170 {
6171 quotient = Array();
6172 x = 0;
6173 for(i = 0; i < dividend.length; i++)
6174 {
6175 x = (x << 16) + dividend[i];
6176 q = Math.floor(x / divisor);
6177 x -= q * divisor;
6178 if(quotient.length > 0 || q > 0)
6179 quotient[quotient.length] = q;
6180 }
6181 remainders[remainders.length] = x;
6182 dividend = quotient;
6183 }
6184
6185 /* Convert the remainders to the output string */
6186 var output = "";
6187 for(i = remainders.length - 1; i >= 0; i--)
6188 output += encoding.charAt(remainders[i]);
6189
6190 /* Append leading zero equivalents */
6191 var full_length = Math.ceil(input.length * 8 /
6192 (Math.log(encoding.length) / Math.log(2)))
6193 for(i = output.length; i < full_length; i++)
6194 output = encoding[0] + output;
6195
6196 return output;
6197}
6198
6199/*
6200 * Encode a string as utf-8.
6201 * For efficiency, this assumes the input is valid utf-16.
6202 */
6203function str2rstr_utf8(input)
6204{
6205 var output = "";
6206 var i = -1;
6207 var x, y;
6208
6209 while(++i < input.length)
6210 {
6211 /* Decode utf-16 surrogate pairs */
6212 x = input.charCodeAt(i);
6213 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
6214 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
6215 {
6216 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
6217 i++;
6218 }
6219
6220 /* Encode output as utf-8 */
6221 if(x <= 0x7F)
6222 output += String.fromCharCode(x);
6223 else if(x <= 0x7FF)
6224 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
6225 0x80 | ( x & 0x3F));
6226 else if(x <= 0xFFFF)
6227 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
6228 0x80 | ((x >>> 6 ) & 0x3F),
6229 0x80 | ( x & 0x3F));
6230 else if(x <= 0x1FFFFF)
6231 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
6232 0x80 | ((x >>> 12) & 0x3F),
6233 0x80 | ((x >>> 6 ) & 0x3F),
6234 0x80 | ( x & 0x3F));
6235 }
6236 return output;
6237}
6238
6239/*
6240 * Encode a string as utf-16
6241 */
6242function str2rstr_utf16le(input)
6243{
6244 var output = "";
6245 for(var i = 0; i < input.length; i++)
6246 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
6247 (input.charCodeAt(i) >>> 8) & 0xFF);
6248 return output;
6249}
6250
6251function str2rstr_utf16be(input)
6252{
6253 var output = "";
6254 for(var i = 0; i < input.length; i++)
6255 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
6256 input.charCodeAt(i) & 0xFF);
6257 return output;
6258}
6259
6260/*
6261 * Convert a raw string to an array of little-endian words
6262 * Characters >255 have their high-byte silently ignored.
6263 */
6264function rstr2binl(input)
6265{
6266 var output = Array(input.length >> 2);
6267 for(var i = 0; i < output.length; i++)
6268 output[i] = 0;
6269 for(var i = 0; i < input.length * 8; i += 8)
6270 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
6271 return output;
6272}
6273
6274/*
6275 * Convert an array of little-endian words to a string
6276 */
6277function binl2rstr(input)
6278{
6279 var output = "";
6280 for(var i = 0; i < input.length * 32; i += 8)
6281 output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
6282 return output;
6283}
6284
6285/*
6286 * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
6287 */
6288function binl_rmd160(x, len)
6289{
6290 /* append padding */
6291 x[len >> 5] |= 0x80 << (len % 32);
6292 x[(((len + 64) >>> 9) << 4) + 14] = len;
6293
6294 var h0 = 0x67452301;
6295 var h1 = 0xefcdab89;
6296 var h2 = 0x98badcfe;
6297 var h3 = 0x10325476;
6298 var h4 = 0xc3d2e1f0;
6299
6300 for (var i = 0; i < x.length; i += 16) {
6301 var T;
6302 var A1 = h0, B1 = h1, C1 = h2, D1 = h3, E1 = h4;
6303 var A2 = h0, B2 = h1, C2 = h2, D2 = h3, E2 = h4;
6304 for (var j = 0; j <= 79; ++j) {
6305 T = safe_add(A1, rmd160_f(j, B1, C1, D1));
6306 T = safe_add(T, x[i + rmd160_r1[j]]);
6307 T = safe_add(T, rmd160_K1(j));
6308 T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
6309 A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T;
6310 T = safe_add(A2, rmd160_f(79-j, B2, C2, D2));
6311 T = safe_add(T, x[i + rmd160_r2[j]]);
6312 T = safe_add(T, rmd160_K2(j));
6313 T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
6314 A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T;
6315 }
6316 T = safe_add(h1, safe_add(C1, D2));
6317 h1 = safe_add(h2, safe_add(D1, E2));
6318 h2 = safe_add(h3, safe_add(E1, A2));
6319 h3 = safe_add(h4, safe_add(A1, B2));
6320 h4 = safe_add(h0, safe_add(B1, C2));
6321 h0 = T;
6322 }
6323 return [h0, h1, h2, h3, h4];
6324}
6325
6326function rmd160_f(j, x, y, z)
6327{
6328 return ( 0 <= j && j <= 15) ? (x ^ y ^ z) :
6329 (16 <= j && j <= 31) ? (x & y) | (~x & z) :
6330 (32 <= j && j <= 47) ? (x | ~y) ^ z :
6331 (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
6332 (64 <= j && j <= 79) ? x ^ (y | ~z) :
6333 "rmd160_f: j out of range";
6334}
6335function rmd160_K1(j)
6336{
6337 return ( 0 <= j && j <= 15) ? 0x00000000 :
6338 (16 <= j && j <= 31) ? 0x5a827999 :
6339 (32 <= j && j <= 47) ? 0x6ed9eba1 :
6340 (48 <= j && j <= 63) ? 0x8f1bbcdc :
6341 (64 <= j && j <= 79) ? 0xa953fd4e :
6342 "rmd160_K1: j out of range";
6343}
6344function rmd160_K2(j)
6345{
6346 return ( 0 <= j && j <= 15) ? 0x50a28be6 :
6347 (16 <= j && j <= 31) ? 0x5c4dd124 :
6348 (32 <= j && j <= 47) ? 0x6d703ef3 :
6349 (48 <= j && j <= 63) ? 0x7a6d76e9 :
6350 (64 <= j && j <= 79) ? 0x00000000 :
6351 "rmd160_K2: j out of range";
6352}
6353var rmd160_r1 = [
6354 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
6355 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
6356 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
6357 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
6358 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
6359];
6360var rmd160_r2 = [
6361 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6362 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
6363 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
6364 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
6365 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
6366];
6367var rmd160_s1 = [
6368 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
6369 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
6370 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
6371 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
6372 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
6373];
6374var rmd160_s2 = [
6375 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
6376 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
6377 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
6378 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
6379 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
6380];
6381
6382/*
6383 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
6384 * to work around bugs in some JS interpreters.
6385 */
6386function safe_add(x, y)
6387{
6388 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
6389 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
6390 return (msw << 16) | (lsw & 0xFFFF);
6391}
6392
6393/*
6394 * Bitwise rotate a 32-bit number to the left.
6395 */
6396function bit_rol(num, cnt)
6397{
6398 return (num << cnt) | (num >>> (32 - cnt));
6399}
6400
6401var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6402var b64pad="=";
6403
6404function hex2b64(h) {
6405 var i;
6406 var c;
6407 var ret = "";
6408 for(i = 0; i+3 <= h.length; i+=3) {
6409 c = parseInt(h.substring(i,i+3),16);
6410 ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
6411 }
6412 if(i+1 == h.length) {
6413 c = parseInt(h.substring(i,i+1),16);
6414 ret += b64map.charAt(c << 2);
6415 }
6416 else if(i+2 == h.length) {
6417 c = parseInt(h.substring(i,i+2),16);
6418 ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
6419 }
6420 while((ret.length & 3) > 0) ret += b64pad;
6421 return ret;
6422}
6423
6424// convert a base64 string to hex
6425function b64tohex(s) {
6426 var ret = ""
6427 var i;
6428 var k = 0; // b64 state, 0-3
6429 var slop;
6430 for(i = 0; i < s.length; ++i) {
6431 if(s.charAt(i) == b64pad) break;
6432 v = b64map.indexOf(s.charAt(i));
6433 if(v < 0) continue;
6434 if(k == 0) {
6435 ret += int2char(v >> 2);
6436 slop = v & 3;
6437 k = 1;
6438 }
6439 else if(k == 1) {
6440 ret += int2char((slop << 2) | (v >> 4));
6441 slop = v & 0xf;
6442 k = 2;
6443 }
6444 else if(k == 2) {
6445 ret += int2char(slop);
6446 ret += int2char(v >> 2);
6447 slop = v & 3;
6448 k = 3;
6449 }
6450 else {
6451 ret += int2char((slop << 2) | (v >> 4));
6452 ret += int2char(v & 0xf);
6453 k = 0;
6454 }
6455 }
6456 if(k == 1)
6457 ret += int2char(slop << 2);
6458 return ret;
6459}
6460
6461// convert a base64 string to a byte/number array
6462function b64toBA(s) {
6463 //piggyback on b64tohex for now, optimize later
6464 var h = b64tohex(s);
6465 var i;
6466 var a = new Array();
6467 for(i = 0; 2*i < h.length; ++i) {
6468 a[i] = parseInt(h.substring(2*i,2*i+2),16);
6469 }
6470 return a;
6471}
6472
6473// Depends on jsbn.js and rng.js
6474
6475// Version 1.1: support utf-8 encoding in pkcs1pad2
6476
6477// convert a (hex) string to a bignum object
6478function parseBigInt(str,r) {
6479 return new BigInteger(str,r);
6480}
6481
6482function linebrk(s,n) {
6483 var ret = "";
6484 var i = 0;
6485 while(i + n < s.length) {
6486 ret += s.substring(i,i+n) + "\n";
6487 i += n;
6488 }
6489 return ret + s.substring(i,s.length);
6490}
6491
6492function byte2Hex(b) {
6493 if(b < 0x10)
6494 return "0" + b.toString(16);
6495 else
6496 return b.toString(16);
6497}
6498
6499/**
6500 * PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
6501 * @param s: the string to encode
6502 * @param n: the size in byte
6503 */
6504function pkcs1pad2(s,n) {
6505 if(n < s.length + 11) { // TODO: fix for utf-8
6506 alert("Message too long for RSA");
6507 return null;
6508 }
6509 var ba = new Array();
6510 var i = s.length - 1;
6511 while(i >= 0 && n > 0) {
6512 var c = s.charCodeAt(i--);
6513 if(c < 128) { // encode using utf-8
6514 ba[--n] = c;
6515 }
6516 else if((c > 127) && (c < 2048)) {
6517 ba[--n] = (c & 63) | 128;
6518 ba[--n] = (c >> 6) | 192;
6519 }
6520 else {
6521 ba[--n] = (c & 63) | 128;
6522 ba[--n] = ((c >> 6) & 63) | 128;
6523 ba[--n] = (c >> 12) | 224;
6524 }
6525 }
6526 ba[--n] = 0;
6527 var rng = new SecureRandom();
6528 var x = new Array();
6529 while(n > 2) { // random non-zero pad
6530 x[0] = 0;
6531 while(x[0] == 0) rng.nextBytes(x);
6532 ba[--n] = x[0];
6533 }
6534 ba[--n] = 2;
6535 ba[--n] = 0;
6536 return new BigInteger(ba);
6537}
6538
6539/**
6540 * "empty" RSA key constructor
6541 * @returns {RSAKey}
6542 */
6543function RSAKey() {
6544 this.n = null;
6545 this.e = 0;
6546 this.d = null;
6547 this.p = null;
6548 this.q = null;
6549 this.dmp1 = null;
6550 this.dmq1 = null;
6551 this.coeff = null;
6552}
6553
6554/**
6555 * Set the public key fields N and e from hex strings
6556 * @param N
6557 * @param E
6558 * @returns {RSASetPublic}
6559 */
6560function RSASetPublic(N,E) {
6561 if(N != null && E != null && N.length > 0 && E.length > 0) {
6562 this.n = parseBigInt(N,16);
6563 this.e = parseInt(E,16);
6564 }
6565 else
6566 alert("Invalid RSA public key");
6567}
6568
6569/**
6570 * Perform raw public operation on "x": return x^e (mod n)
6571 * @param x
6572 * @returns x^e (mod n)
6573 */
6574function RSADoPublic(x) {
6575 return x.modPowInt(this.e, this.n);
6576}
6577
6578/**
6579 * Return the PKCS#1 RSA encryption of "text" as an even-length hex string
6580 */
6581function RSAEncrypt(text) {
6582 var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
6583 if(m == null) return null;
6584 var c = this.doPublic(m);
6585 if(c == null) return null;
6586 var h = c.toString(16);
6587 if((h.length & 1) == 0) return h; else return "0" + h;
6588}
6589
6590// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
6591//function RSAEncryptB64(text) {
6592// var h = this.encrypt(text);
6593// if(h) return hex2b64(h); else return null;
6594//}
6595
6596// protected
6597RSAKey.prototype.doPublic = RSADoPublic;
6598
6599// public
6600RSAKey.prototype.setPublic = RSASetPublic;
6601RSAKey.prototype.encrypt = RSAEncrypt;
6602//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
6603
6604// Depends on rsa.js and jsbn2.js
6605
6606// Version 1.1: support utf-8 decoding in pkcs1unpad2
6607
6608// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
6609function pkcs1unpad2(d,n) {
6610 var b = d.toByteArray();
6611 var i = 0;
6612 while(i < b.length && b[i] == 0) ++i;
6613 if(b.length-i != n-1 || b[i] != 2)
6614 return null;
6615 ++i;
6616 while(b[i] != 0)
6617 if(++i >= b.length) return null;
6618 var ret = "";
6619 while(++i < b.length) {
6620 var c = b[i] & 255;
6621 if(c < 128) { // utf-8 decode
6622 ret += String.fromCharCode(c);
6623 }
6624 else if((c > 191) && (c < 224)) {
6625 ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63));
6626 ++i;
6627 }
6628 else {
6629 ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63));
6630 i += 2;
6631 }
6632 }
6633 return ret;
6634}
6635
6636// Set the private key fields N, e, and d from hex strings
6637function RSASetPrivate(N,E,D) {
6638 if(N != null && E != null && N.length > 0 && E.length > 0) {
6639 this.n = parseBigInt(N,16);
6640 this.e = parseInt(E,16);
6641 this.d = parseBigInt(D,16);
6642 }
6643 else
6644 alert("Invalid RSA private key");
6645}
6646
6647// Set the private key fields N, e, d and CRT params from hex strings
6648function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
6649 if(N != null && E != null && N.length > 0 && E.length > 0) {
6650 this.n = parseBigInt(N,16);
6651 this.e = parseInt(E,16);
6652 this.d = parseBigInt(D,16);
6653 this.p = parseBigInt(P,16);
6654 this.q = parseBigInt(Q,16);
6655 this.dmp1 = parseBigInt(DP,16);
6656 this.dmq1 = parseBigInt(DQ,16);
6657 this.coeff = parseBigInt(C,16);
6658 }
6659 else
6660 alert("Invalid RSA private key");
6661}
6662
6663/**
6664 * Generate a new random private key B bits long, using public expt E
6665 */
6666function RSAGenerate(B,E) {
6667 var rng = new SecureRandom();
6668 var qs = B>>1;
6669 this.e = parseInt(E,16);
6670 var ee = new BigInteger(E,16);
6671 for(;;) {
6672 for(;;) {
6673 this.p = new BigInteger(B-qs,1,rng);
6674 if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
6675 }
6676 for(;;) {
6677 this.q = new BigInteger(qs,1,rng);
6678 if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
6679 }
6680 if(this.p.compareTo(this.q) <= 0) {
6681 var t = this.p;
6682 this.p = this.q;
6683 this.q = t;
6684 }
6685 var p1 = this.p.subtract(BigInteger.ONE); // p1 = p - 1
6686 var q1 = this.q.subtract(BigInteger.ONE); // q1 = q - 1
6687 var phi = p1.multiply(q1);
6688 if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
6689 this.n = this.p.multiply(this.q); // this.n = p * q
6690 this.d = ee.modInverse(phi); // this.d =
6691 this.dmp1 = this.d.mod(p1); // this.dmp1 = d mod (p - 1)
6692 this.dmq1 = this.d.mod(q1); // this.dmq1 = d mod (q - 1)
6693 this.coeff = this.q.modInverse(this.p); // this.coeff = (q ^ -1) mod p
6694 break;
6695 }
6696 }
6697}
6698
6699/**
6700 * Perform raw private operation on "x": return x^d (mod n)
6701 * @return x^d (mod n)
6702 */
6703function RSADoPrivate(x) {
6704 if(this.p == null || this.q == null)
6705 return x.modPow(this.d, this.n);
6706
6707 // TODO: re-calculate any missing CRT params
6708 var xp = x.mod(this.p).modPow(this.dmp1, this.p); // xp=cp?
6709 var xq = x.mod(this.q).modPow(this.dmq1, this.q); // xq=cq?
6710
6711 while(xp.compareTo(xq) < 0)
6712 xp = xp.add(this.p);
6713 // NOTE:
6714 // xp.subtract(xq) => cp -cq
6715 // xp.subtract(xq).multiply(this.coeff).mod(this.p) => (cp - cq) * u mod p = h
6716 // xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq) => cq + (h * q) = M
6717 return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
6718}
6719
6720// Return the PKCS#1 RSA decryption of "ctext".
6721// "ctext" is an even-length hex string and the output is a plain string.
6722function RSADecrypt(ctext) {
6723 var c = parseBigInt(ctext, 16);
6724 var m = this.doPrivate(c);
6725 if(m == null) return null;
6726 return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
6727}
6728
6729// Return the PKCS#1 RSA decryption of "ctext".
6730// "ctext" is a Base64-encoded string and the output is a plain string.
6731//function RSAB64Decrypt(ctext) {
6732// var h = b64tohex(ctext);
6733// if(h) return this.decrypt(h); else return null;
6734//}
6735
6736// protected
6737RSAKey.prototype.doPrivate = RSADoPrivate;
6738
6739// public
6740RSAKey.prototype.setPrivate = RSASetPrivate;
6741RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
6742RSAKey.prototype.generate = RSAGenerate;
6743RSAKey.prototype.decrypt = RSADecrypt;
6744//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
6745
6746/*! rsapem-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
6747 */
6748//
6749// rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
6750// to RSAKey class.
6751//
6752// version: 1.1 (2012-May-10)
6753//
6754// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
6755//
6756// This software is licensed under the terms of the MIT License.
6757// http://kjur.github.com/jsrsasign/license/
6758//
6759// The above copyright and license notice shall be
6760// included in all copies or substantial portions of the Software.
6761//
6762//
6763// Depends on:
6764//
6765//
6766//
6767// _RSApem_pemToBase64(sPEM)
6768//
6769// removing PEM header, PEM footer and space characters including
6770// new lines from PEM formatted RSA private key string.
6771//
6772
6773function _rsapem_pemToBase64(sPEMPrivateKey) {
6774 var s = sPEMPrivateKey;
6775 s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
6776 s = s.replace("-----END RSA PRIVATE KEY-----", "");
6777 s = s.replace(/[ \n]+/g, "");
6778 return s;
6779}
6780
6781function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
6782 var a = new Array();
6783 var v1 = ASN1HEX.getStartPosOfV_AtObj(hPrivateKey, 0);
6784 var n1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, v1);
6785 var e1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, n1);
6786 var d1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, e1);
6787 var p1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, d1);
6788 var q1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, p1);
6789 var dp1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, q1);
6790 var dq1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dp1);
6791 var co1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dq1);
6792 a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
6793 return a;
6794}
6795
6796function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
6797 var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
6798 var v = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[0]);
6799 var n = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[1]);
6800 var e = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[2]);
6801 var d = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[3]);
6802 var p = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[4]);
6803 var q = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[5]);
6804 var dp = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[6]);
6805 var dq = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[7]);
6806 var co = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[8]);
6807 var a = new Array();
6808 a.push(v, n, e, d, p, q, dp, dq, co);
6809 return a;
6810}
6811
6812/**
6813 * read PKCS#1 private key from a string
6814 * @name readPrivateKeyFromPEMString
6815 * @memberOf RSAKey#
6816 * @function
6817 * @param {String} keyPEM string of PKCS#1 private key.
6818 */
6819function _rsapem_readPrivateKeyFromPEMString(keyPEM) {
6820 var keyB64 = _rsapem_pemToBase64(keyPEM);
6821 var keyHex = b64tohex(keyB64) // depends base64.js
6822 var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
6823 this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
6824}
6825
6826RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
6827
6828/*! rsasign-1.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
6829 */
6830//
6831// rsa-sign.js - adding signing functions to RSAKey class.
6832//
6833//
6834// version: 1.2.1 (08 May 2012)
6835//
6836// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
6837//
6838// This software is licensed under the terms of the MIT License.
6839// http://kjur.github.com/jsrsasign/license/
6840//
6841// The above copyright and license notice shall be
6842// included in all copies or substantial portions of the Software.
6843
6844//
6845// Depends on:
6846// function sha1.hex(s) of sha1.js
6847// jsbn.js
6848// jsbn2.js
6849// rsa.js
6850// rsa2.js
6851//
6852
6853// keysize / pmstrlen
6854// 512 / 128
6855// 1024 / 256
6856// 2048 / 512
6857// 4096 / 1024
6858
6859/**
6860 * @property {Dictionary} _RSASIGN_DIHEAD
6861 * @description Array of head part of hexadecimal DigestInfo value for hash algorithms.
6862 * You can add any DigestInfo hash algorith for signing.
6863 * See PKCS#1 v2.1 spec (p38).
6864 */
6865var _RSASIGN_DIHEAD = [];
6866_RSASIGN_DIHEAD['sha1'] = "3021300906052b0e03021a05000414";
6867_RSASIGN_DIHEAD['sha256'] = "3031300d060960864801650304020105000420";
6868_RSASIGN_DIHEAD['sha384'] = "3041300d060960864801650304020205000430";
6869_RSASIGN_DIHEAD['sha512'] = "3051300d060960864801650304020305000440";
6870_RSASIGN_DIHEAD['md2'] = "3020300c06082a864886f70d020205000410";
6871_RSASIGN_DIHEAD['md5'] = "3020300c06082a864886f70d020505000410";
6872_RSASIGN_DIHEAD['ripemd160'] = "3021300906052b2403020105000414";
6873
6874/**
6875 * @property {Dictionary} _RSASIGN_HASHHEXFUNC
6876 * @description Array of functions which calculate hash and returns it as hexadecimal.
6877 * You can add any hash algorithm implementations.
6878 */
6879var _RSASIGN_HASHHEXFUNC = [];
6880_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return hex_sha1(s);}; // http://pajhome.org.uk/crypt/md5/md5.html
6881_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return hex_sha256(s);} // http://pajhome.org.uk/crypt/md5/md5.html
6882_RSASIGN_HASHHEXFUNC['sha512'] = function(s){return hex_sha512(s);} // http://pajhome.org.uk/crypt/md5/md5.html
6883_RSASIGN_HASHHEXFUNC['md5'] = function(s){return hex_md5(s);}; // http://pajhome.org.uk/crypt/md5/md5.html
6884_RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return hex_rmd160(s);}; // http://pajhome.org.uk/crypt/md5/md5.html
6885
6886//@author axelcdv
6887var _RSASIGN_HASHBYTEFUNC = [];
6888_RSASIGN_HASHBYTEFUNC['sha256'] = function(byteArray){return hex_sha256_from_bytes(byteArray);};
6889
6890//_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return sha1.hex(s);} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
6891//_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
6892
6893var _RE_HEXDECONLY = new RegExp("");
6894_RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
6895
6896// ========================================================================
6897// Signature Generation
6898// ========================================================================
6899
6900function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
6901 var pmStrLen = keySize / 4;
6902 var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
6903 var sHashHex = hashFunc(s);
6904
6905 var sHead = "0001";
6906 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
6907 var sMid = "";
6908 var fLen = pmStrLen - sHead.length - sTail.length;
6909 for (var i = 0; i < fLen; i += 2) {
6910 sMid += "ff";
6911 }
6912 sPaddedMessageHex = sHead + sMid + sTail;
6913 return sPaddedMessageHex;
6914}
6915
6916
6917//@author: ucla-cs
6918function _rsasign_getHexPaddedDigestInfoForStringHEX(s, keySize, hashAlg) {
6919 var pmStrLen = keySize / 4;
6920 var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
6921 var sHashHex = hashFunc(s);
6922
6923 var sHead = "0001";
6924 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
6925 var sMid = "";
6926 var fLen = pmStrLen - sHead.length - sTail.length;
6927 for (var i = 0; i < fLen; i += 2) {
6928 sMid += "ff";
6929 }
6930 sPaddedMessageHex = sHead + sMid + sTail;
6931 return sPaddedMessageHex;
6932}
6933
6934/**
6935 * Apply padding, then computes the hash of the given byte array, according to the key size and with the hash algorithm
6936 * @param byteArray (byte[])
6937 * @param keySize (int)
6938 * @param hashAlg the hash algorithm to apply (string)
6939 * @return the hash of byteArray
6940 */
6941function _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, keySize, hashAlg){
6942 var pmStrLen = keySize / 4;
6943 var hashFunc = _RSASIGN_HASHBYTEFUNC[hashAlg];
6944 var sHashHex = hashFunc(byteArray); //returns hex hash
6945
6946 var sHead = "0001";
6947 var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
6948 var sMid = "";
6949 var fLen = pmStrLen - sHead.length - sTail.length;
6950 for (var i = 0; i < fLen; i += 2) {
6951 sMid += "ff";
6952 }
6953 sPaddedMessageHex = sHead + sMid + sTail;
6954 return sPaddedMessageHex;
6955}
6956
6957function _zeroPaddingOfSignature(hex, bitLength) {
6958 var s = "";
6959 var nZero = bitLength / 4 - hex.length;
6960 for (var i = 0; i < nZero; i++) {
6961 s = s + "0";
6962 }
6963 return s + hex;
6964}
6965
6966/**
6967 * sign for a message string with RSA private key.<br/>
6968 * @name signString
6969 * @memberOf RSAKey#
6970 * @function
6971 * @param {String} s message string to be signed.
6972 * @param {String} hashAlg hash algorithm name for signing.<br/>
6973 * @return returns hexadecimal string of signature value.
6974 */
6975function _rsasign_signString(s, hashAlg) {
6976 //alert("this.n.bitLength() = " + this.n.bitLength());
6977 var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
6978 var biPaddedMessage = parseBigInt(hPM, 16);
6979 var biSign = this.doPrivate(biPaddedMessage);
6980 var hexSign = biSign.toString(16);
6981 return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
6982}
6983
6984//@author: ucla-cs
6985function _rsasign_signStringHEX(s, hashAlg) {
6986 //alert("this.n.bitLength() = " + this.n.bitLength());
6987 var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
6988 var biPaddedMessage = parseBigInt(hPM, 16);
6989 var biSign = this.doPrivate(biPaddedMessage);
6990 var hexSign = biSign.toString(16);
6991 return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
6992}
6993
6994
6995/**
6996 * Sign a message byteArray with an RSA private key
6997 * @name signByteArray
6998 * @memberOf RSAKey#
6999 * @function
7000 * @param {byte[]} byteArray
7001 * @param {Sring} hashAlg the hash algorithm to apply
7002 * @param {RSAKey} rsa key to sign with: hack because the context is lost here
7003 * @return hexadecimal string of signature value
7004 */
7005function _rsasign_signByteArray(byteArray, hashAlg, rsaKey) {
7006 var hPM = _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, rsaKey.n.bitLength(), hashAlg); ///hack because the context is lost here
7007 var biPaddedMessage = parseBigInt(hPM, 16);
7008 var biSign = rsaKey.doPrivate(biPaddedMessage); //hack because the context is lost here
7009 var hexSign = biSign.toString(16);
7010 return _zeroPaddingOfSignature(hexSign, rsaKey.n.bitLength()); //hack because the context is lost here
7011}
7012
7013/**
7014 * Sign a byte array with the Sha-256 algorithm
7015 * @param {byte[]} byteArray
7016 * @return hexadecimal string of signature value
7017 */
7018function _rsasign_signByteArrayWithSHA256(byteArray){
7019 return _rsasign_signByteArray(byteArray, 'sha256', this); //Hack because the context is lost in the next function
7020}
7021
7022
7023function _rsasign_signStringWithSHA1(s) {
7024 return _rsasign_signString(s, 'sha1');
7025}
7026
7027function _rsasign_signStringWithSHA256(s) {
7028 return _rsasign_signString(s, 'sha256');
7029}
7030
7031// ========================================================================
7032// Signature Verification
7033// ========================================================================
7034
7035function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
7036 var rsa = new RSAKey();
7037 rsa.setPublic(hN, hE);
7038 var biDecryptedSig = rsa.doPublic(biSig);
7039 return biDecryptedSig;
7040}
7041
7042function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
7043 var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
7044 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
7045 return hDigestInfo;
7046}
7047
7048function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
7049 for (var algName in _RSASIGN_DIHEAD) {
7050 var head = _RSASIGN_DIHEAD[algName];
7051 var len = head.length;
7052 if (hDigestInfo.substring(0, len) == head) {
7053 var a = [algName, hDigestInfo.substring(len)];
7054 return a;
7055 }
7056 }
7057 return [];
7058}
7059
7060function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
7061 var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
7062 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
7063 if (digestInfoAry.length == 0) return false;
7064 var algName = digestInfoAry[0];
7065 var diHashValue = digestInfoAry[1];
7066 var ff = _RSASIGN_HASHHEXFUNC[algName];
7067 var msgHashValue = ff(sMsg);
7068 return (diHashValue == msgHashValue);
7069}
7070
7071function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
7072 var biSig = parseBigInt(hSig, 16);
7073 var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
7074 this.n.toString(16),
7075 this.e.toString(16));
7076 return result;
7077}
7078
7079/**
7080 * verifies a sigature for a message string with RSA public key.<br/>
7081 * @name verifyString
7082 * @memberOf RSAKey#
7083 * @function
7084 * @param {String} sMsg message string to be verified.
7085 * @param {String} hSig hexadecimal string of siganture.<br/>
7086 * non-hexadecimal charactors including new lines will be ignored.
7087 * @return returns 1 if valid, otherwise 0
7088 */
7089function _rsasign_verifyString(sMsg, hSig) {
7090 hSig = hSig.replace(_RE_HEXDECONLY, '');
7091
7092 if(LOG>3)console.log('n is '+this.n);
7093 if(LOG>3)console.log('e is '+this.e);
7094
7095 if (hSig.length != this.n.bitLength() / 4) return 0;
7096 hSig = hSig.replace(/[ \n]+/g, "");
7097 var biSig = parseBigInt(hSig, 16);
7098 var biDecryptedSig = this.doPublic(biSig);
7099 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
7100 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
7101
7102 if (digestInfoAry.length == 0) return false;
7103 var algName = digestInfoAry[0];
7104 var diHashValue = digestInfoAry[1];
7105 var ff = _RSASIGN_HASHHEXFUNC[algName];
7106 var msgHashValue = ff(sMsg);
7107 return (diHashValue == msgHashValue);
7108}
7109
7110/**
7111 * verifies a sigature for a message byte array with RSA public key.<br/>
7112 * @name verifyByteArray
7113 * @memberOf RSAKey#
7114 * @function
7115 * @param {byte[]} byteArray message byte array to be verified.
7116 * @param {String} hSig hexadecimal string of signature.<br/>
7117 * non-hexadecimal charactors including new lines will be ignored.
7118 * @return returns 1 if valid, otherwise 0
7119 */
7120function _rsasign_verifyByteArray(byteArray, hSig) {
7121 hSig = hSig.replace(_RE_HEXDECONLY, '');
7122
7123 if(LOG>3)console.log('n is '+this.n);
7124 if(LOG>3)console.log('e is '+this.e);
7125
7126 if (hSig.length != this.n.bitLength() / 4) return 0;
7127 hSig = hSig.replace(/[ \n]+/g, "");
7128 var biSig = parseBigInt(hSig, 16);
7129 var biDecryptedSig = this.doPublic(biSig);
7130 var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
7131 var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
7132
7133 if (digestInfoAry.length == 0) return false;
7134 var algName = digestInfoAry[0];
7135 var diHashValue = digestInfoAry[1];
7136 var ff = _RSASIGN_HASHBYTEFUNC[algName];
7137 var msgHashValue = ff(byteArray);
7138 return (diHashValue == msgHashValue);
7139}
7140
7141RSAKey.prototype.signString = _rsasign_signString;
7142
7143RSAKey.prototype.signByteArray = _rsasign_signByteArray; //@author axelcdv
7144RSAKey.prototype.signByteArrayWithSHA256 = _rsasign_signByteArrayWithSHA256; //@author axelcdv
7145
7146RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
7147RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
7148RSAKey.prototype.sign = _rsasign_signString;
7149RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
7150RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
7151
7152
7153/*RSAKey.prototype.signStringHEX = _rsasign_signStringHEX;
7154RSAKey.prototype.signStringWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
7155RSAKey.prototype.signStringWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
7156RSAKey.prototype.signHEX = _rsasign_signStringHEX;
7157RSAKey.prototype.signWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
7158RSAKey.prototype.signWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
7159*/
7160
7161RSAKey.prototype.verifyByteArray = _rsasign_verifyByteArray;
7162RSAKey.prototype.verifyString = _rsasign_verifyString;
7163RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
7164RSAKey.prototype.verify = _rsasign_verifyString;
7165RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
7166
7167/*
7168RSAKey.prototype.verifyStringHEX = _rsasign_verifyStringHEX;
7169RSAKey.prototype.verifyHexSignatureForMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
7170RSAKey.prototype.verifyHEX = _rsasign_verifyStringHEX;
7171RSAKey.prototype.verifyHexSignatureForByteArrayMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
7172*/
7173
7174
7175/**
7176 * @name RSAKey
7177 * @class
7178 * @description Tom Wu's RSA Key class and extension
7179 */
7180
7181/*! asn1hex-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
7182 */
7183//
7184// asn1hex.js - Hexadecimal represented ASN.1 string library
7185//
7186// version: 1.1 (09-May-2012)
7187//
7188// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
7189//
7190// This software is licensed under the terms of the MIT License.
7191// http://kjur.github.com/jsrsasign/license/
7192//
7193// The above copyright and license notice shall be
7194// included in all copies or substantial portions of the Software.
7195//
7196// Depends on:
7197//
7198
7199// MEMO:
7200// f('3082025b02...', 2) ... 82025b ... 3bytes
7201// f('020100', 2) ... 01 ... 1byte
7202// f('0203001...', 2) ... 03 ... 1byte
7203// f('02818003...', 2) ... 8180 ... 2bytes
7204// f('3080....0000', 2) ... 80 ... -1
7205//
7206// Requirements:
7207// - ASN.1 type octet length MUST be 1.
7208// (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
7209// -
7210/**
7211 * get byte length for ASN.1 L(length) bytes
7212 * @name getByteLengthOfL_AtObj
7213 * @memberOf ASN1HEX
7214 * @function
7215 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7216 * @param {Number} pos string index
7217 * @return byte length for ASN.1 L(length) bytes
7218 */
7219function _asnhex_getByteLengthOfL_AtObj(s, pos) {
7220 if (s.substring(pos + 2, pos + 3) != '8') return 1;
7221 var i = parseInt(s.substring(pos + 3, pos + 4));
7222 if (i == 0) return -1; // length octet '80' indefinite length
7223 if (0 < i && i < 10) return i + 1; // including '8?' octet;
7224 return -2; // malformed format
7225}
7226
7227
7228/**
7229 * get hexadecimal string for ASN.1 L(length) bytes
7230 * @name getHexOfL_AtObj
7231 * @memberOf ASN1HEX
7232 * @function
7233 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7234 * @param {Number} pos string index
7235 * @return {String} hexadecimal string for ASN.1 L(length) bytes
7236 */
7237function _asnhex_getHexOfL_AtObj(s, pos) {
7238 var len = _asnhex_getByteLengthOfL_AtObj(s, pos);
7239 if (len < 1) return '';
7240 return s.substring(pos + 2, pos + 2 + len * 2);
7241}
7242
7243//
7244// getting ASN.1 length value at the position 'idx' of
7245// hexa decimal string 's'.
7246//
7247// f('3082025b02...', 0) ... 82025b ... ???
7248// f('020100', 0) ... 01 ... 1
7249// f('0203001...', 0) ... 03 ... 3
7250// f('02818003...', 0) ... 8180 ... 128
7251/**
7252 * get integer value of ASN.1 length for ASN.1 data
7253 * @name getIntOfL_AtObj
7254 * @memberOf ASN1HEX
7255 * @function
7256 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7257 * @param {Number} pos string index
7258 * @return ASN.1 L(length) integer value
7259 */
7260function _asnhex_getIntOfL_AtObj(s, pos) {
7261 var hLength = _asnhex_getHexOfL_AtObj(s, pos);
7262 if (hLength == '') return -1;
7263 var bi;
7264 if (parseInt(hLength.substring(0, 1)) < 8) {
7265 bi = parseBigInt(hLength, 16);
7266 } else {
7267 bi = parseBigInt(hLength.substring(2), 16);
7268 }
7269 return bi.intValue();
7270}
7271
7272/**
7273 * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
7274 * @name getStartPosOfV_AtObj
7275 * @memberOf ASN1HEX
7276 * @function
7277 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7278 * @param {Number} pos string index
7279 */
7280function _asnhex_getStartPosOfV_AtObj(s, pos) {
7281 var l_len = _asnhex_getByteLengthOfL_AtObj(s, pos);
7282 if (l_len < 0) return l_len;
7283 return pos + (l_len + 1) * 2;
7284}
7285
7286/**
7287 * get hexadecimal string of ASN.1 V(value)
7288 * @name getHexOfV_AtObj
7289 * @memberOf ASN1HEX
7290 * @function
7291 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7292 * @param {Number} pos string index
7293 * @return {String} hexadecimal string of ASN.1 value.
7294 */
7295function _asnhex_getHexOfV_AtObj(s, pos) {
7296 var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
7297 var len = _asnhex_getIntOfL_AtObj(s, pos);
7298 return s.substring(pos1, pos1 + len * 2);
7299}
7300
7301/**
7302 * get hexadecimal string of ASN.1 TLV at
7303 * @name getHexOfTLV_AtObj
7304 * @memberOf ASN1HEX
7305 * @function
7306 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7307 * @param {Number} pos string index
7308 * @return {String} hexadecimal string of ASN.1 TLV.
7309 * @since 1.1
7310 */
7311function _asnhex_getHexOfTLV_AtObj(s, pos) {
7312 var hT = s.substr(pos, 2);
7313 var hL = _asnhex_getHexOfL_AtObj(s, pos);
7314 var hV = _asnhex_getHexOfV_AtObj(s, pos);
7315 return hT + hL + hV;
7316}
7317
7318/**
7319 * get next sibling starting index for ASN.1 object string
7320 * @name getPosOfNextSibling_AtObj
7321 * @memberOf ASN1HEX
7322 * @function
7323 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7324 * @param {Number} pos string index
7325 * @return next sibling starting index for ASN.1 object string
7326 */
7327function _asnhex_getPosOfNextSibling_AtObj(s, pos) {
7328 var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
7329 var len = _asnhex_getIntOfL_AtObj(s, pos);
7330 return pos1 + len * 2;
7331}
7332
7333/**
7334 * get array of indexes of child ASN.1 objects
7335 * @name getPosArrayOfChildren_AtObj
7336 * @memberOf ASN1HEX
7337 * @function
7338 * @param {String} s hexadecimal string of ASN.1 DER encoded data
7339 * @param {Number} start string index of ASN.1 object
7340 * @return {Array of Number} array of indexes for childen of ASN.1 objects
7341 */
7342function _asnhex_getPosArrayOfChildren_AtObj(h, pos) {
7343 var a = new Array();
7344 var p0 = _asnhex_getStartPosOfV_AtObj(h, pos);
7345 a.push(p0);
7346
7347 var len = _asnhex_getIntOfL_AtObj(h, pos);
7348 var p = p0;
7349 var k = 0;
7350 while (1) {
7351 var pNext = _asnhex_getPosOfNextSibling_AtObj(h, p);
7352 if (pNext == null || (pNext - p0 >= (len * 2))) break;
7353 if (k >= 200) break;
7354
7355 a.push(pNext);
7356 p = pNext;
7357
7358 k++;
7359 }
7360
7361 return a;
7362}
7363
7364/**
7365 * get string index of nth child object of ASN.1 object refered by h, idx
7366 * @name getNthChildIndex_AtObj
7367 * @memberOf ASN1HEX
7368 * @function
7369 * @param {String} h hexadecimal string of ASN.1 DER encoded data
7370 * @param {Number} idx start string index of ASN.1 object
7371 * @param {Number} nth for child
7372 * @return {Number} string index of nth child.
7373 * @since 1.1
7374 */
7375function _asnhex_getNthChildIndex_AtObj(h, idx, nth) {
7376 var a = _asnhex_getPosArrayOfChildren_AtObj(h, idx);
7377 return a[nth];
7378}
7379
7380// ========== decendant methods ==============================
7381
7382/**
7383 * get string index of nth child object of ASN.1 object refered by h, idx
7384 * @name getDecendantIndexByNthList
7385 * @memberOf ASN1HEX
7386 * @function
7387 * @param {String} h hexadecimal string of ASN.1 DER encoded data
7388 * @param {Number} currentIndex start string index of ASN.1 object
7389 * @param {Array of Number} nthList array list of nth
7390 * @return {Number} string index refered by nthList
7391 * @since 1.1
7392 */
7393function _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList) {
7394 if (nthList.length == 0) {
7395 return currentIndex;
7396 }
7397 var firstNth = nthList.shift();
7398 var a = _asnhex_getPosArrayOfChildren_AtObj(h, currentIndex);
7399 return _asnhex_getDecendantIndexByNthList(h, a[firstNth], nthList);
7400}
7401
7402/**
7403 * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
7404 * @name getDecendantHexTLVByNthList
7405 * @memberOf ASN1HEX
7406 * @function
7407 * @param {String} h hexadecimal string of ASN.1 DER encoded data
7408 * @param {Number} currentIndex start string index of ASN.1 object
7409 * @param {Array of Number} nthList array list of nth
7410 * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
7411 * @since 1.1
7412 */
7413function _asnhex_getDecendantHexTLVByNthList(h, currentIndex, nthList) {
7414 var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
7415 return _asnhex_getHexOfTLV_AtObj(h, idx);
7416}
7417
7418/**
7419 * get hexadecimal string of ASN.1 V refered by current index and nth index list.
7420 * @name getDecendantHexVByNthList
7421 * @memberOf ASN1HEX
7422 * @function
7423 * @param {String} h hexadecimal string of ASN.1 DER encoded data
7424 * @param {Number} currentIndex start string index of ASN.1 object
7425 * @param {Array of Number} nthList array list of nth
7426 * @return {Number} hexadecimal string of ASN.1 V refered by nthList
7427 * @since 1.1
7428 */
7429function _asnhex_getDecendantHexVByNthList(h, currentIndex, nthList) {
7430 var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
7431 return _asnhex_getHexOfV_AtObj(h, idx);
7432}
7433
7434// ========== class definition ==============================
7435
7436/**
7437 * ASN.1 DER encoded hexadecimal string utility class
7438 * @class ASN.1 DER encoded hexadecimal string utility class
7439 * @author Kenji Urushima
7440 * @version 1.1 (09 May 2012)
7441 * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
7442 * @since 1.1
7443 */
7444function ASN1HEX() {
7445 return ASN1HEX;
7446}
7447
7448ASN1HEX.getByteLengthOfL_AtObj = _asnhex_getByteLengthOfL_AtObj;
7449ASN1HEX.getHexOfL_AtObj = _asnhex_getHexOfL_AtObj;
7450ASN1HEX.getIntOfL_AtObj = _asnhex_getIntOfL_AtObj;
7451ASN1HEX.getStartPosOfV_AtObj = _asnhex_getStartPosOfV_AtObj;
7452ASN1HEX.getHexOfV_AtObj = _asnhex_getHexOfV_AtObj;
7453ASN1HEX.getHexOfTLV_AtObj = _asnhex_getHexOfTLV_AtObj;
7454ASN1HEX.getPosOfNextSibling_AtObj = _asnhex_getPosOfNextSibling_AtObj;
7455ASN1HEX.getPosArrayOfChildren_AtObj = _asnhex_getPosArrayOfChildren_AtObj;
7456ASN1HEX.getNthChildIndex_AtObj = _asnhex_getNthChildIndex_AtObj;
7457ASN1HEX.getDecendantIndexByNthList = _asnhex_getDecendantIndexByNthList;
7458ASN1HEX.getDecendantHexVByNthList = _asnhex_getDecendantHexVByNthList;
7459ASN1HEX.getDecendantHexTLVByNthList = _asnhex_getDecendantHexTLVByNthList;
7460
7461/*! x509-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
7462 */
7463//
7464// x509.js - X509 class to read subject public key from certificate.
7465//
7466// version: 1.1 (10-May-2012)
7467//
7468// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
7469//
7470// This software is licensed under the terms of the MIT License.
7471// http://kjur.github.com/jsrsasign/license
7472//
7473// The above copyright and license notice shall be
7474// included in all copies or substantial portions of the Software.
7475//
7476
7477// Depends:
7478// base64.js
7479// rsa.js
7480// asn1hex.js
7481
7482function _x509_pemToBase64(sCertPEM) {
7483 var s = sCertPEM;
7484 s = s.replace("-----BEGIN CERTIFICATE-----", "");
7485 s = s.replace("-----END CERTIFICATE-----", "");
7486 s = s.replace(/[ \n]+/g, "");
7487 return s;
7488}
7489
7490function _x509_pemToHex(sCertPEM) {
7491 var b64Cert = _x509_pemToBase64(sCertPEM);
7492 var hCert = b64tohex(b64Cert);
7493 return hCert;
7494}
7495
7496function _x509_getHexTbsCertificateFromCert(hCert) {
7497 var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
7498 return pTbsCert;
7499}
7500
7501// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
7502// NOTE: v1 and v3 supported
7503function _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert) {
7504 var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
7505 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert);
7506 if (a.length < 1) return -1;
7507 if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
7508 if (a.length < 6) return -1;
7509 return a[6];
7510 } else {
7511 if (a.length < 5) return -1;
7512 return a[5];
7513 }
7514}
7515
7516// NOTE: Without BITSTRING encapsulation.
7517function _x509_getSubjectPublicKeyPosFromCertHex(hCert) {
7518 var pInfo = _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert);
7519 if (pInfo == -1) return -1;
7520 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo);
7521
7522 if (a.length != 2) return -1;
7523 var pBitString = a[1];
7524 if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
7525 var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
7526
7527 if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
7528 return pBitStringV + 2;
7529}
7530
7531function _x509_getPublicKeyHexArrayFromCertHex(hCert) {
7532 var p = _x509_getSubjectPublicKeyPosFromCertHex(hCert);
7533 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
7534 //var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a[3]);
7535 if(LOG>4){
7536 console.log('a is now');
7537 console.log(a);
7538 }
7539
7540 //if (a.length != 2) return [];
7541 if (a.length < 2) return [];
7542
7543 var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
7544 var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
7545 if (hN != null && hE != null) {
7546 return [hN, hE];
7547 } else {
7548 return [];
7549 }
7550}
7551
7552function _x509_getPublicKeyHexArrayFromCertPEM(sCertPEM) {
7553 var hCert = _x509_pemToHex(sCertPEM);
7554 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
7555 return a;
7556}
7557
7558// ===== get basic fields from hex =====================================
7559/**
7560 * get hexadecimal string of serialNumber field of certificate.<br/>
7561 * @name getSerialNumberHex
7562 * @memberOf X509#
7563 * @function
7564 */
7565function _x509_getSerialNumberHex() {
7566 return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
7567}
7568
7569/**
7570 * get hexadecimal string of issuer field of certificate.<br/>
7571 * @name getIssuerHex
7572 * @memberOf X509#
7573 * @function
7574 */
7575function _x509_getIssuerHex() {
7576 return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
7577}
7578
7579/**
7580 * get string of issuer field of certificate.<br/>
7581 * @name getIssuerString
7582 * @memberOf X509#
7583 * @function
7584 */
7585function _x509_getIssuerString() {
7586 return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
7587}
7588
7589/**
7590 * get hexadecimal string of subject field of certificate.<br/>
7591 * @name getSubjectHex
7592 * @memberOf X509#
7593 * @function
7594 */
7595function _x509_getSubjectHex() {
7596 return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
7597}
7598
7599/**
7600 * get string of subject field of certificate.<br/>
7601 * @name getSubjectString
7602 * @memberOf X509#
7603 * @function
7604 */
7605function _x509_getSubjectString() {
7606 return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
7607}
7608
7609/**
7610 * get notBefore field string of certificate.<br/>
7611 * @name getNotBefore
7612 * @memberOf X509#
7613 * @function
7614 */
7615function _x509_getNotBefore() {
7616 var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
7617 s = s.replace(/(..)/g, "%$1");
7618 s = decodeURIComponent(s);
7619 return s;
7620}
7621
7622/**
7623 * get notAfter field string of certificate.<br/>
7624 * @name getNotAfter
7625 * @memberOf X509#
7626 * @function
7627 */
7628function _x509_getNotAfter() {
7629 var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
7630 s = s.replace(/(..)/g, "%$1");
7631 s = decodeURIComponent(s);
7632 return s;
7633}
7634
7635// ===== read certificate =====================================
7636
7637_x509_DN_ATTRHEX = {
7638 "0603550406": "C",
7639 "060355040a": "O",
7640 "060355040b": "OU",
7641 "0603550403": "CN",
7642 "0603550405": "SN",
7643 "0603550408": "ST",
7644 "0603550407": "L" };
7645
7646function _x509_hex2dn(hDN) {
7647 var s = "";
7648 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
7649 for (var i = 0; i < a.length; i++) {
7650 var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
7651 s = s + "/" + _x509_hex2rdn(hRDN);
7652 }
7653 return s;
7654}
7655
7656function _x509_hex2rdn(hRDN) {
7657 var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
7658 var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
7659 var type = "";
7660 try { type = _x509_DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
7661 hValue = hValue.replace(/(..)/g, "%$1");
7662 var value = decodeURIComponent(hValue);
7663 return type + "=" + value;
7664}
7665
7666// ===== read certificate =====================================
7667
7668
7669/**
7670 * read PEM formatted X.509 certificate from string.<br/>
7671 * @name readCertPEM
7672 * @memberOf X509#
7673 * @function
7674 * @param {String} sCertPEM string for PEM formatted X.509 certificate
7675 */
7676function _x509_readCertPEM(sCertPEM) {
7677 var hCert = _x509_pemToHex(sCertPEM);
7678 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
7679 if(LOG>4){
7680 console.log('HEX VALUE IS ' + hCert);
7681 console.log('type of a' + typeof a);
7682 console.log('a VALUE IS ');
7683 console.log(a);
7684 console.log('a[0] VALUE IS ' + a[0]);
7685 console.log('a[1] VALUE IS ' + a[1]);
7686 }
7687 var rsa = new RSAKey();
7688 rsa.setPublic(a[0], a[1]);
7689 this.subjectPublicKeyRSA = rsa;
7690 this.subjectPublicKeyRSA_hN = a[0];
7691 this.subjectPublicKeyRSA_hE = a[1];
7692 this.hex = hCert;
7693}
7694
7695function _x509_readCertPEMWithoutRSAInit(sCertPEM) {
7696 var hCert = _x509_pemToHex(sCertPEM);
7697 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
7698 this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
7699 this.subjectPublicKeyRSA_hN = a[0];
7700 this.subjectPublicKeyRSA_hE = a[1];
7701 this.hex = hCert;
7702}
7703
7704/**
7705 * X.509 certificate class.<br/>
7706 * @class X.509 certificate class
7707 * @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object
7708 * @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key
7709 * @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key
7710 * @property {String} hex hexacedimal string for X.509 certificate.
7711 * @author Kenji Urushima
7712 * @version 1.0.1 (08 May 2012)
7713 * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
7714 */
7715function X509() {
7716 this.subjectPublicKeyRSA = null;
7717 this.subjectPublicKeyRSA_hN = null;
7718 this.subjectPublicKeyRSA_hE = null;
7719 this.hex = null;
7720}
7721
7722X509.prototype.readCertPEM = _x509_readCertPEM;
7723X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
7724X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
7725X509.prototype.getIssuerHex = _x509_getIssuerHex;
7726X509.prototype.getSubjectHex = _x509_getSubjectHex;
7727X509.prototype.getIssuerString = _x509_getIssuerString;
7728X509.prototype.getSubjectString = _x509_getSubjectString;
7729X509.prototype.getNotBefore = _x509_getNotBefore;
7730X509.prototype.getNotAfter = _x509_getNotAfter;
7731
7732
7733// Copyright (c) 2005 Tom Wu
7734// All Rights Reserved.
7735// See "LICENSE" for details.
7736
7737// Basic JavaScript BN library - subset useful for RSA encryption.
7738
7739// Bits per digit
7740var dbits;
7741
7742// JavaScript engine analysis
7743var canary = 0xdeadbeefcafe;
7744var j_lm = ((canary&0xffffff)==0xefcafe);
7745
7746// (public) Constructor
7747function BigInteger(a,b,c) {
7748 if(a != null)
7749 if("number" == typeof a) this.fromNumber(a,b,c);
7750 else if(b == null && "string" != typeof a) this.fromString(a,256);
7751 else this.fromString(a,b);
7752}
7753
7754// return new, unset BigInteger
7755function nbi() { return new BigInteger(null); }
7756
7757// am: Compute w_j += (x*this_i), propagate carries,
7758// c is initial carry, returns final carry.
7759// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
7760// We need to select the fastest one that works in this environment.
7761
7762// am1: use a single mult and divide to get the high bits,
7763// max digit bits should be 26 because
7764// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
7765function am1(i,x,w,j,c,n) {
7766 while(--n >= 0) {
7767 var v = x*this[i++]+w[j]+c;
7768 c = Math.floor(v/0x4000000);
7769 w[j++] = v&0x3ffffff;
7770 }
7771 return c;
7772}
7773// am2 avoids a big mult-and-extract completely.
7774// Max digit bits should be <= 30 because we do bitwise ops
7775// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
7776function am2(i,x,w,j,c,n) {
7777 var xl = x&0x7fff, xh = x>>15;
7778 while(--n >= 0) {
7779 var l = this[i]&0x7fff;
7780 var h = this[i++]>>15;
7781 var m = xh*l+h*xl;
7782 l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
7783 c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
7784 w[j++] = l&0x3fffffff;
7785 }
7786 return c;
7787}
7788// Alternately, set max digit bits to 28 since some
7789// browsers slow down when dealing with 32-bit numbers.
7790function am3(i,x,w,j,c,n) {
7791 var xl = x&0x3fff, xh = x>>14;
7792 while(--n >= 0) {
7793 var l = this[i]&0x3fff;
7794 var h = this[i++]>>14;
7795 var m = xh*l+h*xl;
7796 l = xl*l+((m&0x3fff)<<14)+w[j]+c;
7797 c = (l>>28)+(m>>14)+xh*h;
7798 w[j++] = l&0xfffffff;
7799 }
7800 return c;
7801}
7802if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
7803 BigInteger.prototype.am = am2;
7804 dbits = 30;
7805}
7806else if(j_lm && (navigator.appName != "Netscape")) {
7807 BigInteger.prototype.am = am1;
7808 dbits = 26;
7809}
7810else { // Mozilla/Netscape seems to prefer am3
7811 BigInteger.prototype.am = am3;
7812 dbits = 28;
7813}
7814
7815BigInteger.prototype.DB = dbits;
7816BigInteger.prototype.DM = ((1<<dbits)-1);
7817BigInteger.prototype.DV = (1<<dbits);
7818
7819var BI_FP = 52;
7820BigInteger.prototype.FV = Math.pow(2,BI_FP);
7821BigInteger.prototype.F1 = BI_FP-dbits;
7822BigInteger.prototype.F2 = 2*dbits-BI_FP;
7823
7824// Digit conversions
7825var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
7826var BI_RC = new Array();
7827var rr,vv;
7828rr = "0".charCodeAt(0);
7829for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
7830rr = "a".charCodeAt(0);
7831for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
7832rr = "A".charCodeAt(0);
7833for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
7834
7835function int2char(n) { return BI_RM.charAt(n); }
7836function intAt(s,i) {
7837 var c = BI_RC[s.charCodeAt(i)];
7838 return (c==null)?-1:c;
7839}
7840
7841// (protected) copy this to r
7842function bnpCopyTo(r) {
7843 for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
7844 r.t = this.t;
7845 r.s = this.s;
7846}
7847
7848// (protected) set from integer value x, -DV <= x < DV
7849function bnpFromInt(x) {
7850 this.t = 1;
7851 this.s = (x<0)?-1:0;
7852 if(x > 0) this[0] = x;
7853 else if(x < -1) this[0] = x+DV;
7854 else this.t = 0;
7855}
7856
7857// return bigint initialized to value
7858function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
7859
7860// (protected) set from string and radix
7861function bnpFromString(s,b) {
7862 var k;
7863 if(b == 16) k = 4;
7864 else if(b == 8) k = 3;
7865 else if(b == 256) k = 8; // byte array
7866 else if(b == 2) k = 1;
7867 else if(b == 32) k = 5;
7868 else if(b == 4) k = 2;
7869 else { this.fromRadix(s,b); return; }
7870 this.t = 0;
7871 this.s = 0;
7872 var i = s.length, mi = false, sh = 0;
7873 while(--i >= 0) {
7874 var x = (k==8)?s[i]&0xff:intAt(s,i);
7875 if(x < 0) {
7876 if(s.charAt(i) == "-") mi = true;
7877 continue;
7878 }
7879 mi = false;
7880 if(sh == 0)
7881 this[this.t++] = x;
7882 else if(sh+k > this.DB) {
7883 this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
7884 this[this.t++] = (x>>(this.DB-sh));
7885 }
7886 else
7887 this[this.t-1] |= x<<sh;
7888 sh += k;
7889 if(sh >= this.DB) sh -= this.DB;
7890 }
7891 if(k == 8 && (s[0]&0x80) != 0) {
7892 this.s = -1;
7893 if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
7894 }
7895 this.clamp();
7896 if(mi) BigInteger.ZERO.subTo(this,this);
7897}
7898
7899// (protected) clamp off excess high words
7900function bnpClamp() {
7901 var c = this.s&this.DM;
7902 while(this.t > 0 && this[this.t-1] == c) --this.t;
7903}
7904
7905// (public) return string representation in given radix
7906function bnToString(b) {
7907 if(this.s < 0) return "-"+this.negate().toString(b);
7908 var k;
7909 if(b == 16) k = 4;
7910 else if(b == 8) k = 3;
7911 else if(b == 2) k = 1;
7912 else if(b == 32) k = 5;
7913 else if(b == 4) k = 2;
7914 else return this.toRadix(b);
7915 var km = (1<<k)-1, d, m = false, r = "", i = this.t;
7916 var p = this.DB-(i*this.DB)%k;
7917 if(i-- > 0) {
7918 if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
7919 while(i >= 0) {
7920 if(p < k) {
7921 d = (this[i]&((1<<p)-1))<<(k-p);
7922 d |= this[--i]>>(p+=this.DB-k);
7923 }
7924 else {
7925 d = (this[i]>>(p-=k))&km;
7926 if(p <= 0) { p += this.DB; --i; }
7927 }
7928 if(d > 0) m = true;
7929 if(m) r += int2char(d);
7930 }
7931 }
7932 return m?r:"0";
7933}
7934
7935// (public) -this
7936function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
7937
7938// (public) |this|
7939function bnAbs() { return (this.s<0)?this.negate():this; }
7940
7941// (public) return + if this > a, - if this < a, 0 if equal
7942function bnCompareTo(a) {
7943 var r = this.s-a.s;
7944 if(r != 0) return r;
7945 var i = this.t;
7946 r = i-a.t;
7947 if(r != 0) return r;
7948 while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
7949 return 0;
7950}
7951
7952// returns bit length of the integer x
7953function nbits(x) {
7954 var r = 1, t;
7955 if((t=x>>>16) != 0) { x = t; r += 16; }
7956 if((t=x>>8) != 0) { x = t; r += 8; }
7957 if((t=x>>4) != 0) { x = t; r += 4; }
7958 if((t=x>>2) != 0) { x = t; r += 2; }
7959 if((t=x>>1) != 0) { x = t; r += 1; }
7960 return r;
7961}
7962
7963// (public) return the number of bits in "this"
7964function bnBitLength() {
7965 if(this.t <= 0) return 0;
7966 return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
7967}
7968
7969// (protected) r = this << n*DB
7970function bnpDLShiftTo(n,r) {
7971 var i;
7972 for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
7973 for(i = n-1; i >= 0; --i) r[i] = 0;
7974 r.t = this.t+n;
7975 r.s = this.s;
7976}
7977
7978// (protected) r = this >> n*DB
7979function bnpDRShiftTo(n,r) {
7980 for(var i = n; i < this.t; ++i) r[i-n] = this[i];
7981 r.t = Math.max(this.t-n,0);
7982 r.s = this.s;
7983}
7984
7985// (protected) r = this << n
7986function bnpLShiftTo(n,r) {
7987 var bs = n%this.DB;
7988 var cbs = this.DB-bs;
7989 var bm = (1<<cbs)-1;
7990 var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
7991 for(i = this.t-1; i >= 0; --i) {
7992 r[i+ds+1] = (this[i]>>cbs)|c;
7993 c = (this[i]&bm)<<bs;
7994 }
7995 for(i = ds-1; i >= 0; --i) r[i] = 0;
7996 r[ds] = c;
7997 r.t = this.t+ds+1;
7998 r.s = this.s;
7999 r.clamp();
8000}
8001
8002// (protected) r = this >> n
8003function bnpRShiftTo(n,r) {
8004 r.s = this.s;
8005 var ds = Math.floor(n/this.DB);
8006 if(ds >= this.t) { r.t = 0; return; }
8007 var bs = n%this.DB;
8008 var cbs = this.DB-bs;
8009 var bm = (1<<bs)-1;
8010 r[0] = this[ds]>>bs;
8011 for(var i = ds+1; i < this.t; ++i) {
8012 r[i-ds-1] |= (this[i]&bm)<<cbs;
8013 r[i-ds] = this[i]>>bs;
8014 }
8015 if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
8016 r.t = this.t-ds;
8017 r.clamp();
8018}
8019
8020// (protected) r = this - a
8021function bnpSubTo(a,r) {
8022 var i = 0, c = 0, m = Math.min(a.t,this.t);
8023 while(i < m) {
8024 c += this[i]-a[i];
8025 r[i++] = c&this.DM;
8026 c >>= this.DB;
8027 }
8028 if(a.t < this.t) {
8029 c -= a.s;
8030 while(i < this.t) {
8031 c += this[i];
8032 r[i++] = c&this.DM;
8033 c >>= this.DB;
8034 }
8035 c += this.s;
8036 }
8037 else {
8038 c += this.s;
8039 while(i < a.t) {
8040 c -= a[i];
8041 r[i++] = c&this.DM;
8042 c >>= this.DB;
8043 }
8044 c -= a.s;
8045 }
8046 r.s = (c<0)?-1:0;
8047 if(c < -1) r[i++] = this.DV+c;
8048 else if(c > 0) r[i++] = c;
8049 r.t = i;
8050 r.clamp();
8051}
8052
8053// (protected) r = this * a, r != this,a (HAC 14.12)
8054// "this" should be the larger one if appropriate.
8055function bnpMultiplyTo(a,r) {
8056 var x = this.abs(), y = a.abs();
8057 var i = x.t;
8058 r.t = i+y.t;
8059 while(--i >= 0) r[i] = 0;
8060 for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
8061 r.s = 0;
8062 r.clamp();
8063 if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
8064}
8065
8066// (protected) r = this^2, r != this (HAC 14.16)
8067function bnpSquareTo(r) {
8068 var x = this.abs();
8069 var i = r.t = 2*x.t;
8070 while(--i >= 0) r[i] = 0;
8071 for(i = 0; i < x.t-1; ++i) {
8072 var c = x.am(i,x[i],r,2*i,0,1);
8073 if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
8074 r[i+x.t] -= x.DV;
8075 r[i+x.t+1] = 1;
8076 }
8077 }
8078 if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
8079 r.s = 0;
8080 r.clamp();
8081}
8082
8083// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
8084// r != q, this != m. q or r may be null.
8085function bnpDivRemTo(m,q,r) {
8086 var pm = m.abs();
8087 if(pm.t <= 0) return;
8088 var pt = this.abs();
8089 if(pt.t < pm.t) {
8090 if(q != null) q.fromInt(0);
8091 if(r != null) this.copyTo(r);
8092 return;
8093 }
8094 if(r == null) r = nbi();
8095 var y = nbi(), ts = this.s, ms = m.s;
8096 var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
8097 if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
8098 else { pm.copyTo(y); pt.copyTo(r); }
8099 var ys = y.t;
8100 var y0 = y[ys-1];
8101 if(y0 == 0) return;
8102 var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
8103 var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
8104 var i = r.t, j = i-ys, t = (q==null)?nbi():q;
8105 y.dlShiftTo(j,t);
8106 if(r.compareTo(t) >= 0) {
8107 r[r.t++] = 1;
8108 r.subTo(t,r);
8109 }
8110 BigInteger.ONE.dlShiftTo(ys,t);
8111 t.subTo(y,y); // "negative" y so we can replace sub with am later
8112 while(y.t < ys) y[y.t++] = 0;
8113 while(--j >= 0) {
8114 // Estimate quotient digit
8115 var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
8116 if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
8117 y.dlShiftTo(j,t);
8118 r.subTo(t,r);
8119 while(r[i] < --qd) r.subTo(t,r);
8120 }
8121 }
8122 if(q != null) {
8123 r.drShiftTo(ys,q);
8124 if(ts != ms) BigInteger.ZERO.subTo(q,q);
8125 }
8126 r.t = ys;
8127 r.clamp();
8128 if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
8129 if(ts < 0) BigInteger.ZERO.subTo(r,r);
8130}
8131
8132// (public) this mod a
8133function bnMod(a) {
8134 var r = nbi();
8135 this.abs().divRemTo(a,null,r);
8136 if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
8137 return r;
8138}
8139
8140// Modular reduction using "classic" algorithm
8141function Classic(m) { this.m = m; }
8142function cConvert(x) {
8143 if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
8144 else return x;
8145}
8146function cRevert(x) { return x; }
8147function cReduce(x) { x.divRemTo(this.m,null,x); }
8148function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
8149function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
8150
8151Classic.prototype.convert = cConvert;
8152Classic.prototype.revert = cRevert;
8153Classic.prototype.reduce = cReduce;
8154Classic.prototype.mulTo = cMulTo;
8155Classic.prototype.sqrTo = cSqrTo;
8156
8157// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
8158// justification:
8159// xy == 1 (mod m)
8160// xy = 1+km
8161// xy(2-xy) = (1+km)(1-km)
8162// x[y(2-xy)] = 1-k^2m^2
8163// x[y(2-xy)] == 1 (mod m^2)
8164// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
8165// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
8166// JS multiply "overflows" differently from C/C++, so care is needed here.
8167function bnpInvDigit() {
8168 if(this.t < 1) return 0;
8169 var x = this[0];
8170 if((x&1) == 0) return 0;
8171 var y = x&3; // y == 1/x mod 2^2
8172 y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
8173 y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
8174 y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
8175 // last step - calculate inverse mod DV directly;
8176 // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
8177 y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
8178 // we really want the negative inverse, and -DV < y < DV
8179 return (y>0)?this.DV-y:-y;
8180}
8181
8182// Montgomery reduction
8183function Montgomery(m) {
8184 this.m = m;
8185 this.mp = m.invDigit();
8186 this.mpl = this.mp&0x7fff;
8187 this.mph = this.mp>>15;
8188 this.um = (1<<(m.DB-15))-1;
8189 this.mt2 = 2*m.t;
8190}
8191
8192// xR mod m
8193function montConvert(x) {
8194 var r = nbi();
8195 x.abs().dlShiftTo(this.m.t,r);
8196 r.divRemTo(this.m,null,r);
8197 if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
8198 return r;
8199}
8200
8201// x/R mod m
8202function montRevert(x) {
8203 var r = nbi();
8204 x.copyTo(r);
8205 this.reduce(r);
8206 return r;
8207}
8208
8209// x = x/R mod m (HAC 14.32)
8210function montReduce(x) {
8211 while(x.t <= this.mt2) // pad x so am has enough room later
8212 x[x.t++] = 0;
8213 for(var i = 0; i < this.m.t; ++i) {
8214 // faster way of calculating u0 = x[i]*mp mod DV
8215 var j = x[i]&0x7fff;
8216 var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
8217 // use am to combine the multiply-shift-add into one call
8218 j = i+this.m.t;
8219 x[j] += this.m.am(0,u0,x,i,0,this.m.t);
8220 // propagate carry
8221 while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
8222 }
8223 x.clamp();
8224 x.drShiftTo(this.m.t,x);
8225 if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
8226}
8227
8228// r = "x^2/R mod m"; x != r
8229function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
8230
8231// r = "xy/R mod m"; x,y != r
8232function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
8233
8234Montgomery.prototype.convert = montConvert;
8235Montgomery.prototype.revert = montRevert;
8236Montgomery.prototype.reduce = montReduce;
8237Montgomery.prototype.mulTo = montMulTo;
8238Montgomery.prototype.sqrTo = montSqrTo;
8239
8240// (protected) true iff this is even
8241function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
8242
8243// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
8244function bnpExp(e,z) {
8245 if(e > 0xffffffff || e < 1) return BigInteger.ONE;
8246 var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
8247 g.copyTo(r);
8248 while(--i >= 0) {
8249 z.sqrTo(r,r2);
8250 if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
8251 else { var t = r; r = r2; r2 = t; }
8252 }
8253 return z.revert(r);
8254}
8255
8256// (public) this^e % m, 0 <= e < 2^32
8257function bnModPowInt(e,m) {
8258 var z;
8259 if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
8260 return this.exp(e,z);
8261}
8262
8263// protected
8264BigInteger.prototype.copyTo = bnpCopyTo;
8265BigInteger.prototype.fromInt = bnpFromInt;
8266BigInteger.prototype.fromString = bnpFromString;
8267BigInteger.prototype.clamp = bnpClamp;
8268BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
8269BigInteger.prototype.drShiftTo = bnpDRShiftTo;
8270BigInteger.prototype.lShiftTo = bnpLShiftTo;
8271BigInteger.prototype.rShiftTo = bnpRShiftTo;
8272BigInteger.prototype.subTo = bnpSubTo;
8273BigInteger.prototype.multiplyTo = bnpMultiplyTo;
8274BigInteger.prototype.squareTo = bnpSquareTo;
8275BigInteger.prototype.divRemTo = bnpDivRemTo;
8276BigInteger.prototype.invDigit = bnpInvDigit;
8277BigInteger.prototype.isEven = bnpIsEven;
8278BigInteger.prototype.exp = bnpExp;
8279
8280// public
8281BigInteger.prototype.toString = bnToString;
8282BigInteger.prototype.negate = bnNegate;
8283BigInteger.prototype.abs = bnAbs;
8284BigInteger.prototype.compareTo = bnCompareTo;
8285BigInteger.prototype.bitLength = bnBitLength;
8286BigInteger.prototype.mod = bnMod;
8287BigInteger.prototype.modPowInt = bnModPowInt;
8288
8289// "constants"
8290BigInteger.ZERO = nbv(0);
8291BigInteger.ONE = nbv(1);
8292
8293// Copyright (c) 2005-2009 Tom Wu
8294// All Rights Reserved.
8295// See "LICENSE" for details.
8296
8297// Extended JavaScript BN functions, required for RSA private ops.
8298
8299// Version 1.1: new BigInteger("0", 10) returns "proper" zero
8300
8301// (public)
8302function bnClone() { var r = nbi(); this.copyTo(r); return r; }
8303
8304// (public) return value as integer
8305function bnIntValue() {
8306 if(this.s < 0) {
8307 if(this.t == 1) return this[0]-this.DV;
8308 else if(this.t == 0) return -1;
8309 }
8310 else if(this.t == 1) return this[0];
8311 else if(this.t == 0) return 0;
8312 // assumes 16 < DB < 32
8313 return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
8314}
8315
8316// (public) return value as byte
8317function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
8318
8319// (public) return value as short (assumes DB>=16)
8320function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
8321
8322// (protected) return x s.t. r^x < DV
8323function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
8324
8325// (public) 0 if this == 0, 1 if this > 0
8326function bnSigNum() {
8327 if(this.s < 0) return -1;
8328 else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
8329 else return 1;
8330}
8331
8332// (protected) convert to radix string
8333function bnpToRadix(b) {
8334 if(b == null) b = 10;
8335 if(this.signum() == 0 || b < 2 || b > 36) return "0";
8336 var cs = this.chunkSize(b);
8337 var a = Math.pow(b,cs);
8338 var d = nbv(a), y = nbi(), z = nbi(), r = "";
8339 this.divRemTo(d,y,z);
8340 while(y.signum() > 0) {
8341 r = (a+z.intValue()).toString(b).substr(1) + r;
8342 y.divRemTo(d,y,z);
8343 }
8344 return z.intValue().toString(b) + r;
8345}
8346
8347// (protected) convert from radix string
8348function bnpFromRadix(s,b) {
8349 this.fromInt(0);
8350 if(b == null) b = 10;
8351 var cs = this.chunkSize(b);
8352 var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
8353 for(var i = 0; i < s.length; ++i) {
8354 var x = intAt(s,i);
8355 if(x < 0) {
8356 if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
8357 continue;
8358 }
8359 w = b*w+x;
8360 if(++j >= cs) {
8361 this.dMultiply(d);
8362 this.dAddOffset(w,0);
8363 j = 0;
8364 w = 0;
8365 }
8366 }
8367 if(j > 0) {
8368 this.dMultiply(Math.pow(b,j));
8369 this.dAddOffset(w,0);
8370 }
8371 if(mi) BigInteger.ZERO.subTo(this,this);
8372}
8373
8374// (protected) alternate constructor
8375function bnpFromNumber(a,b,c) {
8376 if("number" == typeof b) {
8377 // new BigInteger(int,int,RNG)
8378 if(a < 2) this.fromInt(1);
8379 else {
8380 this.fromNumber(a,c);
8381 if(!this.testBit(a-1)) // force MSB set
8382 this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
8383 if(this.isEven()) this.dAddOffset(1,0); // force odd
8384 while(!this.isProbablePrime(b)) {
8385 this.dAddOffset(2,0);
8386 if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
8387 }
8388 }
8389 }
8390 else {
8391 // new BigInteger(int,RNG)
8392 var x = new Array(), t = a&7;
8393 x.length = (a>>3)+1;
8394 b.nextBytes(x);
8395 if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
8396 this.fromString(x,256);
8397 }
8398}
8399
8400// (public) convert to bigendian byte array
8401function bnToByteArray() {
8402 var i = this.t, r = new Array();
8403 r[0] = this.s;
8404 var p = this.DB-(i*this.DB)%8, d, k = 0;
8405 if(i-- > 0) {
8406 if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
8407 r[k++] = d|(this.s<<(this.DB-p));
8408 while(i >= 0) {
8409 if(p < 8) {
8410 d = (this[i]&((1<<p)-1))<<(8-p);
8411 d |= this[--i]>>(p+=this.DB-8);
8412 }
8413 else {
8414 d = (this[i]>>(p-=8))&0xff;
8415 if(p <= 0) { p += this.DB; --i; }
8416 }
8417 if((d&0x80) != 0) d |= -256;
8418 if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
8419 if(k > 0 || d != this.s) r[k++] = d;
8420 }
8421 }
8422 return r;
8423}
8424
8425function bnEquals(a) { return(this.compareTo(a)==0); }
8426function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
8427function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
8428
8429// (protected) r = this op a (bitwise)
8430function bnpBitwiseTo(a,op,r) {
8431 var i, f, m = Math.min(a.t,this.t);
8432 for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
8433 if(a.t < this.t) {
8434 f = a.s&this.DM;
8435 for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
8436 r.t = this.t;
8437 }
8438 else {
8439 f = this.s&this.DM;
8440 for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
8441 r.t = a.t;
8442 }
8443 r.s = op(this.s,a.s);
8444 r.clamp();
8445}
8446
8447// (public) this & a
8448function op_and(x,y) { return x&y; }
8449function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
8450
8451// (public) this | a
8452function op_or(x,y) { return x|y; }
8453function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
8454
8455// (public) this ^ a
8456function op_xor(x,y) { return x^y; }
8457function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
8458
8459// (public) this & ~a
8460function op_andnot(x,y) { return x&~y; }
8461function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
8462
8463// (public) ~this
8464function bnNot() {
8465 var r = nbi();
8466 for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
8467 r.t = this.t;
8468 r.s = ~this.s;
8469 return r;
8470}
8471
8472// (public) this << n
8473function bnShiftLeft(n) {
8474 var r = nbi();
8475 if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
8476 return r;
8477}
8478
8479// (public) this >> n
8480function bnShiftRight(n) {
8481 var r = nbi();
8482 if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
8483 return r;
8484}
8485
8486// return index of lowest 1-bit in x, x < 2^31
8487function lbit(x) {
8488 if(x == 0) return -1;
8489 var r = 0;
8490 if((x&0xffff) == 0) { x >>= 16; r += 16; }
8491 if((x&0xff) == 0) { x >>= 8; r += 8; }
8492 if((x&0xf) == 0) { x >>= 4; r += 4; }
8493 if((x&3) == 0) { x >>= 2; r += 2; }
8494 if((x&1) == 0) ++r;
8495 return r;
8496}
8497
8498// (public) returns index of lowest 1-bit (or -1 if none)
8499function bnGetLowestSetBit() {
8500 for(var i = 0; i < this.t; ++i)
8501 if(this[i] != 0) return i*this.DB+lbit(this[i]);
8502 if(this.s < 0) return this.t*this.DB;
8503 return -1;
8504}
8505
8506// return number of 1 bits in x
8507function cbit(x) {
8508 var r = 0;
8509 while(x != 0) { x &= x-1; ++r; }
8510 return r;
8511}
8512
8513// (public) return number of set bits
8514function bnBitCount() {
8515 var r = 0, x = this.s&this.DM;
8516 for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
8517 return r;
8518}
8519
8520// (public) true iff nth bit is set
8521function bnTestBit(n) {
8522 var j = Math.floor(n/this.DB);
8523 if(j >= this.t) return(this.s!=0);
8524 return((this[j]&(1<<(n%this.DB)))!=0);
8525}
8526
8527// (protected) this op (1<<n)
8528function bnpChangeBit(n,op) {
8529 var r = BigInteger.ONE.shiftLeft(n);
8530 this.bitwiseTo(r,op,r);
8531 return r;
8532}
8533
8534// (public) this | (1<<n)
8535function bnSetBit(n) { return this.changeBit(n,op_or); }
8536
8537// (public) this & ~(1<<n)
8538function bnClearBit(n) { return this.changeBit(n,op_andnot); }
8539
8540// (public) this ^ (1<<n)
8541function bnFlipBit(n) { return this.changeBit(n,op_xor); }
8542
8543// (protected) r = this + a
8544function bnpAddTo(a,r) {
8545 var i = 0, c = 0, m = Math.min(a.t,this.t);
8546 while(i < m) {
8547 c += this[i]+a[i];
8548 r[i++] = c&this.DM;
8549 c >>= this.DB;
8550 }
8551 if(a.t < this.t) {
8552 c += a.s;
8553 while(i < this.t) {
8554 c += this[i];
8555 r[i++] = c&this.DM;
8556 c >>= this.DB;
8557 }
8558 c += this.s;
8559 }
8560 else {
8561 c += this.s;
8562 while(i < a.t) {
8563 c += a[i];
8564 r[i++] = c&this.DM;
8565 c >>= this.DB;
8566 }
8567 c += a.s;
8568 }
8569 r.s = (c<0)?-1:0;
8570 if(c > 0) r[i++] = c;
8571 else if(c < -1) r[i++] = this.DV+c;
8572 r.t = i;
8573 r.clamp();
8574}
8575
8576// (public) this + a
8577function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
8578
8579// (public) this - a
8580function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
8581
8582// (public) this * a
8583function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
8584
8585// (public) this / a
8586function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
8587
8588// (public) this % a
8589function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
8590
8591// (public) [this/a,this%a]
8592function bnDivideAndRemainder(a) {
8593 var q = nbi(), r = nbi();
8594 this.divRemTo(a,q,r);
8595 return new Array(q,r);
8596}
8597
8598// (protected) this *= n, this >= 0, 1 < n < DV
8599function bnpDMultiply(n) {
8600 this[this.t] = this.am(0,n-1,this,0,0,this.t);
8601 ++this.t;
8602 this.clamp();
8603}
8604
8605// (protected) this += n << w words, this >= 0
8606function bnpDAddOffset(n,w) {
8607 if(n == 0) return;
8608 while(this.t <= w) this[this.t++] = 0;
8609 this[w] += n;
8610 while(this[w] >= this.DV) {
8611 this[w] -= this.DV;
8612 if(++w >= this.t) this[this.t++] = 0;
8613 ++this[w];
8614 }
8615}
8616
8617// A "null" reducer
8618function NullExp() {}
8619function nNop(x) { return x; }
8620function nMulTo(x,y,r) { x.multiplyTo(y,r); }
8621function nSqrTo(x,r) { x.squareTo(r); }
8622
8623NullExp.prototype.convert = nNop;
8624NullExp.prototype.revert = nNop;
8625NullExp.prototype.mulTo = nMulTo;
8626NullExp.prototype.sqrTo = nSqrTo;
8627
8628// (public) this^e
8629function bnPow(e) { return this.exp(e,new NullExp()); }
8630
8631// (protected) r = lower n words of "this * a", a.t <= n
8632// "this" should be the larger one if appropriate.
8633function bnpMultiplyLowerTo(a,n,r) {
8634 var i = Math.min(this.t+a.t,n);
8635 r.s = 0; // assumes a,this >= 0
8636 r.t = i;
8637 while(i > 0) r[--i] = 0;
8638 var j;
8639 for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
8640 for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
8641 r.clamp();
8642}
8643
8644// (protected) r = "this * a" without lower n words, n > 0
8645// "this" should be the larger one if appropriate.
8646function bnpMultiplyUpperTo(a,n,r) {
8647 --n;
8648 var i = r.t = this.t+a.t-n;
8649 r.s = 0; // assumes a,this >= 0
8650 while(--i >= 0) r[i] = 0;
8651 for(i = Math.max(n-this.t,0); i < a.t; ++i)
8652 r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
8653 r.clamp();
8654 r.drShiftTo(1,r);
8655}
8656
8657// Barrett modular reduction
8658function Barrett(m) {
8659 // setup Barrett
8660 this.r2 = nbi();
8661 this.q3 = nbi();
8662 BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
8663 this.mu = this.r2.divide(m);
8664 this.m = m;
8665}
8666
8667function barrettConvert(x) {
8668 if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
8669 else if(x.compareTo(this.m) < 0) return x;
8670 else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
8671}
8672
8673function barrettRevert(x) { return x; }
8674
8675// x = x mod m (HAC 14.42)
8676function barrettReduce(x) {
8677 x.drShiftTo(this.m.t-1,this.r2);
8678 if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
8679 this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
8680 this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
8681 while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
8682 x.subTo(this.r2,x);
8683 while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
8684}
8685
8686// r = x^2 mod m; x != r
8687function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
8688
8689// r = x*y mod m; x,y != r
8690function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
8691
8692Barrett.prototype.convert = barrettConvert;
8693Barrett.prototype.revert = barrettRevert;
8694Barrett.prototype.reduce = barrettReduce;
8695Barrett.prototype.mulTo = barrettMulTo;
8696Barrett.prototype.sqrTo = barrettSqrTo;
8697
8698// (public) this^e % m (HAC 14.85)
8699function bnModPow(e,m) {
8700 var i = e.bitLength(), k, r = nbv(1), z;
8701 if(i <= 0) return r;
8702 else if(i < 18) k = 1;
8703 else if(i < 48) k = 3;
8704 else if(i < 144) k = 4;
8705 else if(i < 768) k = 5;
8706 else k = 6;
8707 if(i < 8)
8708 z = new Classic(m);
8709 else if(m.isEven())
8710 z = new Barrett(m);
8711 else
8712 z = new Montgomery(m);
8713
8714 // precomputation
8715 var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
8716 g[1] = z.convert(this);
8717 if(k > 1) {
8718 var g2 = nbi();
8719 z.sqrTo(g[1],g2);
8720 while(n <= km) {
8721 g[n] = nbi();
8722 z.mulTo(g2,g[n-2],g[n]);
8723 n += 2;
8724 }
8725 }
8726
8727 var j = e.t-1, w, is1 = true, r2 = nbi(), t;
8728 i = nbits(e[j])-1;
8729 while(j >= 0) {
8730 if(i >= k1) w = (e[j]>>(i-k1))&km;
8731 else {
8732 w = (e[j]&((1<<(i+1))-1))<<(k1-i);
8733 if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
8734 }
8735
8736 n = k;
8737 while((w&1) == 0) { w >>= 1; --n; }
8738 if((i -= n) < 0) { i += this.DB; --j; }
8739 if(is1) { // ret == 1, don't bother squaring or multiplying it
8740 g[w].copyTo(r);
8741 is1 = false;
8742 }
8743 else {
8744 while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
8745 if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
8746 z.mulTo(r2,g[w],r);
8747 }
8748
8749 while(j >= 0 && (e[j]&(1<<i)) == 0) {
8750 z.sqrTo(r,r2); t = r; r = r2; r2 = t;
8751 if(--i < 0) { i = this.DB-1; --j; }
8752 }
8753 }
8754 return z.revert(r);
8755}
8756
8757// (public) gcd(this,a) (HAC 14.54)
8758function bnGCD(a) {
8759 var x = (this.s<0)?this.negate():this.clone();
8760 var y = (a.s<0)?a.negate():a.clone();
8761 if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
8762 var i = x.getLowestSetBit(), g = y.getLowestSetBit();
8763 if(g < 0) return x;
8764 if(i < g) g = i;
8765 if(g > 0) {
8766 x.rShiftTo(g,x);
8767 y.rShiftTo(g,y);
8768 }
8769 while(x.signum() > 0) {
8770 if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
8771 if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
8772 if(x.compareTo(y) >= 0) {
8773 x.subTo(y,x);
8774 x.rShiftTo(1,x);
8775 }
8776 else {
8777 y.subTo(x,y);
8778 y.rShiftTo(1,y);
8779 }
8780 }
8781 if(g > 0) y.lShiftTo(g,y);
8782 return y;
8783}
8784
8785// (protected) this % n, n < 2^26
8786function bnpModInt(n) {
8787 if(n <= 0) return 0;
8788 var d = this.DV%n, r = (this.s<0)?n-1:0;
8789 if(this.t > 0)
8790 if(d == 0) r = this[0]%n;
8791 else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
8792 return r;
8793}
8794
8795// (public) 1/this % m (HAC 14.61)
8796function bnModInverse(m) {
8797 var ac = m.isEven();
8798 if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
8799 var u = m.clone(), v = this.clone();
8800 var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
8801 while(u.signum() != 0) {
8802 while(u.isEven()) {
8803 u.rShiftTo(1,u);
8804 if(ac) {
8805 if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
8806 a.rShiftTo(1,a);
8807 }
8808 else if(!b.isEven()) b.subTo(m,b);
8809 b.rShiftTo(1,b);
8810 }
8811 while(v.isEven()) {
8812 v.rShiftTo(1,v);
8813 if(ac) {
8814 if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
8815 c.rShiftTo(1,c);
8816 }
8817 else if(!d.isEven()) d.subTo(m,d);
8818 d.rShiftTo(1,d);
8819 }
8820 if(u.compareTo(v) >= 0) {
8821 u.subTo(v,u);
8822 if(ac) a.subTo(c,a);
8823 b.subTo(d,b);
8824 }
8825 else {
8826 v.subTo(u,v);
8827 if(ac) c.subTo(a,c);
8828 d.subTo(b,d);
8829 }
8830 }
8831 if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
8832 if(d.compareTo(m) >= 0) return d.subtract(m);
8833 if(d.signum() < 0) d.addTo(m,d); else return d;
8834 if(d.signum() < 0) return d.add(m); else return d;
8835}
8836
8837var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
8838var lplim = (1<<26)/lowprimes[lowprimes.length-1];
8839
8840// (public) test primality with certainty >= 1-.5^t
8841function bnIsProbablePrime(t) {
8842 var i, x = this.abs();
8843 if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
8844 for(i = 0; i < lowprimes.length; ++i)
8845 if(x[0] == lowprimes[i]) return true;
8846 return false;
8847 }
8848 if(x.isEven()) return false;
8849 i = 1;
8850 while(i < lowprimes.length) {
8851 var m = lowprimes[i], j = i+1;
8852 while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
8853 m = x.modInt(m);
8854 while(i < j) if(m%lowprimes[i++] == 0) return false;
8855 }
8856 return x.millerRabin(t);
8857}
8858
8859// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
8860function bnpMillerRabin(t) {
8861 var n1 = this.subtract(BigInteger.ONE);
8862 var k = n1.getLowestSetBit();
8863 if(k <= 0) return false;
8864 var r = n1.shiftRight(k);
8865 t = (t+1)>>1;
8866 if(t > lowprimes.length) t = lowprimes.length;
8867 var a = nbi();
8868 for(var i = 0; i < t; ++i) {
8869 a.fromInt(lowprimes[i]);
8870 var y = a.modPow(r,this);
8871 if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
8872 var j = 1;
8873 while(j++ < k && y.compareTo(n1) != 0) {
8874 y = y.modPowInt(2,this);
8875 if(y.compareTo(BigInteger.ONE) == 0) return false;
8876 }
8877 if(y.compareTo(n1) != 0) return false;
8878 }
8879 }
8880 return true;
8881}
8882
8883// protected
8884BigInteger.prototype.chunkSize = bnpChunkSize;
8885BigInteger.prototype.toRadix = bnpToRadix;
8886BigInteger.prototype.fromRadix = bnpFromRadix;
8887BigInteger.prototype.fromNumber = bnpFromNumber;
8888BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
8889BigInteger.prototype.changeBit = bnpChangeBit;
8890BigInteger.prototype.addTo = bnpAddTo;
8891BigInteger.prototype.dMultiply = bnpDMultiply;
8892BigInteger.prototype.dAddOffset = bnpDAddOffset;
8893BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
8894BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
8895BigInteger.prototype.modInt = bnpModInt;
8896BigInteger.prototype.millerRabin = bnpMillerRabin;
8897
8898// public
8899BigInteger.prototype.clone = bnClone;
8900BigInteger.prototype.intValue = bnIntValue;
8901BigInteger.prototype.byteValue = bnByteValue;
8902BigInteger.prototype.shortValue = bnShortValue;
8903BigInteger.prototype.signum = bnSigNum;
8904BigInteger.prototype.toByteArray = bnToByteArray;
8905BigInteger.prototype.equals = bnEquals;
8906BigInteger.prototype.min = bnMin;
8907BigInteger.prototype.max = bnMax;
8908BigInteger.prototype.and = bnAnd;
8909BigInteger.prototype.or = bnOr;
8910BigInteger.prototype.xor = bnXor;
8911BigInteger.prototype.andNot = bnAndNot;
8912BigInteger.prototype.not = bnNot;
8913BigInteger.prototype.shiftLeft = bnShiftLeft;
8914BigInteger.prototype.shiftRight = bnShiftRight;
8915BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
8916BigInteger.prototype.bitCount = bnBitCount;
8917BigInteger.prototype.testBit = bnTestBit;
8918BigInteger.prototype.setBit = bnSetBit;
8919BigInteger.prototype.clearBit = bnClearBit;
8920BigInteger.prototype.flipBit = bnFlipBit;
8921BigInteger.prototype.add = bnAdd;
8922BigInteger.prototype.subtract = bnSubtract;
8923BigInteger.prototype.multiply = bnMultiply;
8924BigInteger.prototype.divide = bnDivide;
8925BigInteger.prototype.remainder = bnRemainder;
8926BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
8927BigInteger.prototype.modPow = bnModPow;
8928BigInteger.prototype.modInverse = bnModInverse;
8929BigInteger.prototype.pow = bnPow;
8930BigInteger.prototype.gcd = bnGCD;
8931BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
8932
8933// BigInteger interfaces not implemented in jsbn:
8934
8935// BigInteger(int signum, byte[] magnitude)
8936// double doubleValue()
8937// float floatValue()
8938// int hashCode()
8939// long longValue()
8940// static BigInteger valueOf(long val)
8941