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