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