KeyStore implemented
diff --git a/js/Key.js b/js/Key.js
index 99fc813..7f02090 100644
--- a/js/Key.js
+++ b/js/Key.js
@@ -46,94 +46,94 @@
KeyLocator.prototype.from_ccnb = function(decoder) {
- decoder.readStartElement(this.getElementLabel());
+ decoder.readStartElement(this.getElementLabel());
- if (decoder.peekStartElement(CCNProtocolDTags.Key)) {
- try {
- encodedKey = decoder.readBinaryElement(CCNProtocolDTags.Key);
- // This is a DER-encoded SubjectPublicKeyInfo.
-
- //TODO FIX THIS, This should create a Key Object instead of keeping bytes
-
- this.publicKey = encodedKey;//CryptoUtil.getPublicKey(encodedKey);
- this.type = KeyLocatorType.KEY;
-
-
- if(LOG>4) console.log('PUBLIC KEY FOUND: '+ this.publicKey);
- //this.publicKey = encodedKey;
-
-
- } catch (e) {
- throw new Error("Cannot parse key: ", e);
- }
-
- if (null == this.publicKey) {
- throw new Error("Cannot parse key: ");
- }
-
- } else if ( decoder.peekStartElement(CCNProtocolDTags.Certificate)) {
- try {
- encodedCert = decoder.readBinaryElement(CCNProtocolDTags.Certificate);
-
- /*
- * Certificates not yet working
- */
-
- //CertificateFactory factory = CertificateFactory.getInstance("X.509");
- //this.certificate = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(encodedCert));
-
-
- this.certificate = encodedCert;
- this.type = KeyLocatorType.CERTIFICATE;
-
- if(LOG>4) console.log('CERTIFICATE FOUND: '+ this.certificate);
-
- } catch ( e) {
- throw new Error("Cannot decode certificate: " + e);
- }
- if (null == this.certificate) {
- throw new Error("Cannot parse certificate! ");
- }
- } else {
- this.type = KeyLocatorType.KEYNAME;
+ if (decoder.peekStartElement(CCNProtocolDTags.Key)) {
+ try {
+ encodedKey = decoder.readBinaryElement(CCNProtocolDTags.Key);
+ // This is a DER-encoded SubjectPublicKeyInfo.
- this.keyName = new KeyName();
- this.keyName.from_ccnb(decoder);
+ //TODO FIX THIS, This should create a Key Object instead of keeping bytes
+
+ this.publicKey = encodedKey;//CryptoUtil.getPublicKey(encodedKey);
+ this.type = KeyLocatorType.KEY;
+
+
+ if(LOG>4) console.log('PUBLIC KEY FOUND: '+ this.publicKey);
+ //this.publicKey = encodedKey;
+
+
+ } catch (e) {
+ throw new Error("Cannot parse key: ", e);
+ }
+
+ if (null == this.publicKey) {
+ throw new Error("Cannot parse key: ");
}
- decoder.readEndElement();
+
+ } else if ( decoder.peekStartElement(CCNProtocolDTags.Certificate)) {
+ try {
+ encodedCert = decoder.readBinaryElement(CCNProtocolDTags.Certificate);
+
+ /*
+ * Certificates not yet working
+ */
+
+ //CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ //this.certificate = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(encodedCert));
+
+
+ this.certificate = encodedCert;
+ this.type = KeyLocatorType.CERTIFICATE;
+
+ if(LOG>4) console.log('CERTIFICATE FOUND: '+ this.certificate);
+
+ } catch ( e) {
+ throw new Error("Cannot decode certificate: " + e);
+ }
+ if (null == this.certificate) {
+ throw new Error("Cannot parse certificate! ");
+ }
+ } else {
+ this.type = KeyLocatorType.KEYNAME;
+
+ this.keyName = new KeyName();
+ this.keyName.from_ccnb(decoder);
}
+ decoder.readEndElement();
+};
- KeyLocator.prototype.to_ccnb = function( encoder) {
-
- if(LOG>4) console.log('type is is ' + this.type);
- //TODO Check if Name is missing
- if (!this.validate()) {
- throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
- }
+KeyLocator.prototype.to_ccnb = function( encoder) {
+
+ if(LOG>4) console.log('type is is ' + this.type);
+ //TODO Check if Name is missing
+ if (!this.validate()) {
+ throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
+ }
+
+ //TODO FIX THIS TOO
+ encoder.writeStartElement(this.getElementLabel());
+
+ if (this.type == KeyLocatorType.KEY) {
+ if(LOG>5)console.log('About to encode a public key' +this.publicKey);
+ encoder.writeElement(CCNProtocolDTags.Key, this.publicKey);
- //TODO FIX THIS TOO
- encoder.writeStartElement(this.getElementLabel());
+ } else if (this.type == KeyLocatorType.CERTIFICATE) {
- if (this.type == KeyLocatorType.KEY) {
- if(LOG>5)console.log('About to encode a public key' +this.publicKey);
- encoder.writeElement(CCNProtocolDTags.Key, this.publicKey);
-
- } else if (this.type == KeyLocatorType.CERTIFICATE) {
-
- try {
- encoder.writeElement(CCNProtocolDTags.Certificate, this.certificate);
- } catch ( e) {
- throw new Error("CertificateEncodingException attempting to write key locator: " + e);
- }
-
- } else if (this.type == KeyLocatorType.KEYNAME) {
-
- this.keyName.to_ccnb(encoder);
+ try {
+ encoder.writeElement(CCNProtocolDTags.Certificate, this.certificate);
+ } catch ( e) {
+ throw new Error("CertificateEncodingException attempting to write key locator: " + e);
}
- encoder.writeEndElement();
+ } else if (this.type == KeyLocatorType.KEYNAME) {
+
+ this.keyName.to_ccnb(encoder);
+ }
+ encoder.writeEndElement();
+
};
KeyLocator.prototype.getElementLabel = function() {
@@ -194,3 +194,21 @@
// null signedInfo ok
return (null != this.contentName);
};
+
+KeyName.prototype.matches_name = function(/*Name*/ name) {
+ var i_name = this.contentName.components;
+ var o_name = name.components;
+
+ // The intrest name is longer than the name we are checking it against.
+ if (i_name.length > o_name.length)
+ return false;
+
+ // Check if at least one of given components doesn't match.
+ for (var i = 0; i < i_name.length; ++i) {
+ if (!DataUtils.arraysEqual(i_name[i], o_name[i]))
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/js/NDN.js b/js/NDN.js
index e515975..a61603e 100644
--- a/js/NDN.js
+++ b/js/NDN.js
@@ -44,6 +44,29 @@
this.port=port;
}
+
+NDN.KeyStore = new Array();
+
+var KeyStoreEntry = function KeyStoreEntry(name, key, rsa) {
+ this.keyName = name; // KeyName
+ this.keyHex = key; // Raw key hex string
+ this.rsaKey = rsa; // RSA key
+};
+
+NDN.getKeyByName = function(/* KeyName */ name) {
+ var result = null;
+
+ for (var i = 0; i < NDN.KeyStore.length; i++) {
+ if (NDN.KeyStore[i].keyName.matches_name(name.contentName)) {
+ if (result == null ||
+ NDN.KeyStore[i].keyName.contentName.components.length > result.keyName.contentName.components.length)
+ result = NDN.KeyStore[i];
+ }
+ }
+
+ return result;
+};
+
// For fetching data
NDN.PITTable = new Array();
diff --git a/js/WebSocketTransport.js b/js/WebSocketTransport.js
index f3ee4d9..6b65b37 100644
--- a/js/WebSocketTransport.js
+++ b/js/WebSocketTransport.js
@@ -151,7 +151,7 @@
// Key verification
var verified = false;
- // Recursive key fetching closure
+ // Recursive key fetching & verification closure
var KeyFetchClosure = function KeyFetchClosure(content, closure, key, signature) {
this.contentObject = content; // unverified content object
this.closure = closure; // closure corresponding to the contentObject
@@ -165,7 +165,7 @@
if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
console.log("In KeyFetchClosure.upcall: interest time out.");
} else if (kind == Closure.UPCALL_CONTENT) {
- console.log("In KeyFetchClosure.upcall");
+ console.log("In KeyFetchClosure.upcall: signature verification passed");
var keyHex = DataUtils.toHex(upcallInfo.contentObject.content).toLowerCase();
console.log("Key: " + keyHex);
@@ -174,7 +174,7 @@
var rsakey = new RSAKey();
rsakey.setPublic(kp, exp);
- verified = rsakey.verifyByteArray(this.contentObject.rawSignatureData, sigHex);
+ var verified = rsakey.verifyByteArray(this.contentObject.rawSignatureData, this.signature);
var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
console.log("raise encapsulated closure");
@@ -192,19 +192,51 @@
var keyname = keylocator.keyName.contentName.getName();
console.log(keyname);
- if (nameStr.match("/ccnx.org/Users/")) {
- console.log("Key found");
- currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
+ if (nameStr.match(keyname)) {
+ console.log("Content is key itself");
+
+ var keyHex = DataUtils.toHex(co.content).toLowerCase();
+ console.log("Key content: " + keyHex);
+
+ var kp = keyHex.slice(56, 314);
+ var exp = keyHex.slice(318, 324);
+
+ var rsakey = new RSAKey();
+ rsakey.setPublic(kp, exp);
+ var verified = rsakey.verifyByteArray(co.rawSignatureData, sigHex);
+ var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
+
+ currentClosure.upcall(flag, new UpcallInfo(ndn, null, 0, co));
+
+ // Store key in cache
+ var keyEntry = new KeyStoreEntry(keylocator.keyName, keyHex, rsakey);
+ NDN.KeyStore.push(keyEntry);
} else {
console.log("Fetch key according to keylocator");
- var nextClosure = new KeyFetchClosure(co, currentClosure, keyname, sigHex);
- var interest = new Interest(keylocator.keyName.contentName.getPrefix(4));
- interest.interestLifetime = 4.0;
- self.expressInterest(ndn, interest, nextClosure);
+
+ // Check local key store
+ var keyEntry = NDN.getKeyByName(keylocator.keyName);
+ if (keyEntry) {
+ // Key found, verify now
+ console.log("Local key cache hit");
+ var rsakey = keyEntry.rsaKey;
+ verified = rsakey.verifyByteArray(co.rawSignatureData, sigHex);
+
+ var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
+
+ // Raise callback
+ currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
+ } else {
+ // Not found, fetch now
+ var nextClosure = new KeyFetchClosure(co, currentClosure, keyname, sigHex);
+ var interest = new Interest(keylocator.keyName.contentName.getPrefix(4));
+ interest.interestLifetime = 4.0;
+ self.expressInterest(ndn, interest, nextClosure);
+ }
}
} else if (keylocator.type == KeyLocatorType.KEY) {
console.log("Keylocator contains KEY");
- var publickeyHex = DataUtils.toHex(co.signedInfo.locator.publicKey).toLowerCase();
+ var publickeyHex = DataUtils.toHex(keylocator.publicKey).toLowerCase();
console.log(publickeyHex);
var kp = publickeyHex.slice(56, 314);
@@ -218,6 +250,10 @@
// Raise callback
currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
+
+ // Store key in cache
+ var keyEntry = new KeyStoreEntry(keylocator.keyName, publickeyHex, rsakey);
+ NDN.KeyStore.push(keyEntry);
} else {
var cert = keylocator.certificate;
console.log("KeyLocator contains CERT");
diff --git a/js/testing/test-get-async.html b/js/testing/test-get-async.html
index a5ac9d8..e019537 100644
--- a/js/testing/test-get-async.html
+++ b/js/testing/test-get-async.html
@@ -16,6 +16,10 @@
var ndn = new NDN({port:9696});
ndn.transport.connectWebSocket(ndn);
+ ndn.onopen = function() {
+ document.getElementById("testBtn").disabled = false;
+ };
+
var AsyncGetClosure = function AsyncGetClosure() {
// Inherit from Closure.
Closure.call(this);
@@ -59,7 +63,7 @@
<input id="interest" type="text" name="INTEREST" size="50" value="/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY" />
</form>
- <button onclick="run()">Fetch Content</button>
+ <button id="testBtn" onclick="run()" disabled="disabled">Fetch Content</button>
<p id="content">Content: <br/></p>
diff --git a/js/testing/test-publish-async.html b/js/testing/test-publish-async.html
index b29098e..f69756a 100644
--- a/js/testing/test-publish-async.html
+++ b/js/testing/test-publish-async.html
@@ -17,6 +17,10 @@
var ndn = new NDN();
ndn.transport.connectWebSocket(ndn);
+ ndn.onopen = function() {
+ document.getElementById("testBtn").disabled = false;
+ };
+
var AsyncPutClosure = function AsyncPutClosure() {
// Inherit from Closure.
Closure.call(this);
@@ -70,7 +74,7 @@
</div>
</form>
<div>
- <button onclick="run()">Publish Content</button>
+ <button id="testBtn" onclick="run()" disabled="disabled">Publish Content</button>
</div>
<p id="result"></p>
diff --git a/js/tools/build/ndn-js-uncomp.js b/js/tools/build/ndn-js-uncomp.js
index 6f0cd3e..0a291f1 100644
--- a/js/tools/build/ndn-js-uncomp.js
+++ b/js/tools/build/ndn-js-uncomp.js
@@ -110,6 +110,29 @@
this.port=port;
}
+
+NDN.KeyStore = new Array();
+
+var KeyStoreEntry = function KeyStoreEntry(name, key, rsa) {
+ this.keyName = name; // KeyName
+ this.keyHex = key; // Raw key hex string
+ this.rsaKey = rsa; // RSA key
+};
+
+NDN.getKeyByName = function(/* KeyName */ name) {
+ var result = null;
+
+ for (var i = 0; i < NDN.KeyStore.length; i++) {
+ if (NDN.KeyStore[i].keyName.matches_name(name.contentName)) {
+ if (result == null ||
+ NDN.KeyStore[i].keyName.contentName.components.length > result.keyName.contentName.components.length)
+ result = NDN.KeyStore[i];
+ }
+ }
+
+ return result;
+};
+
// For fetching data
NDN.PITTable = new Array();
@@ -407,7 +430,7 @@
// Key verification
var verified = false;
- // Recursive key fetching closure
+ // Recursive key fetching & verification closure
var KeyFetchClosure = function KeyFetchClosure(content, closure, key, signature) {
this.contentObject = content; // unverified content object
this.closure = closure; // closure corresponding to the contentObject
@@ -421,7 +444,7 @@
if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
console.log("In KeyFetchClosure.upcall: interest time out.");
} else if (kind == Closure.UPCALL_CONTENT) {
- console.log("In KeyFetchClosure.upcall");
+ console.log("In KeyFetchClosure.upcall: signature verification passed");
var keyHex = DataUtils.toHex(upcallInfo.contentObject.content).toLowerCase();
console.log("Key: " + keyHex);
@@ -430,7 +453,7 @@
var rsakey = new RSAKey();
rsakey.setPublic(kp, exp);
- verified = rsakey.verifyByteArray(this.contentObject.rawSignatureData, sigHex);
+ var verified = rsakey.verifyByteArray(this.contentObject.rawSignatureData, this.signature);
var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
console.log("raise encapsulated closure");
@@ -448,19 +471,51 @@
var keyname = keylocator.keyName.contentName.getName();
console.log(keyname);
- if (nameStr.match("/ccnx.org/Users/")) {
- console.log("Key found");
- currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
+ if (nameStr.match(keyname)) {
+ console.log("Content is key itself");
+
+ var keyHex = DataUtils.toHex(co.content).toLowerCase();
+ console.log("Key content: " + keyHex);
+
+ var kp = keyHex.slice(56, 314);
+ var exp = keyHex.slice(318, 324);
+
+ var rsakey = new RSAKey();
+ rsakey.setPublic(kp, exp);
+ var verified = rsakey.verifyByteArray(co.rawSignatureData, sigHex);
+ var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
+
+ currentClosure.upcall(flag, new UpcallInfo(ndn, null, 0, co));
+
+ // Store key in cache
+ var keyEntry = new KeyStoreEntry(keylocator.keyName, keyHex, rsakey);
+ NDN.KeyStore.push(keyEntry);
} else {
console.log("Fetch key according to keylocator");
- var nextClosure = new KeyFetchClosure(co, currentClosure, keyname, sigHex);
- var interest = new Interest(keylocator.keyName.contentName.getPrefix(4));
- interest.interestLifetime = 4.0;
- self.expressInterest(ndn, interest, nextClosure);
+
+ // Check local key store
+ var keyEntry = NDN.getKeyByName(keylocator.keyName);
+ if (keyEntry) {
+ // Key found, verify now
+ console.log("Local key cache hit");
+ var rsakey = keyEntry.rsaKey;
+ verified = rsakey.verifyByteArray(co.rawSignatureData, sigHex);
+
+ var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
+
+ // Raise callback
+ currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
+ } else {
+ // Not found, fetch now
+ var nextClosure = new KeyFetchClosure(co, currentClosure, keyname, sigHex);
+ var interest = new Interest(keylocator.keyName.contentName.getPrefix(4));
+ interest.interestLifetime = 4.0;
+ self.expressInterest(ndn, interest, nextClosure);
+ }
}
} else if (keylocator.type == KeyLocatorType.KEY) {
console.log("Keylocator contains KEY");
- var publickeyHex = DataUtils.toHex(co.signedInfo.locator.publicKey).toLowerCase();
+ var publickeyHex = DataUtils.toHex(keylocator.publicKey).toLowerCase();
console.log(publickeyHex);
var kp = publickeyHex.slice(56, 314);
@@ -474,6 +529,10 @@
// Raise callback
currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
+
+ // Store key in cache
+ var keyEntry = new KeyStoreEntry(keylocator.keyName, publickeyHex, rsakey);
+ NDN.KeyStore.push(keyEntry);
} else {
var cert = keylocator.certificate;
console.log("KeyLocator contains CERT");
@@ -2022,94 +2081,94 @@
KeyLocator.prototype.from_ccnb = function(decoder) {
- decoder.readStartElement(this.getElementLabel());
+ decoder.readStartElement(this.getElementLabel());
- if (decoder.peekStartElement(CCNProtocolDTags.Key)) {
- try {
- encodedKey = decoder.readBinaryElement(CCNProtocolDTags.Key);
- // This is a DER-encoded SubjectPublicKeyInfo.
-
- //TODO FIX THIS, This should create a Key Object instead of keeping bytes
-
- this.publicKey = encodedKey;//CryptoUtil.getPublicKey(encodedKey);
- this.type = KeyLocatorType.KEY;
-
-
- if(LOG>4) console.log('PUBLIC KEY FOUND: '+ this.publicKey);
- //this.publicKey = encodedKey;
-
-
- } catch (e) {
- throw new Error("Cannot parse key: ", e);
- }
-
- if (null == this.publicKey) {
- throw new Error("Cannot parse key: ");
- }
-
- } else if ( decoder.peekStartElement(CCNProtocolDTags.Certificate)) {
- try {
- encodedCert = decoder.readBinaryElement(CCNProtocolDTags.Certificate);
-
- /*
- * Certificates not yet working
- */
-
- //CertificateFactory factory = CertificateFactory.getInstance("X.509");
- //this.certificate = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(encodedCert));
-
-
- this.certificate = encodedCert;
- this.type = KeyLocatorType.CERTIFICATE;
-
- if(LOG>4) console.log('CERTIFICATE FOUND: '+ this.certificate);
-
- } catch ( e) {
- throw new Error("Cannot decode certificate: " + e);
- }
- if (null == this.certificate) {
- throw new Error("Cannot parse certificate! ");
- }
- } else {
- this.type = KeyLocatorType.KEYNAME;
+ if (decoder.peekStartElement(CCNProtocolDTags.Key)) {
+ try {
+ encodedKey = decoder.readBinaryElement(CCNProtocolDTags.Key);
+ // This is a DER-encoded SubjectPublicKeyInfo.
- this.keyName = new KeyName();
- this.keyName.from_ccnb(decoder);
+ //TODO FIX THIS, This should create a Key Object instead of keeping bytes
+
+ this.publicKey = encodedKey;//CryptoUtil.getPublicKey(encodedKey);
+ this.type = KeyLocatorType.KEY;
+
+
+ if(LOG>4) console.log('PUBLIC KEY FOUND: '+ this.publicKey);
+ //this.publicKey = encodedKey;
+
+
+ } catch (e) {
+ throw new Error("Cannot parse key: ", e);
+ }
+
+ if (null == this.publicKey) {
+ throw new Error("Cannot parse key: ");
}
- decoder.readEndElement();
+
+ } else if ( decoder.peekStartElement(CCNProtocolDTags.Certificate)) {
+ try {
+ encodedCert = decoder.readBinaryElement(CCNProtocolDTags.Certificate);
+
+ /*
+ * Certificates not yet working
+ */
+
+ //CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ //this.certificate = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(encodedCert));
+
+
+ this.certificate = encodedCert;
+ this.type = KeyLocatorType.CERTIFICATE;
+
+ if(LOG>4) console.log('CERTIFICATE FOUND: '+ this.certificate);
+
+ } catch ( e) {
+ throw new Error("Cannot decode certificate: " + e);
+ }
+ if (null == this.certificate) {
+ throw new Error("Cannot parse certificate! ");
+ }
+ } else {
+ this.type = KeyLocatorType.KEYNAME;
+
+ this.keyName = new KeyName();
+ this.keyName.from_ccnb(decoder);
}
+ decoder.readEndElement();
+};
- KeyLocator.prototype.to_ccnb = function( encoder) {
-
- if(LOG>4) console.log('type is is ' + this.type);
- //TODO Check if Name is missing
- if (!this.validate()) {
- throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
- }
+KeyLocator.prototype.to_ccnb = function( encoder) {
+
+ if(LOG>4) console.log('type is is ' + this.type);
+ //TODO Check if Name is missing
+ if (!this.validate()) {
+ throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
+ }
+
+ //TODO FIX THIS TOO
+ encoder.writeStartElement(this.getElementLabel());
+
+ if (this.type == KeyLocatorType.KEY) {
+ if(LOG>5)console.log('About to encode a public key' +this.publicKey);
+ encoder.writeElement(CCNProtocolDTags.Key, this.publicKey);
- //TODO FIX THIS TOO
- encoder.writeStartElement(this.getElementLabel());
+ } else if (this.type == KeyLocatorType.CERTIFICATE) {
- if (this.type == KeyLocatorType.KEY) {
- if(LOG>5)console.log('About to encode a public key' +this.publicKey);
- encoder.writeElement(CCNProtocolDTags.Key, this.publicKey);
-
- } else if (this.type == KeyLocatorType.CERTIFICATE) {
-
- try {
- encoder.writeElement(CCNProtocolDTags.Certificate, this.certificate);
- } catch ( e) {
- throw new Error("CertificateEncodingException attempting to write key locator: " + e);
- }
-
- } else if (this.type == KeyLocatorType.KEYNAME) {
-
- this.keyName.to_ccnb(encoder);
+ try {
+ encoder.writeElement(CCNProtocolDTags.Certificate, this.certificate);
+ } catch ( e) {
+ throw new Error("CertificateEncodingException attempting to write key locator: " + e);
}
- encoder.writeEndElement();
+ } else if (this.type == KeyLocatorType.KEYNAME) {
+
+ this.keyName.to_ccnb(encoder);
+ }
+ encoder.writeEndElement();
+
};
KeyLocator.prototype.getElementLabel = function() {
@@ -2170,6 +2229,24 @@
// null signedInfo ok
return (null != this.contentName);
};
+
+KeyName.prototype.matches_name = function(/*Name*/ name) {
+ var i_name = this.contentName.components;
+ var o_name = name.components;
+
+ // The intrest name is longer than the name we are checking it against.
+ if (i_name.length > o_name.length)
+ return false;
+
+ // Check if at least one of given components doesn't match.
+ for (var i = 0; i < i_name.length; ++i) {
+ if (!DataUtils.arraysEqual(i_name[i], o_name[i]))
+ return false;
+ }
+
+ return true;
+}
+
/**
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
diff --git a/js/tools/build/ndn-js.js b/js/tools/build/ndn-js.js
index 9dc4b33..33b3faf 100644
--- a/js/tools/build/ndn-js.js
+++ b/js/tools/build/ndn-js.js
@@ -1,8 +1,8 @@
var Closure=function(){this.ndn_data=null;this.ndn_data_dirty=!1;this.timerID=-1};Closure.RESULT_ERR=-1;Closure.RESULT_OK=0;Closure.RESULT_REEXPRESS=1;Closure.RESULT_INTEREST_CONSUMED=2;Closure.RESULT_VERIFY=3;Closure.RESULT_FETCHKEY=4;Closure.UPCALL_FINAL=0;Closure.UPCALL_INTEREST=1;Closure.UPCALL_CONSUMED_INTEREST=2;Closure.UPCALL_CONTENT=3;Closure.UPCALL_INTEREST_TIMED_OUT=4;Closure.UPCALL_CONTENT_UNVERIFIED=5;Closure.UPCALL_CONTENT_BAD=6;Closure.prototype.upcall=function(){return Closure.RESULT_OK};
var UpcallInfo=function(a,b,c,d){this.ndn=a;this.interest=b;this.matchedComps=c;this.contentObject=d};UpcallInfo.prototype.toString=function(){var a="ndn = "+this.ndn,a=a+("\nInterest = "+this.interest),a=a+("\nmatchedComps = "+this.matchedComps);return a+="\nContentObject: "+this.contentObject};
var LOG=0,NDN=function NDN(b){b=b||{};this.transport=(b.getTransport||function(){return new WebSocketTransport})();this.getHostAndPort=b.getHostAndPort||this.transport.defaultGetHostAndPort;this.host=void 0!==b.host?b.host:"localhost";this.port=b.port||9696;this.readyStatus=NDN.UNOPEN;this.onopen=b.onopen||function(){3<LOG&&console.log("NDN connection established.")};this.onclose=b.onclose||function(){3<LOG&&console.log("NDN connection closed.")}};NDN.UNOPEN=0;NDN.OPENED=1;NDN.CLOSED=2;
-NDN.ccndIdFetcher="/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY";NDN.prototype.createRoute=function(a,b){this.host=a;this.port=b};NDN.PITTable=[];var PITEntry=function(a,b){this.interest=a;this.closure=b};NDN.getEntryForExpressedInterest=function(a){for(var b=null,c=0;c<NDN.PITTable.length;c++)if(NDN.PITTable[c].interest.matches_name(a)&&(null==b||NDN.PITTable[c].interest.name.components.length>b.interest.name.components.length))b=NDN.PITTable[c];return b};
-NDN.makeShuffledGetHostAndPort=function(a,b){a=a.slice(0,a.length);DataUtils.shuffle(a);return function(){return 0==a.length?null:{host:a.splice(0,1)[0],port:b}}};
+NDN.ccndIdFetcher="/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY";NDN.prototype.createRoute=function(a,b){this.host=a;this.port=b};NDN.KeyStore=[];var KeyStoreEntry=function(a,b,c){this.keyName=a;this.keyHex=b;this.rsaKey=c};NDN.getKeyByName=function(a){for(var b=null,c=0;c<NDN.KeyStore.length;c++)if(NDN.KeyStore[c].keyName.matches_name(a.contentName)&&(null==b||NDN.KeyStore[c].keyName.contentName.components.length>b.keyName.contentName.components.length))b=NDN.KeyStore[c];return b};NDN.PITTable=[];
+var PITEntry=function(a,b){this.interest=a;this.closure=b};NDN.getEntryForExpressedInterest=function(a){for(var b=null,c=0;c<NDN.PITTable.length;c++)if(NDN.PITTable[c].interest.matches_name(a)&&(null==b||NDN.PITTable[c].interest.name.components.length>b.interest.name.components.length))b=NDN.PITTable[c];return b};NDN.makeShuffledGetHostAndPort=function(a,b){a=a.slice(0,a.length);DataUtils.shuffle(a);return function(){return 0==a.length?null:{host:a.splice(0,1)[0],port:b}}};
NDN.prototype.expressInterest=function(a,b,c){a=new Interest(a);null!=c?(a.minSuffixComponents=c.minSuffixComponents,a.maxSuffixComponents=c.maxSuffixComponents,a.publisherPublicKeyDigest=c.publisherPublicKeyDigest,a.exclude=c.exclude,a.childSelector=c.childSelector,a.answerOriginKind=c.answerOriginKind,a.scope=c.scope,a.interestLifetime=c.interestLifetime):a.interestLifetime=4;null==this.host||null==this.port?null==this.getHostAndPort?console.log("ERROR: host OR port NOT SET"):this.connectAndExpressInterest(a,
b):this.transport.expressInterest(this,a,b)};NDN.prototype.registerPrefix=function(a,b,c){return this.transport.registerPrefix(this,a,b,c)};
NDN.prototype.connectAndExpressInterest=function(a,b){var c=this.getHostAndPort();if(null==c)console.log("ERROR: No more hosts from getHostAndPort"),this.host=null;else if(c.host==this.host&&c.port==this.port)console.log("ERROR: The host returned by getHostAndPort is not alive: "+this.host+":"+this.port);else{this.host=c.host;this.port=c.port;console.log("Trying host from getHostAndPort: "+this.host);c=new Interest(new Name(NDN.ccndIdFetcher));c.interestLifetime=4;var d=this,e=setTimeout(function(){console.log("Timeout waiting for host "+
@@ -13,12 +13,13 @@
console.log("NDN.ws.onmessage: buffer overflow. Accumulate received length: "+b.bufferOffset+". Current packet length: "+d.length+".");delete b.structureDecoder;delete b.buffer;b.structureDecoder=new BinaryXMLStructureDecoder;b.buffer=new Uint8Array(b.maxBufferSize);b.bufferOffset=0;return}b.buffer.set(d,b.bufferOffset);b.bufferOffset+=d.length;if(!b.structureDecoder.findElementEnd(b.buffer.subarray(0,b.bufferOffset))){3<LOG&&console.log("Incomplete packet received. Length "+d.length+". Wait for more input.");
return}3<LOG&&console.log("Complete packet received. Length "+d.length+". Start decoding.")}catch(e){console.log("NDN.ws.onmessage exception: "+e);return}c=new BinaryXMLDecoder(b.buffer);if(c.peekStartElement(CCNProtocolDTags.Interest)){3<LOG&&console.log("Interest packet received.");d=new Interest;d.from_ccnb(c);3<LOG&&console.log(d);var f=escape(d.name.getName());3<LOG&&console.log(f);var g=getEntryForRegisteredPrefix(f);null!=g&&(d=new UpcallInfo(a,d,0,null),g.closure.upcall(Closure.UPCALL_INTEREST,
d)==Closure.RESULT_INTEREST_CONSUMED&&null!=d.contentObject&&(g=encodeToBinaryContentObject(d.contentObject),d=new Uint8Array(g.length),d.set(g),b.ws.send(d.buffer)))}else if(c.peekStartElement(CCNProtocolDTags.ContentObject))if(console.log("ContentObject packet received."),d=new ContentObject,d.from_ccnb(c),3<LOG&&console.log(d),f=d.name.getName(),console.log(f),null==b.ccndid&&null!=f.match(NDN.ccndIdFetcher))!d.signedInfo||!d.signedInfo.publisher||!d.signedInfo.publisher.publisherPublicKeyDigest?
-(console.log("Cannot contact router, close NDN now."),a.readyStatus=NDN.CLOSED,a.onclose()):(b.ccndid=d.signedInfo.publisher.publisherPublicKeyDigest,3<LOG&&console.log(b.ccndid),a.readyStatus=NDN.OPENED,a.onopen());else{if(g=NDN.getEntryForExpressedInterest(d.name),null!=g){var h=NDN.PITTable.indexOf(g);0<=h&&NDN.PITTable.splice(h,1);g=g.closure;clearTimeout(g.timerID);var j=!1,k=function(a,b,c,d){this.contentObject=a;this.closure=b;this.keyName=c;this.signature=d;Closure.call(this)};k.prototype.upcall=
-function(b,c){if(b==Closure.UPCALL_INTEREST_TIMED_OUT)console.log("In KeyFetchClosure.upcall: interest time out.");else if(b==Closure.UPCALL_CONTENT){console.log("In KeyFetchClosure.upcall");var d=DataUtils.toHex(c.contentObject.content).toLowerCase();console.log("Key: "+d);var e=d.slice(56,314),d=d.slice(318,324),f=new RSAKey;f.setPublic(e,d);j=f.verifyByteArray(this.contentObject.rawSignatureData,n);e=!0==j?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD;console.log("raise encapsulated closure");
-this.closure.upcall(e,new UpcallInfo(a,null,0,this.contentObject))}};if(d.signedInfo&&d.signedInfo.locator&&d.signature){3<LOG&&console.log("Key verification...");var n=DataUtils.toHex(d.signature.signature).toLowerCase(),h=d.signedInfo.locator;if(h.type==KeyLocatorType.KEYNAME){console.log("KeyLocator contains KEYNAME");var m=h.keyName.contentName.getName();console.log(m);f.match("/ccnx.org/Users/")?(console.log("Key found"),g.upcall(Closure.UPCALL_CONTENT,new UpcallInfo(a,null,0,d))):(console.log("Fetch key according to keylocator"),
-g=new k(d,g,m,n),d=new Interest(h.keyName.contentName.getPrefix(4)),d.interestLifetime=4,b.expressInterest(a,d,g))}else h.type==KeyLocatorType.KEY?(console.log("Keylocator contains KEY"),h=DataUtils.toHex(d.signedInfo.locator.publicKey).toLowerCase(),console.log(h),f=h.slice(56,314),h=h.slice(318,324),k=new RSAKey,k.setPublic(f,h),j=k.verifyByteArray(d.rawSignatureData,n),g.upcall(Closure.UPCALL_CONTENT,new UpcallInfo(a,null,0,d))):(d=h.certificate,console.log("KeyLocator contains CERT"),console.log(d))}}}else console.log("Incoming packet is not Interest or ContentObject. Discard now.");
-delete c;delete b.structureDecoder;delete b.buffer;b.structureDecoder=new BinaryXMLStructureDecoder;b.buffer=new Uint8Array(b.maxBufferSize);b.bufferOffset=0}};this.ws.onopen=function(a){3<LOG&&console.log(a);3<LOG&&console.log("ws.onopen: WebSocket connection opened.");3<LOG&&console.log("ws.onopen: ReadyState: "+this.readyState);a=new Interest(new Name(NDN.ccndIdFetcher));a.interestLifetime=4;var a=encodeToBinaryInterest(a),d=new Uint8Array(a.length);d.set(a);b.ws.send(d.buffer)};this.ws.onerror=
-function(a){console.log("ws.onerror: ReadyState: "+this.readyState);console.log(a);console.log("ws.onerror: WebSocket error: "+a.data)};this.ws.onclose=function(){console.log("ws.onclose: WebSocket connection closed.");b.ws=null;a.readyStatus=NDN.CLOSED;a.onclose()}};
+(console.log("Cannot contact router, close NDN now."),a.readyStatus=NDN.CLOSED,a.onclose()):(b.ccndid=d.signedInfo.publisher.publisherPublicKeyDigest,3<LOG&&console.log(b.ccndid),a.readyStatus=NDN.OPENED,a.onopen());else{if(g=NDN.getEntryForExpressedInterest(d.name),null!=g){var h=NDN.PITTable.indexOf(g);0<=h&&NDN.PITTable.splice(h,1);h=g.closure;clearTimeout(h.timerID);var j=!1,k=function(a,b,c,d){this.contentObject=a;this.closure=b;this.keyName=c;this.signature=d;Closure.call(this)};k.prototype.upcall=
+function(b,c){if(b==Closure.UPCALL_INTEREST_TIMED_OUT)console.log("In KeyFetchClosure.upcall: interest time out.");else if(b==Closure.UPCALL_CONTENT){console.log("In KeyFetchClosure.upcall: signature verification passed");var d=DataUtils.toHex(c.contentObject.content).toLowerCase();console.log("Key: "+d);var e=d.slice(56,314),d=d.slice(318,324),f=new RSAKey;f.setPublic(e,d);e=!0==f.verifyByteArray(this.contentObject.rawSignatureData,this.signature)?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD;
+console.log("raise encapsulated closure");this.closure.upcall(e,new UpcallInfo(a,null,0,this.contentObject))}};if(d.signedInfo&&d.signedInfo.locator&&d.signature)if(3<LOG&&console.log("Key verification..."),j=DataUtils.toHex(d.signature.signature).toLowerCase(),g=d.signedInfo.locator,g.type==KeyLocatorType.KEYNAME){console.log("KeyLocator contains KEYNAME");var m=g.keyName.contentName.getName();console.log(m);if(f.match(m)){console.log("Content is key itself");k=DataUtils.toHex(d.content).toLowerCase();
+console.log("Key content: "+k);var m=k.slice(56,314),n=k.slice(318,324),f=new RSAKey;f.setPublic(m,n);j=f.verifyByteArray(d.rawSignatureData,j);j=!0==j?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD;h.upcall(j,new UpcallInfo(a,null,0,d));f=new KeyStoreEntry(g.keyName,k,f);NDN.KeyStore.push(f)}else console.log("Fetch key according to keylocator"),(f=NDN.getKeyByName(g.keyName))?(console.log("Local key cache hit"),f=f.rsaKey,j=f.verifyByteArray(d.rawSignatureData,j),j=!0==j?Closure.UPCALL_CONTENT:
+Closure.UPCALL_CONTENT_BAD,h.upcall(Closure.UPCALL_CONTENT,new UpcallInfo(a,null,0,d))):(h=new k(d,h,m,j),d=new Interest(g.keyName.contentName.getPrefix(4)),d.interestLifetime=4,b.expressInterest(a,d,h))}else g.type==KeyLocatorType.KEY?(console.log("Keylocator contains KEY"),k=DataUtils.toHex(g.publicKey).toLowerCase(),console.log(k),m=k.slice(56,314),n=k.slice(318,324),f=new RSAKey,f.setPublic(m,n),j=f.verifyByteArray(d.rawSignatureData,j),j=!0==j?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD,
+h.upcall(Closure.UPCALL_CONTENT,new UpcallInfo(a,null,0,d)),f=new KeyStoreEntry(g.keyName,k,f),NDN.KeyStore.push(f)):(d=g.certificate,console.log("KeyLocator contains CERT"),console.log(d))}}else console.log("Incoming packet is not Interest or ContentObject. Discard now.");delete c;delete b.structureDecoder;delete b.buffer;b.structureDecoder=new BinaryXMLStructureDecoder;b.buffer=new Uint8Array(b.maxBufferSize);b.bufferOffset=0}};this.ws.onopen=function(a){3<LOG&&console.log(a);3<LOG&&console.log("ws.onopen: WebSocket connection opened.");
+3<LOG&&console.log("ws.onopen: ReadyState: "+this.readyState);a=new Interest(new Name(NDN.ccndIdFetcher));a.interestLifetime=4;var a=encodeToBinaryInterest(a),d=new Uint8Array(a.length);d.set(a);b.ws.send(d.buffer)};this.ws.onerror=function(a){console.log("ws.onerror: ReadyState: "+this.readyState);console.log(a);console.log("ws.onerror: WebSocket error: "+a.data)};this.ws.onclose=function(){console.log("ws.onclose: WebSocket connection closed.");b.ws=null;a.readyStatus=NDN.CLOSED;a.onclose()}};
WebSocketTransport.prototype.expressInterest=function(a,b,c){if(null!=this.ws){var d=encodeToBinaryInterest(b),e=new Uint8Array(d.length);e.set(d);var f=new PITEntry(b,c);NDN.PITTable.push(f);this.ws.send(e.buffer);3<LOG&&console.log("ws.send() returned.");c.timerID=setTimeout(function(){3<LOG&&console.log("Interest time out.");var d=NDN.PITTable.indexOf(f);0<=d&&NDN.PITTable.splice(d,1);c.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,new UpcallInfo(a,b,0,null))},1E3*b.interestLifetime)}else console.log("WebSocket connection is not established.")};
var CSTable=[],CSEntry=function(a,b){this.name=a;this.closure=b};function getEntryForRegisteredPrefix(a){for(var b=0;b<CSTable.length;b++)if(null!=CSTable[b].name.match(a))return CSTable[b];return null}
WebSocketTransport.prototype.registerPrefix=function(a,b,c){if(null!=this.ws){if(null==this.ccndid)return console.log("ccnd node ID unkonwn. Cannot register prefix."),-1;var a=new ForwardingEntry("selfreg",b,null,null,3,2147483647),a=encodeForwardingEntry(a),d=new SignedInfo;d.setFields();a=new ContentObject(new Name,d,a,new Signature);a.sign();a=encodeToBinaryContentObject(a);a=new Name(["ccnx",this.ccndid,"selfreg",a]);a=new Interest(a);a.scope=1;d=encodeToBinaryInterest(a);a=new Uint8Array(d.length);
@@ -60,10 +61,10 @@
SignedInfo.prototype.to_ccnb=function(a){if(!this.validate())throw Error("Cannot encode : field values missing.");a.writeStartElement(this.getElementLabel());null!=this.publisher&&(3<LOG&&console.log("ENCODING PUBLISHER KEY"+this.publisher.publisherPublicKeyDigest),this.publisher.to_ccnb(a));null!=this.timestamp&&a.writeDateTime(CCNProtocolDTags.Timestamp,this.timestamp);null!=this.type&&0!=this.type&&a.writeElement(CCNProtocolDTags.type,this.type);null!=this.freshnessSeconds&&a.writeElement(CCNProtocolDTags.FreshnessSeconds,
this.freshnessSeconds);null!=this.finalBlockID&&a.writeElement(CCNProtocolDTags.FinalBlockID,this.finalBlockID);null!=this.locator&&this.locator.to_ccnb(a);a.writeEndElement()};SignedInfo.prototype.valueToType=function(){return null};SignedInfo.prototype.getElementLabel=function(){return CCNProtocolDTags.SignedInfo};SignedInfo.prototype.validate=function(){return null==this.publisher||null==this.timestamp||null==this.locator?!1:!0};
var DateFormat=function(){var a=/d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,b=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,c=/[^-+\dA-Z]/g,d=function(a,b){a=String(a);for(b=b||2;a.length<b;)a="0"+a;return a};return function(e,f,g){var h=dateFormat;1==arguments.length&&("[object String]"==Object.prototype.toString.call(e)&&!/\d/.test(e))&&(f=e,e=void 0);e=e?new Date(e):new Date;if(isNaN(e))throw SyntaxError("invalid date");
-f=String(h.masks[f]||f||h.masks["default"]);"UTC:"==f.slice(0,4)&&(f=f.slice(4),g=!0);var j=g?"getUTC":"get",k=e[j+"Date"](),n=e[j+"Day"](),m=e[j+"Month"](),p=e[j+"FullYear"](),l=e[j+"Hours"](),q=e[j+"Minutes"](),s=e[j+"Seconds"](),j=e[j+"Milliseconds"](),r=g?0:e.getTimezoneOffset(),t={d:k,dd:d(k),ddd:h.i18n.dayNames[n],dddd:h.i18n.dayNames[n+7],m:m+1,mm:d(m+1),mmm:h.i18n.monthNames[m],mmmm:h.i18n.monthNames[m+12],yy:String(p).slice(2),yyyy:p,h:l%12||12,hh:d(l%12||12),H:l,HH:d(l),M:q,MM:d(q),s:s,
+f=String(h.masks[f]||f||h.masks["default"]);"UTC:"==f.slice(0,4)&&(f=f.slice(4),g=!0);var j=g?"getUTC":"get",k=e[j+"Date"](),m=e[j+"Day"](),n=e[j+"Month"](),p=e[j+"FullYear"](),l=e[j+"Hours"](),q=e[j+"Minutes"](),s=e[j+"Seconds"](),j=e[j+"Milliseconds"](),r=g?0:e.getTimezoneOffset(),t={d:k,dd:d(k),ddd:h.i18n.dayNames[m],dddd:h.i18n.dayNames[m+7],m:n+1,mm:d(n+1),mmm:h.i18n.monthNames[n],mmmm:h.i18n.monthNames[n+12],yy:String(p).slice(2),yyyy:p,h:l%12||12,hh:d(l%12||12),H:l,HH:d(l),M:q,MM:d(q),s:s,
ss:d(s),l:d(j,3),L:d(99<j?Math.round(j/10):j),t:12>l?"a":"p",tt:12>l?"am":"pm",T:12>l?"A":"P",TT:12>l?"AM":"PM",Z:g?"UTC":(String(e).match(b)||[""]).pop().replace(c,""),o:(0<r?"-":"+")+d(100*Math.floor(Math.abs(r)/60)+Math.abs(r)%60,4),S:["th","st","nd","rd"][3<k%10?0:(10!=k%100-k%10)*k%10]};return f.replace(a,function(a){return a in t?t[a]:a.slice(1,a.length-1)})}}();
DateFormat.masks={"default":"ddd mmm dd yyyy HH:MM:ss",shortDate:"m/d/yy",mediumDate:"mmm d, yyyy",longDate:"mmmm d, yyyy",fullDate:"dddd, mmmm d, yyyy",shortTime:"h:MM TT",mediumTime:"h:MM:ss TT",longTime:"h:MM:ss TT Z",isoDate:"yyyy-mm-dd",isoTime:"HH:MM:ss",isoDateTime:"yyyy-mm-dd'T'HH:MM:ss",isoUtcDateTime:"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"};DateFormat.i18n={dayNames:"Sun Mon Tue Wed Thu Fri Sat Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),monthNames:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December".split(" ")};
-Date.prototype.format=function(a,b){return dateFormat(this,a,b)};var Interest=function(a,b,c,d,e,f,g,h,j,k,n){this.name=a;this.faceInstance=b;this.maxSuffixComponents=d;this.minSuffixComponents=c;this.publisherPublicKeyDigest=e;this.exclude=f;this.childSelector=g;this.answerOriginKind=h;this.scope=j;this.interestLifetime=k;this.nonce=n};Interest.RECURSIVE_POSTFIX="*";Interest.CHILD_SELECTOR_LEFT=0;Interest.CHILD_SELECTOR_RIGHT=1;Interest.ANSWER_CONTENT_STORE=1;Interest.ANSWER_GENERATED=2;
+Date.prototype.format=function(a,b){return dateFormat(this,a,b)};var Interest=function(a,b,c,d,e,f,g,h,j,k,m){this.name=a;this.faceInstance=b;this.maxSuffixComponents=d;this.minSuffixComponents=c;this.publisherPublicKeyDigest=e;this.exclude=f;this.childSelector=g;this.answerOriginKind=h;this.scope=j;this.interestLifetime=k;this.nonce=m};Interest.RECURSIVE_POSTFIX="*";Interest.CHILD_SELECTOR_LEFT=0;Interest.CHILD_SELECTOR_RIGHT=1;Interest.ANSWER_CONTENT_STORE=1;Interest.ANSWER_GENERATED=2;
Interest.ANSWER_STALE=4;Interest.MARK_STALE=16;Interest.DEFAULT_ANSWER_ORIGIN_KIND=Interest.ANSWER_CONTENT_STORE|Interest.ANSWER_GENERATED;
Interest.prototype.from_ccnb=function(a){a.readStartElement(CCNProtocolDTags.Interest);this.name=new Name;this.name.from_ccnb(a);a.peekStartElement(CCNProtocolDTags.MinSuffixComponents)&&(this.minSuffixComponents=a.readIntegerElement(CCNProtocolDTags.MinSuffixComponents));a.peekStartElement(CCNProtocolDTags.MaxSuffixComponents)&&(this.maxSuffixComponents=a.readIntegerElement(CCNProtocolDTags.MaxSuffixComponents));a.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)&&(this.publisherPublicKeyDigest=
new PublisherPublicKeyDigest,this.publisherPublicKeyDigest.from_ccnb(a));a.peekStartElement(CCNProtocolDTags.Exclude)&&(this.exclude=new Exclude,this.exclude.from_ccnb(a));a.peekStartElement(CCNProtocolDTags.ChildSelector)&&(this.childSelector=a.readIntegerElement(CCNProtocolDTags.ChildSelector));a.peekStartElement(CCNProtocolDTags.AnswerOriginKind)&&(this.answerOriginKind=a.readIntegerElement(CCNProtocolDTags.AnswerOriginKind));a.peekStartElement(CCNProtocolDTags.Scope)&&(this.scope=a.readIntegerElement(CCNProtocolDTags.Scope));
@@ -80,6 +81,7 @@
b);}else this.type==KeyLocatorType.KEYNAME&&this.keyName.to_ccnb(a);a.writeEndElement()};KeyLocator.prototype.getElementLabel=function(){return CCNProtocolDTags.KeyLocator};KeyLocator.prototype.validate=function(){return null!=this.keyName||null!=this.publicKey||null!=this.certificate};var KeyName=function(){this.contentName=this.contentName;this.publisherID=this.publisherID};
KeyName.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());this.contentName=new Name;this.contentName.from_ccnb(a);4<LOG&&console.log("KEY NAME FOUND: ");PublisherID.peek(a)&&(this.publisherID=new PublisherID,this.publisherID.from_ccnb(a));a.readEndElement()};
KeyName.prototype.to_ccnb=function(a){if(!this.validate())throw Error("Cannot encode : field values missing.");a.writeStartElement(this.getElementLabel());this.contentName.to_ccnb(a);null!=this.publisherID&&this.publisherID.to_ccnb(a);a.writeEndElement()};KeyName.prototype.getElementLabel=function(){return CCNProtocolDTags.KeyName};KeyName.prototype.validate=function(){return null!=this.contentName};
+KeyName.prototype.matches_name=function(a){var b=this.contentName.components,a=a.components;if(b.length>a.length)return!1;for(var c=0;c<b.length;++c)if(!DataUtils.arraysEqual(b[c],a[c]))return!1;return!0};
var PublisherType=function(a){this.KEY=CCNProtocolDTags.PublisherPublicKeyDigest;this.CERTIFICATE=CCNProtocolDTags.PublisherCertificateDigest;this.ISSUER_KEY=CCNProtocolDTags.PublisherIssuerKeyDigest;this.ISSUER_CERTIFICATE=CCNProtocolDTags.PublisherIssuerCertificateDigest;this.Tag=a},isTypeTagVal=function(a){return a==CCNProtocolDTags.PublisherPublicKeyDigest||a==CCNProtocolDTags.PublisherCertificateDigest||a==CCNProtocolDTags.PublisherIssuerKeyDigest||a==CCNProtocolDTags.PublisherIssuerCertificateDigest?
!0:!1},PublisherID=function(){this.PUBLISHER_ID_DIGEST_ALGORITHM="SHA-256";this.PUBLISHER_ID_LEN=32;this.publisherType=this.publisherID=null};
PublisherID.prototype.from_ccnb=function(a){var b=a.peekStartElementAsLong();if(null==b)throw Error("Cannot parse publisher ID.");this.publisherType=new PublisherType(b);if(!isTypeTagVal(b))throw Error("Invalid publisher ID, got unexpected type: "+b);this.publisherID=a.readBinaryElement(b);if(null==this.publisherID)throw new ContentDecodingException(Error("Cannot parse publisher ID of type : "+b+"."));};
@@ -167,8 +169,8 @@
function sha256_Gamma1512(a){return sha256_S(a,19)^sha256_S(a,61)^sha256_R(a,6)}
var sha256_K=[1116352408,1899447441,-1245643825,-373957723,961987163,1508970993,-1841331548,-1424204075,-670586216,310598401,607225278,1426881987,1925078388,-2132889090,-1680079193,-1046744716,-459576895,-272742522,264347078,604807628,770255983,1249150122,1555081692,1996064986,-1740746414,-1473132947,-1341970488,-1084653625,-958395405,-710438585,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,-2117940946,-1838011259,-1564481375,-1474664885,-1035236496,-949202525,
-778901479,-694614492,-200395387,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,-2067236844,-1933114872,-1866530822,-1538233109,-1090935817,-965641998];function binb_sha256(a,b){var c=[1779033703,-1150833019,1013904242,-1521486534,1359893119,-1694144372,528734635,1541459225],d=Array(64);a[b>>5]|=128<<24-b%32;a[(b+64>>9<<4)+15]=b;for(var e=0;e<a.length;e+=16)processBlock_sha256(a,e,c,d);return c}
-function processBlock_sha256(a,b,c,d){var e,f,g,h,j,k,n,m,p,l,q;e=c[0];f=c[1];g=c[2];h=c[3];j=c[4];k=c[5];n=c[6];m=c[7];for(p=0;64>p;p++)d[p]=16>p?a[p+b]:safe_add(safe_add(safe_add(sha256_Gamma1256(d[p-2]),d[p-7]),sha256_Gamma0256(d[p-15])),d[p-16]),l=safe_add(safe_add(safe_add(safe_add(m,sha256_Sigma1256(j)),sha256_Ch(j,k,n)),sha256_K[p]),d[p]),q=safe_add(sha256_Sigma0256(e),sha256_Maj(e,f,g)),m=n,n=k,k=j,j=safe_add(h,l),h=g,g=f,f=e,e=safe_add(l,q);c[0]=safe_add(e,c[0]);c[1]=safe_add(f,c[1]);c[2]=
-safe_add(g,c[2]);c[3]=safe_add(h,c[3]);c[4]=safe_add(j,c[4]);c[5]=safe_add(k,c[5]);c[6]=safe_add(n,c[6]);c[7]=safe_add(m,c[7])}function safe_add(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535}var Sha256=function(){this.W=Array(64);this.hash=[1779033703,-1150833019,1013904242,-1521486534,1359893119,-1694144372,528734635,1541459225];this.nTotalBytes=0;this.buffer=new Uint8Array(64);this.nBufferBytes=0};
+function processBlock_sha256(a,b,c,d){var e,f,g,h,j,k,m,n,p,l,q;e=c[0];f=c[1];g=c[2];h=c[3];j=c[4];k=c[5];m=c[6];n=c[7];for(p=0;64>p;p++)d[p]=16>p?a[p+b]:safe_add(safe_add(safe_add(sha256_Gamma1256(d[p-2]),d[p-7]),sha256_Gamma0256(d[p-15])),d[p-16]),l=safe_add(safe_add(safe_add(safe_add(n,sha256_Sigma1256(j)),sha256_Ch(j,k,m)),sha256_K[p]),d[p]),q=safe_add(sha256_Sigma0256(e),sha256_Maj(e,f,g)),n=m,m=k,k=j,j=safe_add(h,l),h=g,g=f,f=e,e=safe_add(l,q);c[0]=safe_add(e,c[0]);c[1]=safe_add(f,c[1]);c[2]=
+safe_add(g,c[2]);c[3]=safe_add(h,c[3]);c[4]=safe_add(j,c[4]);c[5]=safe_add(k,c[5]);c[6]=safe_add(m,c[6]);c[7]=safe_add(n,c[7])}function safe_add(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535}var Sha256=function(){this.W=Array(64);this.hash=[1779033703,-1150833019,1013904242,-1521486534,1359893119,-1694144372,528734635,1541459225];this.nTotalBytes=0;this.buffer=new Uint8Array(64);this.nBufferBytes=0};
Sha256.prototype.update=function(a){this.nTotalBytes+=a.length;if(0<this.nBufferBytes){var b=this.buffer.length-this.nBufferBytes;if(a.length<b){this.buffer.set(a,this.nBufferBytes);this.nBufferBytes+=a.length;return}this.buffer.set(a.subarray(0,b),this.nBufferBytes);processBlock_sha256(byteArray2binb(this.buffer),0,this.hash,this.W);this.nBufferBytes=0;a=a.subarray(b,a.length);if(0==a.length)return}b=a.length>>6;if(0<b){for(var b=64*b,c=byteArray2binb(a.subarray(0,b)),d=0;d<c.length;d+=16)processBlock_sha256(c,
d,this.hash,this.W);a=a.subarray(b,a.length)}0<a.length&&(this.buffer.set(a),this.nBufferBytes=a.length)};Sha256.prototype.finalize=function(){var a=byteArray2binb(this.buffer.subarray(0,this.nBufferBytes)),b=8*this.nBufferBytes;a[b>>5]|=128<<24-b%32;a[(b+64>>9<<4)+15]=8*this.nTotalBytes;for(b=0;b<a.length;b+=16)processBlock_sha256(a,b,this.hash,this.W);return Sha256.binb2Uint8Array(this.hash)};
Sha256.binb2Uint8Array=function(a){for(var b=new Uint8Array(4*a.length),c=0,d=0;d<32*a.length;d+=8)b[c++]=a[d>>5]>>>24-d%32&255;return b};var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b64pad="=";
@@ -217,8 +219,8 @@
function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)b.t=0;else{var d=a%this.DB,e=this.DB-d,f=(1<<d)-1;b[0]=this[c]>>d;for(var g=c+1;g<this.t;++g)b[g-c-1]|=(this[g]&f)<<e,b[g-c]=this[g]>>d;0<d&&(b[this.t-c-1]|=(this.s&f)<<e);b.t=this.t-c;b.clamp()}}
function bnpSubTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d-=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d-=a[c],b[c++]=d&this.DM,d>>=this.DB;d-=a.s}b.s=0>d?-1:0;-1>d?b[c++]=this.DV+d:0<d&&(b[c++]=d);b.t=c;b.clamp()}
function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;0<=--e;)b[e]=0;for(e=0;e<d.t;++e)b[e+c.t]=c.am(0,d[e],b,e,0,c.t);b.s=0;b.clamp();this.s!=a.s&&BigInteger.ZERO.subTo(b,b)}function bnpSquareTo(a){for(var b=this.abs(),c=a.t=2*b.t;0<=--c;)a[c]=0;for(c=0;c<b.t-1;++c){var d=b.am(c,b[c],a,2*c,0,1);if((a[c+b.t]+=b.am(c+1,2*b[c],a,2*c+1,d,b.t-c-1))>=b.DV)a[c+b.t]-=b.DV,a[c+b.t+1]=1}0<a.t&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1));a.s=0;a.clamp()}
-function bnpDivRemTo(a,b,c){var d=a.abs();if(!(0>=d.t)){var e=this.abs();if(e.t<d.t)null!=b&&b.fromInt(0),null!=c&&this.copyTo(c);else{null==c&&(c=nbi());var f=nbi(),g=this.s,a=a.s,h=this.DB-nbits(d[d.t-1]);0<h?(d.lShiftTo(h,f),e.lShiftTo(h,c)):(d.copyTo(f),e.copyTo(c));d=f.t;e=f[d-1];if(0!=e){var j=e*(1<<this.F1)+(1<d?f[d-2]>>this.F2:0),k=this.FV/j,j=(1<<this.F1)/j,n=1<<this.F2,m=c.t,p=m-d,l=null==b?nbi():b;f.dlShiftTo(p,l);0<=c.compareTo(l)&&(c[c.t++]=1,c.subTo(l,c));BigInteger.ONE.dlShiftTo(d,
-l);for(l.subTo(f,f);f.t<d;)f[f.t++]=0;for(;0<=--p;){var q=c[--m]==e?this.DM:Math.floor(c[m]*k+(c[m-1]+n)*j);if((c[m]+=f.am(0,q,c,p,0,d))<q){f.dlShiftTo(p,l);for(c.subTo(l,c);c[m]<--q;)c.subTo(l,c)}}null!=b&&(c.drShiftTo(d,b),g!=a&&BigInteger.ZERO.subTo(b,b));c.t=d;c.clamp();0<h&&c.rShiftTo(h,c);0>g&&BigInteger.ZERO.subTo(c,c)}}}}function bnMod(a){var b=nbi();this.abs().divRemTo(a,null,b);0>this.s&&0<b.compareTo(BigInteger.ZERO)&&a.subTo(b,b);return b}function Classic(a){this.m=a}
+function bnpDivRemTo(a,b,c){var d=a.abs();if(!(0>=d.t)){var e=this.abs();if(e.t<d.t)null!=b&&b.fromInt(0),null!=c&&this.copyTo(c);else{null==c&&(c=nbi());var f=nbi(),g=this.s,a=a.s,h=this.DB-nbits(d[d.t-1]);0<h?(d.lShiftTo(h,f),e.lShiftTo(h,c)):(d.copyTo(f),e.copyTo(c));d=f.t;e=f[d-1];if(0!=e){var j=e*(1<<this.F1)+(1<d?f[d-2]>>this.F2:0),k=this.FV/j,j=(1<<this.F1)/j,m=1<<this.F2,n=c.t,p=n-d,l=null==b?nbi():b;f.dlShiftTo(p,l);0<=c.compareTo(l)&&(c[c.t++]=1,c.subTo(l,c));BigInteger.ONE.dlShiftTo(d,
+l);for(l.subTo(f,f);f.t<d;)f[f.t++]=0;for(;0<=--p;){var q=c[--n]==e?this.DM:Math.floor(c[n]*k+(c[n-1]+m)*j);if((c[n]+=f.am(0,q,c,p,0,d))<q){f.dlShiftTo(p,l);for(c.subTo(l,c);c[n]<--q;)c.subTo(l,c)}}null!=b&&(c.drShiftTo(d,b),g!=a&&BigInteger.ZERO.subTo(b,b));c.t=d;c.clamp();0<h&&c.rShiftTo(h,c);0>g&&BigInteger.ZERO.subTo(c,c)}}}}function bnMod(a){var b=nbi();this.abs().divRemTo(a,null,b);0>this.s&&0<b.compareTo(BigInteger.ZERO)&&a.subTo(b,b);return b}function Classic(a){this.m=a}
function cConvert(a){return 0>a.s||0<=a.compareTo(this.m)?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}function cSqrTo(a,b){a.squareTo(b);this.reduce(b)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;
function bnpInvDigit(){if(1>this.t)return 0;var a=this[0];if(0==(a&1))return 0;var b=a&3,b=b*(2-(a&15)*b)&15,b=b*(2-(a&255)*b)&255,b=b*(2-((a&65535)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV;return 0<b?this.DV-b:-b}function Montgomery(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<a.DB-15)-1;this.mt2=2*a.t}
function montConvert(a){var b=nbi();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);0>a.s&&0<b.compareTo(BigInteger.ZERO)&&this.m.subTo(b,b);return b}function montRevert(a){var b=nbi();a.copyTo(b);this.reduce(b);return b}
@@ -242,8 +244,8 @@
function Barrett(a){this.r2=nbi();this.q3=nbi();BigInteger.ONE.dlShiftTo(2*a.t,this.r2);this.mu=this.r2.divide(a);this.m=a}function barrettConvert(a){if(0>a.s||a.t>2*this.m.t)return a.mod(this.m);if(0>a.compareTo(this.m))return a;var b=nbi();a.copyTo(b);this.reduce(b);return b}function barrettRevert(a){return a}
function barrettReduce(a){a.drShiftTo(this.m.t-1,this.r2);a.t>this.m.t+1&&(a.t=this.m.t+1,a.clamp());this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);for(this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);0>a.compareTo(this.r2);)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);0<=a.compareTo(this.m);)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b);this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Barrett.prototype.convert=barrettConvert;
Barrett.prototype.revert=barrettRevert;Barrett.prototype.reduce=barrettReduce;Barrett.prototype.mulTo=barrettMulTo;Barrett.prototype.sqrTo=barrettSqrTo;
-function bnModPow(a,b){var c=a.bitLength(),d,e=nbv(1),f;if(0>=c)return e;d=18>c?1:48>c?3:144>c?4:768>c?5:6;f=8>c?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var g=[],h=3,j=d-1,k=(1<<d)-1;g[1]=f.convert(this);if(1<d){c=nbi();for(f.sqrTo(g[1],c);h<=k;)g[h]=nbi(),f.mulTo(c,g[h-2],g[h]),h+=2}for(var n=a.t-1,m,p=!0,l=nbi(),c=nbits(a[n])-1;0<=n;){c>=j?m=a[n]>>c-j&k:(m=(a[n]&(1<<c+1)-1)<<j-c,0<n&&(m|=a[n-1]>>this.DB+c-j));for(h=d;0==(m&1);)m>>=1,--h;if(0>(c-=h))c+=this.DB,--n;if(p)g[m].copyTo(e),
-p=!1;else{for(;1<h;)f.sqrTo(e,l),f.sqrTo(l,e),h-=2;0<h?f.sqrTo(e,l):(h=e,e=l,l=h);f.mulTo(l,g[m],e)}for(;0<=n&&0==(a[n]&1<<c);)f.sqrTo(e,l),h=e,e=l,l=h,0>--c&&(c=this.DB-1,--n)}return f.revert(e)}
+function bnModPow(a,b){var c=a.bitLength(),d,e=nbv(1),f;if(0>=c)return e;d=18>c?1:48>c?3:144>c?4:768>c?5:6;f=8>c?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var g=[],h=3,j=d-1,k=(1<<d)-1;g[1]=f.convert(this);if(1<d){c=nbi();for(f.sqrTo(g[1],c);h<=k;)g[h]=nbi(),f.mulTo(c,g[h-2],g[h]),h+=2}for(var m=a.t-1,n,p=!0,l=nbi(),c=nbits(a[m])-1;0<=m;){c>=j?n=a[m]>>c-j&k:(n=(a[m]&(1<<c+1)-1)<<j-c,0<m&&(n|=a[m-1]>>this.DB+c-j));for(h=d;0==(n&1);)n>>=1,--h;if(0>(c-=h))c+=this.DB,--m;if(p)g[n].copyTo(e),
+p=!1;else{for(;1<h;)f.sqrTo(e,l),f.sqrTo(l,e),h-=2;0<h?f.sqrTo(e,l):(h=e,e=l,l=h);f.mulTo(l,g[n],e)}for(;0<=m&&0==(a[m]&1<<c);)f.sqrTo(e,l),h=e,e=l,l=h,0>--c&&(c=this.DB-1,--m)}return f.revert(e)}
function bnGCD(a){var b=0>this.s?this.negate():this.clone(),a=0>a.s?a.negate():a.clone();if(0>b.compareTo(a))var c=b,b=a,a=c;var c=b.getLowestSetBit(),d=a.getLowestSetBit();if(0>d)return b;c<d&&(d=c);0<d&&(b.rShiftTo(d,b),a.rShiftTo(d,a));for(;0<b.signum();)0<(c=b.getLowestSetBit())&&b.rShiftTo(c,b),0<(c=a.getLowestSetBit())&&a.rShiftTo(c,a),0<=b.compareTo(a)?(b.subTo(a,b),b.rShiftTo(1,b)):(a.subTo(b,a),a.rShiftTo(1,a));0<d&&a.lShiftTo(d,a);return a}
function bnpModInt(a){if(0>=a)return 0;var b=this.DV%a,c=0>this.s?a-1:0;if(0<this.t)if(0==b)c=this[0]%a;else for(var d=this.t-1;0<=d;--d)c=(b*c+this[d])%a;return c}
function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),f=nbv(0),g=nbv(0),h=nbv(1);0!=c.signum();){for(;c.isEven();){c.rShiftTo(1,c);if(b){if(!e.isEven()||!f.isEven())e.addTo(this,e),f.subTo(a,f);e.rShiftTo(1,e)}else f.isEven()||f.subTo(a,f);f.rShiftTo(1,f)}for(;d.isEven();){d.rShiftTo(1,d);if(b){if(!g.isEven()||!h.isEven())g.addTo(this,g),h.subTo(a,h);g.rShiftTo(1,g)}else h.isEven()||h.subTo(a,h);h.rShiftTo(1,