diff --git a/gui/html/js/ndn-js.js b/gui/html/js/ndn-js.js
index 63f1fef..9408f0c 100644
--- a/gui/html/js/ndn-js.js
+++ b/gui/html/js/ndn-js.js
@@ -1,5017 +1,1679 @@
-/**
- * @author: Jeff Thompson
- * See COPYING for copyright and distribution information.
- * Provide the callback closure for the async communication methods in the NDN class.
- * This is a port of Closure.py from PyNDN, written by: 
- * Derek Kulinski <takeda@takeda.tk>
- * Jeff Burke <jburke@ucla.edu>
- */
-
-/*
- * Create a subclass of Closure and pass an object to async calls.
- */
-var Closure = function Closure() {
-	// I don't think storing NDN's closure is needed
-	// and it creates a reference loop, as of now both
-	// of those variables are never set -- Derek
-	//
-	// Use instance variables to return data to callback
-	this.ndn_data = null;  // this holds the ndn_closure
-    this.ndn_data_dirty = false;
-    
-};
-
-// Upcall result
-Closure.RESULT_ERR               = -1; // upcall detected an error
-Closure.RESULT_OK                =  0; // normal upcall return
-Closure.RESULT_REEXPRESS         =  1; // reexpress the same interest again
-Closure.RESULT_INTEREST_CONSUMED =  2; // upcall claims to consume interest
-Closure.RESULT_VERIFY            =  3; // force an unverified result to be verified
-Closure.RESULT_FETCHKEY          =  4; // get the key in the key locator and re-call the interest
-                                       //   with the key available in the local storage
-
-// Upcall kind
-Closure.UPCALL_FINAL              = 0; // handler is about to be deregistered
-Closure.UPCALL_INTEREST           = 1; // incoming interest
-Closure.UPCALL_CONSUMED_INTEREST  = 2; // incoming interest, someone has answered
-Closure.UPCALL_CONTENT            = 3; // incoming verified content
-Closure.UPCALL_INTEREST_TIMED_OUT = 4; // interest timed out
-Closure.UPCALL_CONTENT_UNVERIFIED = 5; // content that has not been verified
-Closure.UPCALL_CONTENT_BAD        = 6; // verification failed
-
-/*
- * Override this in your subclass.
- * If you're getting strange errors in upcall()
- * check your code whether you're returning a value.
- */
-Closure.prototype.upcall = function(kind, upcallInfo) {
-	//dump('upcall ' + this + " " + kind + " " + upcallInfo + "\n");
-	return Closure.RESULT_OK;
-};
-
-var UpcallInfo = function UpcallInfo(ndn, interest, matchedComps, contentObject) {
-	this.ndn = ndn;  // NDN object (not used)
-	this.interest = interest;  // Interest object
-	this.matchedComps = matchedComps;  // int
-	this.contentObject = contentObject;  // Content object
-};
-
-UpcallInfo.prototype.toString = function() {
-	var ret = "ndn = " + this.ndn;
-	ret += "\nInterest = " + this.interest;
-	ret += "\nmatchedComps = " + this.matchedComps;
-	ret += "\nContentObject: " + this.contentObject;
-	return ret;
-}
-/** 
- * @author: Wentao Shang
- * See COPYING for copyright and distribution information.
- */
-
-var WebSocketTransport = function WebSocketTransport() {    
-    if (!WebSocket)
-        throw new Error("WebSocket support is not available on this platform.");
-    
-	this.ws = null;
-    this.connectedHost = null; // Read by NDN.
-    this.connectedPort = null; // Read by NDN.
-    this.elementReader = null;
-    this.defaultGetHostAndPort = NDN.makeShuffledGetHostAndPort
-        (["A.ws.ndn.ucla.edu", "B.ws.ndn.ucla.edu", "C.ws.ndn.ucla.edu", "D.ws.ndn.ucla.edu", 
-          "E.ws.ndn.ucla.edu"],
-         9696);
-};
-
-/*
- * Connect to the host and port in ndn.  This replaces a previous connection and sets connectedHost
- *   and connectedPort.  Once connected, call onopenCallback().
- * Listen on the port to read an entire binary XML encoded element and call
- *    ndn.onReceivedElement(element).
- */
-WebSocketTransport.prototype.connect = function(ndn, onopenCallback) {
-	if (this.ws != null)
-		delete this.ws;
-	
-	this.ws = new WebSocket('ws://' + ndn.host + ':' + ndn.port);
-	if (LOG > 0) console.log('ws connection created.');
-    this.connectedHost = ndn.host;
-    this.connectedPort = ndn.port;
-	
-	this.ws.binaryType = "arraybuffer";
-	
-    this.elementReader = new BinaryXmlElementReader(ndn);
-	var self = this;
-	this.ws.onmessage = function(ev) {
-		var result = ev.data;
-		//console.log('RecvHandle called.');
-			
-		if(result == null || result == undefined || result == "" ) {
-			console.log('INVALID ANSWER');
-		} else if (result instanceof ArrayBuffer) {
-	        var bytearray = new Uint8Array(result);
-	        
-			if (LOG>3) console.log('BINARY RESPONSE IS ' + DataUtils.toHex(bytearray));
-			
-			try {
-                // Find the end of the binary XML element and call ndn.onReceivedElement.
-                self.elementReader.onReceivedData(bytearray);
-			} catch (ex) {
-				console.log("NDN.ws.onmessage exception: " + ex);
-				return;
-			}
-		}
-	}
-	
-	this.ws.onopen = function(ev) {
-		if (LOG > 3) console.log(ev);
-		if (LOG > 3) console.log('ws.onopen: WebSocket connection opened.');
-		if (LOG > 3) console.log('ws.onopen: ReadyState: ' + this.readyState);
-        // NDN.registerPrefix will fetch the ndndid when needed.
-        
-        onopenCallback();
-	}
-	
-	this.ws.onerror = function(ev) {
-		console.log('ws.onerror: ReadyState: ' + this.readyState);
-		console.log(ev);
-		console.log('ws.onerror: WebSocket error: ' + ev.data);
-	}
-	
-	this.ws.onclose = function(ev) {
-		console.log('ws.onclose: WebSocket connection closed.');
-		self.ws = null;
-		
-		// Close NDN when WebSocket is closed
-		ndn.readyStatus = NDN.CLOSED;
-		ndn.onclose();
-		//console.log("NDN.onclose event fired.");
-	}
-};
-
-/*
- * Send the Uint8Array data.
- */
-WebSocketTransport.prototype.send = function(data) {
-	if (this.ws != null) {
-        // If we directly use data.buffer to feed ws.send(), 
-        // WebSocket may end up sending a packet with 10000 bytes of data.
-        // That is, WebSocket will flush the entire buffer
-        // regardless of the offset of the Uint8Array. So we have to create
-        // a new Uint8Array buffer with just the right size and copy the 
-        // content from binaryInterest to the new buffer.
-        //    ---Wentao
-        var bytearray = new Uint8Array(data.length);
-        bytearray.set(data);
-        this.ws.send(bytearray.buffer);
-		if (LOG > 3) console.log('ws.send() returned.');
-	}
-	else
-		console.log('WebSocket connection is not established.');
-}
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class contains all NDNx tags
- */
-
-
-var NDNProtocolDTags = {
-
-	/**
-	 * Note if you add one of these, add it to the reverse string map as well.
-	 * Emphasize getting the work done at compile time over trying to make something
-	 * flexible and developer error-proof.
-	 */
-
-	 Any : 13,
-	 Name : 14,
-	 Component : 15,
-	 Certificate : 16,
-	 Collection : 17,
-	 CompleteName : 18,
-	 Content : 19,
-	 SignedInfo : 20,
-	 ContentDigest : 21,
-	 ContentHash : 22,
-	 Count : 24,
-	 Header : 25,
-	 Interest : 26,	/* 20090915 */
-	 Key : 27,
-	 KeyLocator : 28,
-	 KeyName : 29,
-	 Length : 30,
-	 Link : 31,
-	 LinkAuthenticator : 32,
-	 NameComponentCount : 33,	/* DeprecatedInInterest */
-	 RootDigest : 36,
-	 Signature : 37,
-	 Start : 38,
-	 Timestamp : 39,
-	 Type : 40,
-	 Nonce : 41,
-	 Scope : 42,
-	 Exclude : 43,
-	 Bloom : 44,
-	 BloomSeed : 45,
-	 AnswerOriginKind : 47,
-	 InterestLifetime : 48,
-	 Witness : 53,
-	 SignatureBits : 54,
-	 DigestAlgorithm : 55,
-	 BlockSize : 56,
-	 FreshnessSeconds : 58,
-	 FinalBlockID : 59,
-	 PublisherPublicKeyDigest : 60,
-	 PublisherCertificateDigest : 61,
-	 PublisherIssuerKeyDigest : 62,
-	 PublisherIssuerCertificateDigest : 63,
-	 ContentObject : 64,	/* 20090915 */
-	 WrappedKey : 65,
-	 WrappingKeyIdentifier : 66,
-	 WrapAlgorithm : 67,
-	 KeyAlgorithm : 68,
-	 Label : 69,
-	 EncryptedKey : 70,
-	 EncryptedNonceKey : 71,
-	 WrappingKeyName : 72,
-	 Action : 73,
-	 FaceID : 74,
-	 IPProto : 75,
-	 Host : 76,
-	 Port : 77,
-	 MulticastInterface : 78,
-	 ForwardingFlags : 79,
-	 FaceInstance : 80,
-	 ForwardingEntry : 81,
-	 MulticastTTL : 82,
-	 MinSuffixComponents : 83,
-	 MaxSuffixComponents : 84,
-	 ChildSelector : 85,
-	 RepositoryInfo : 86,
-	 Version : 87,
-	 RepositoryVersion : 88,
-	 GlobalPrefix : 89,
-	 LocalName : 90,
-	 Policy : 91,
-	 Namespace : 92,
-	 GlobalPrefixName : 93,
-	 PolicyVersion : 94,
-	 KeyValueSet : 95,
-	 KeyValuePair : 96,
-	 IntegerValue : 97,
-	 DecimalValue : 98,
-	 StringValue : 99,
-	 BinaryValue : 100,
-	 NameValue : 101,
-	 Entry : 102,
-	 ACL : 103,
-	 ParameterizedName : 104,
-	 Prefix : 105,
-	 Suffix : 106,
-	 Root : 107,
-	 ProfileName : 108,
-	 Parameters : 109,
-	 InfoString : 110,
-	// 111 unallocated
-	 StatusResponse : 112,
-	 StatusCode : 113,
-	 StatusText : 114,
-
-	// Sync protocol
-	 SyncNode : 115,
-	 SyncNodeKind : 116,
-	 SyncNodeElement : 117,
-	 SyncVersion : 118,
-	 SyncNodeElements : 119,
-	 SyncContentHash : 120,
-	 SyncLeafCount : 121,
-	 SyncTreeDepth : 122,
-	 SyncByteCount : 123,
-	 ConfigSlice : 124,
-	 ConfigSliceList : 125,
-	 ConfigSliceOp : 126,
-
-	// Remember to keep in sync with schema/tagnames.csvsdict
-	 NDNProtocolDataUnit : 17702112,
-	 NDNPROTOCOL_DATA_UNIT : "NDNProtocolDataUnit"
-};
-
-var NDNProtocolDTagsStrings = [
-	null, null, null, null, null, null, null, null, null, null, null,
-	null, null,
-	"Any", "Name", "Component", "Certificate", "Collection", "CompleteName",
-	"Content", "SignedInfo", "ContentDigest", "ContentHash", null, "Count", "Header",
-	"Interest", "Key", "KeyLocator", "KeyName", "Length", "Link", "LinkAuthenticator",
-	"NameComponentCount", null, null, "RootDigest", "Signature", "Start", "Timestamp", "Type",
-	"Nonce", "Scope", "Exclude", "Bloom", "BloomSeed", null, "AnswerOriginKind",
-	"InterestLifetime", null, null, null, null, "Witness", "SignatureBits", "DigestAlgorithm", "BlockSize",
-	null, "FreshnessSeconds", "FinalBlockID", "PublisherPublicKeyDigest", "PublisherCertificateDigest",
-	"PublisherIssuerKeyDigest", "PublisherIssuerCertificateDigest", "ContentObject",
-	"WrappedKey", "WrappingKeyIdentifier", "WrapAlgorithm", "KeyAlgorithm", "Label",
-	"EncryptedKey", "EncryptedNonceKey", "WrappingKeyName", "Action", "FaceID", "IPProto",
-	"Host", "Port", "MulticastInterface", "ForwardingFlags", "FaceInstance",
-	"ForwardingEntry", "MulticastTTL", "MinSuffixComponents", "MaxSuffixComponents", "ChildSelector",
-	"RepositoryInfo", "Version", "RepositoryVersion", "GlobalPrefix", "LocalName",
-	"Policy", "Namespace", "GlobalPrefixName", "PolicyVersion", "KeyValueSet", "KeyValuePair",
-	"IntegerValue", "DecimalValue", "StringValue", "BinaryValue", "NameValue", "Entry",
-	"ACL", "ParameterizedName", "Prefix", "Suffix", "Root", "ProfileName", "Parameters",
-	"InfoString", null,
-    "StatusResponse", "StatusCode", "StatusText", "SyncNode", "SyncNodeKind", "SyncNodeElement",
-    "SyncVersion", "SyncNodeElements", "SyncContentHash", "SyncLeafCount", "SyncTreeDepth", "SyncByteCount",
-    "ConfigSlice", "ConfigSliceList", "ConfigSliceOp" ];
-
-
-//TESTING
-//console.log(exports.NDNProtocolDTagsStrings[17]);
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents NDNTime Objects
- */
-
-var NDNTime = function NDNTime(
-                               
-		input) {
-
-
-
-
-	this.NANOS_MAX = 999877929;
-	
-	/*if(typeof input =='object'){
-		this.longDate = DataUtils.byteArrayToUnsignedLong(input);
-		this.binaryDate = input;
-	}*/
-	if(typeof input =='number'){
-		this.msec = input;
-		//this.binaryDate = DataUtils.unsignedLongToByteArray(input);
-
-	}
-	else{
-		if(LOG>1) console.log('UNRECOGNIZED TYPE FOR TIME');
-	}
-};
-
-
-NDNTime.prototype.getJavascriptDate = function(){
-	var d = new Date();
-	d.setTime( this.msec );
-	return d
-};
-
-	/**
-	 * Create a NDNTime
-	 * @param timestamp source timestamp to initialize from, some precision will be lost
-	 */
-
-
-	/**
-	 * Create a NDNTime from its binary encoding
-	 * @param binaryTime12 the binary representation of a NDNTime
-	 */
-/*NDNTime.prototype.setDateBinary = function(
-	//byte [] 
-		binaryTime12) {
-
-
-	if ((null == binaryTime12) || (binaryTime12.length == 0)) {
-		throw new IllegalArgumentException("Invalid binary time!");
-	}
-	
-
-	value = 0;
-	for(i = 0; i < binaryTime12.length; i++) {
-		value = value << 8;
-		b = (binaryTime12[i]) & 0xFF;
-		value |= b;
-	}
-
-	//this.date = new Date(value);
-
-};
-
-//byte[]
-NDNTime.prototype.toBinaryTime = function() {
-
-	return this.msec; //unsignedLongToByteArray(this.date.getTime());
-
-}*/
-/*
-unsignedLongToByteArray= function( value) {
-	if( 0 == value )
-		return [0];
-
-	if( 0 <= value && value <= 0x00FF ) {
-		//byte [] 
-		bb = new Array[1];
-		bb[0] = (value & 0x00FF);
-		return bb;
-	}
-
-	
-	//byte [] 
-	out = null;
-	//int
-	offset = -1;
-	for(var i = 7; i >=0; --i) {
-		//byte
-		b = ((value >> (i * 8)) & 0xFF);
-		if( out == null && b != 0 ) {
-			out = new Array(i+1);//byte[i+1];
-			offset = i;
-		}
-		if( out != null )
-			out[ offset - i ] = b;
-	}
-	return out;
-}*/
-	
-/**
- * @author: Jeff Thompson
- * See COPYING for copyright and distribution information.
- * This is the closure class for use in expressInterest to re express with exponential falloff.
- */
-
-/*
- * Create a new ExponentialReExpressClosure where upcall responds to UPCALL_INTEREST_TIMED_OUT
- *   by expressing the interest again with double the interestLifetime. If the interesLifetime goes
- *   over maxInterestLifetime, then call callerClosure.upcall with UPCALL_INTEREST_TIMED_OUT.
- * When upcall is not UPCALL_INTEREST_TIMED_OUT, just call callerClosure.upcall.
- * 
- * settings is an associative array with the following defaults:
- * {
- *   maxInterestLifetime: 16000 // milliseconds
- * }
- */
-var ExponentialReExpressClosure = function ExponentialReExpressClosure
-        (callerClosure, settings) {
-    // Inherit from Closure.
-    Closure.call(this);
-    
-    this.callerClosure = callerClosure;
-    settings = (settings || {});
-	this.maxInterestLifetime = (settings.maxInterestLifetime || 16000);
-};
-
-ExponentialReExpressClosure.prototype.upcall = function(kind, upcallInfo) {
-    try {
-        if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
-            var interestLifetime = upcallInfo.interest.interestLifetime;
-            if (interestLifetime == null)
-                return this.callerClosure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, upcallInfo);
-            
-            var nextInterestLifetime = interestLifetime * 2;
-            if (nextInterestLifetime > this.maxInterestLifetime)
-                return this.callerClosure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, upcallInfo);
-            
-            var nextInterest = upcallInfo.interest.clone();
-            nextInterest.interestLifetime = nextInterestLifetime;
-            upcallInfo.ndn.expressInterest(nextInterest.name, this, nextInterest);
-            return Closure.RESULT_OK;
-        }  
-        else
-            return this.callerClosure.upcall(kind, upcallInfo);
-    } catch (ex) {
-        console.log("ExponentialReExpressClosure.upcall exception: " + ex);
-        return Closure.RESULT_ERR;
+// Domain Public by Eric Wendelin http://www.eriwen.com/ (2008)
+//                  Luke Smith http://lucassmith.name/ (2008)
+//                  Loic Dachary <loic@dachary.org> (2008)
+//                  Johan Euphrosine <proppy@aminche.com> (2008)
+//                  Oyvind Sean Kinsey http://kinsey.no/blog (2010)
+//                  Victor Homyakov <victor-homyakov@users.sourceforge.net> (2010)
+/*global module, exports, define, ActiveXObject*/
+(function(global, factory) {
+    if (typeof exports === 'object') {
+        // Node
+        module.exports.printStackTrace = factory();
+    } else if (typeof define === 'function' && define.amd) {
+        // AMD
+        define(factory);
+    } else {
+        // Browser globals
+        global.printStackTrace = factory();
     }
-};
-/**
- * @author: Meki Cheraoui, Jeff Thompson
- * See COPYING for copyright and distribution information.
- * This class represents a Name as an array of components where each is a byte array.
- */
-
-/*
- * Create a new Name from _components.
- * If _components is a string, parse it as a URI.
- * If _components is a Name, add a deep copy of its components.
- * Otherwise it is an array of components where each is a string, byte array, ArrayBuffer, Uint8Array
- *   or Name.
- * Convert and store as an array of Uint8Array.
- * If a component is a string, encode as utf8.
- */
-var Name = function Name(_components){
-	if( typeof _components == 'string') {
-		if(LOG>3)console.log('Content Name String '+_components);
-		this.components = Name.createNameArray(_components);
-	}
-	else if(typeof _components === 'object'){
-		this.components = [];
-        if (_components instanceof Name)
-            this.add(_components);
-        else {
-            for (var i = 0; i < _components.length; ++i)
-                this.add(_components[i]);
-        }
-	}
-	else if(_components==null)
-		this.components =[];
-	else
-		if(LOG>1)console.log("NO CONTENT NAME GIVEN");
-};
-
-Name.prototype.getName = function() {
-    return this.to_uri();
-};
-
-/* Parse name as a URI and return an array of Uint8Array components.
- *
- */
-Name.createNameArray = function(name) {
-    name = name.trim();
-    if (name.length <= 0)
-        return [];
-
-    var iColon = name.indexOf(':');
-    if (iColon >= 0) {
-        // Make sure the colon came before a '/'.
-        var iFirstSlash = name.indexOf('/');
-        if (iFirstSlash < 0 || iColon < iFirstSlash)
-            // Omit the leading protocol such as ndn:
-            name = name.substr(iColon + 1, name.length - iColon - 1).trim();
-    }
-
-  	if (name[0] == '/') {
-        if (name.length >= 2 && name[1] == '/') {
-            // Strip the authority following "//".
-            var iAfterAuthority = name.indexOf('/', 2);
-            if (iAfterAuthority < 0)
-                // Unusual case: there was only an authority.
-                return [];
-            else
-                name = name.substr(iAfterAuthority + 1, name.length - iAfterAuthority - 1).trim();
-        }
-        else
-            name = name.substr(1, name.length - 1).trim();
-    }
-
-	var array = name.split('/');
-
-    // Unescape the components.
-    for (var i = 0; i < array.length; ++i) {
-        var component = Name.fromEscapedString(array[i]);
-
-        if (component == null) {
-            // Ignore the illegal componenent.  This also gets rid of a trailing '/'.
-            array.splice(i, 1);
-            --i;
-            continue;
-        }
-        else
-            array[i] = component;
-    }
-
-	return array;
-}
-
-
-Name.prototype.from_ndnb = function(/*XMLDecoder*/ decoder)  {
-		decoder.readStartElement(this.getElementLabel());
-
-
-		this.components = new Array(); //new ArrayList<byte []>();
-
-		while (decoder.peekStartElement(NDNProtocolDTags.Component)) {
-			this.add(decoder.readBinaryElement(NDNProtocolDTags.Component));
-		}
-
-		decoder.readEndElement();
-};
-
-Name.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)  {
-
-		if( this.components ==null )
-			throw new Error("CANNOT ENCODE EMPTY CONTENT NAME");
-
-		encoder.writeStartElement(this.getElementLabel());
-		var count = this.components.length;
-		for (var i=0; i < count; i++) {
-			encoder.writeElement(NDNProtocolDTags.Component, this.components[i]);
-		}
-		encoder.writeEndElement();
-};
-
-Name.prototype.getElementLabel = function(){
-	return NDNProtocolDTags.Name;
-};
-
-/*
- * component is a string, byte array, ArrayBuffer, Uint8Array or Name.
- * Convert to Uint8Array and add to this Name.
- * If a component is a string, encode as utf8.
- * Return this Name object to allow chaining calls to add.
- */
-Name.prototype.add = function(component){
-    var result;
-    if(typeof component == 'string')
-        result = DataUtils.stringToUtf8Array(component);
-	else if(typeof component == 'object' && component instanceof Uint8Array)
-        result = new Uint8Array(component);
-	else if(typeof component == 'object' && component instanceof ArrayBuffer) {
-        // Make a copy.  Don't use ArrayBuffer.slice since it isn't always supported.
-        result = new Uint8Array(new ArrayBuffer(component.byteLength));
-        result.set(new Uint8Array(component));
-    }
-    else if (typeof component == 'object' && component instanceof Name) {
-        var components;
-        if (component == this)
-            // special case, when we need to create a copy
-            components = this.components.slice(0, this.components.length);
-        else
-            components = component.components;
-
-        for (var i = 0; i < components.length; ++i)
-            this.components.push(new Uint8Array(components[i]));
-        return this;
-    }
-	else if(typeof component == 'object')
-        // Assume component is a byte array.  We can't check instanceof Array because
-        //   this doesn't work in JavaScript if the array comes from a different module.
-        result = new Uint8Array(component);
-	else
-		throw new Error("Cannot add Name element at index " + this.components.length +
-            ": Invalid type");
-
-    this.components.push(result);
-	return this;
-};
-
-/**
- * @brief Add component that represents a segment number
- *
- * @param number Segment number (integer is expected)
- *
- * This component has a special format handling:
- * - if number is zero, then %00 is added
- * - if number is between 1 and 255, %00%01 .. %00%FF is added
- * - ...
- */
-Name.prototype.addSegment = function(number) {
-    // step 1: figure out how many bytes will be needed
-    var bytes = 1; // at least 1 byte
-    var test_number = number;
-    while (test_number > 0) {
-        bytes ++;
-        test_number >>= 8;
-    }
-
-    var result = new Uint8Array (bytes);
-    var index = 0;
-    result[index] = 0;
-    index ++;
-    while (number > 0) {
-        result[index] = number & 0xFF;
-        number >>= 8;
-        index ++;
-    }
-
-    this.components.push(result);
-    return this;
-}
-
-// Return the escaped name string according to "NDNx URI Scheme".
-Name.prototype.to_uri = function() {
-    if (this.components.length == 0)
-        return "/";
-
-	var result = "";
-
-	for(var i = 0; i < this.components.length; ++i)
-		result += "/"+ Name.toEscapedString(this.components[i]);
-
-	return result;
-};
-
-/**
-* @brief Add component that represents a segment number
-*
-* @param number Segment number (integer is expected)
-*
-* This component has a special format handling:
-* - if number is zero, then %00 is added
-* - if number is between 1 and 255, %00%01 .. %00%FF is added
-* - ...
-*/
-Name.prototype.addSegment = function(number) {
-    var segmentNumberBigEndian = DataUtils.nonNegativeIntToBigEndian(number);
-    // Put a 0 byte in front.
-    var segmentNumberComponent = new Uint8Array(segmentNumberBigEndian.length + 1);
-    segmentNumberComponent.set(segmentNumberBigEndian, 1);
-
-    this.components.push(segmentNumberComponent);
-    return this;
-};
-
-/*
- * Return a new Name with the first nComponents components of this Name.
- */
-Name.prototype.getPrefix = function(nComponents) {
-    return new Name(this.components.slice(0, nComponents));
-}
-
-/**
- * @brief Get prefix of the name, containing less minusComponents right components
- * @param minusComponents number of components to cut from the back
- */
-Name.prototype.cut = function (minusComponents) {
-    return new Name(this.components.slice(0, this.components.length-1));
-}
-
-/*
- * Return a new ArrayBuffer of the component at i.
- */
-Name.prototype.getComponent = function(i) {
-    var result = new ArrayBuffer(this.components[i].length);
-    new Uint8Array(result).set(this.components[i]);
-    return result;
-}
-
-/*
- * The "file name" in a name is the last component that isn't blank and doesn't start with one of the
- *   special marker octets (for version, etc.).  Return the index in this.components of
- *   the file name, or -1 if not found.
- */
-Name.prototype.indexOfFileName = function() {
-    for (var i = this.components.length - 1; i >= 0; --i) {
-        var component = this.components[i];
-        if (component.length <= 0)
-            continue;
-
-        if (component[0] == 0 || component[0] == 0xC0 || component[0] == 0xC1 ||
-            (component[0] >= 0xF5 && component[0] <= 0xFF))
-            continue;
-
-        return i;
-    }
-
-    return -1;
-}
-
-/*
- * Return true if this Name has the same components as name.
- */
-Name.prototype.equalsName = function(name) {
-    if (this.components.length != name.components.length)
-        return false;
-
-    // Start from the last component because they are more likely to differ.
-    for (var i = this.components.length - 1; i >= 0; --i) {
-        if (!DataUtils.arraysEqual(this.components[i], name.components[i]))
-            return false;
-    }
-
-    return true;
-}
-
-/*
- * Find the last component in name that has a ContentDigest and return the digest value as Uint8Array,
- *   or null if not found.  See Name.getComponentContentDigestValue.
- */
-Name.prototype.getContentDigestValue = function() {
-    for (var i = this.components.length - 1; i >= 0; --i) {
-        var digestValue = Name.getComponentContentDigestValue(this.components[i]);
-        if (digestValue != null)
-           return digestValue;
-    }
-
-    return null;
-}
-
-/*
- * If component is a ContentDigest, return the digest value as a Uint8Array subarray (don't modify!).
- * If not a ContentDigest, return null.
- * A ContentDigest component is Name.ContentDigestPrefix + 32 bytes + Name.ContentDigestSuffix.
- */
-Name.getComponentContentDigestValue = function(component) {
-    var digestComponentLength = Name.ContentDigestPrefix.length + 32 + Name.ContentDigestSuffix.length;
-    // Check for the correct length and equal ContentDigestPrefix and ContentDigestSuffix.
-    if (component.length == digestComponentLength &&
-        DataUtils.arraysEqual(component.subarray(0, Name.ContentDigestPrefix.length),
-                              Name.ContentDigestPrefix) &&
-        DataUtils.arraysEqual(component.subarray
-           (component.length - Name.ContentDigestSuffix.length, component.length),
-                              Name.ContentDigestSuffix))
-       return component.subarray(Name.ContentDigestPrefix.length, Name.ContentDigestPrefix.length + 32);
-   else
-       return null;
-}
-
-// Meta GUID "%C1.M.G%C1" + ContentDigest with a 32 byte BLOB.
-Name.ContentDigestPrefix = new Uint8Array([0xc1, 0x2e, 0x4d, 0x2e, 0x47, 0xc1, 0x01, 0xaa, 0x02, 0x85]);
-Name.ContentDigestSuffix = new Uint8Array([0x00]);
-
-/*
- * Return component as an escaped string according to "NDNx URI Scheme".
- * We can't use encodeURIComponent because that doesn't encode all the characters we want to.
- */
-Name.toEscapedString = function(component) {
-    var result = "";
-    var gotNonDot = false;
-    for (var i = 0; i < component.length; ++i) {
-        if (component[i] != 0x2e) {
-            gotNonDot = true;
-            break;
-        }
-    }
-    if (!gotNonDot) {
-        // Special case for component of zero or more periods.  Add 3 periods.
-        result = "...";
-        for (var i = 0; i < component.length; ++i)
-            result += ".";
-    }
-    else {
-        for (var i = 0; i < component.length; ++i) {
-            var value = component[i];
-            // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
-            if (value >= 0x30 && value <= 0x39 || value >= 0x41 && value <= 0x5a ||
-                value >= 0x61 && value <= 0x7a || value == 0x2b || value == 0x2d ||
-                value == 0x2e || value == 0x5f)
-                result += String.fromCharCode(value);
-            else
-                result += "%" + (value < 16 ? "0" : "") + value.toString(16).toUpperCase();
-        }
-    }
-    return result;
-};
-
-/*
- * Return component as a Uint8Array by decoding the escapedString according to "NDNx URI Scheme".
- * If escapedString is "", "." or ".." then return null, which means to skip the component in the name.
- */
-Name.fromEscapedString = function(escapedString) {
-    var component = unescape(escapedString.trim());
-
-    if (component.match(/[^.]/) == null) {
-        // Special case for component of only periods.
-        if (component.length <= 2)
-            // Zero, one or two periods is illegal.  Ignore this componenent to be
-            //   consistent with the C implementation.
-            return null;
-        else
-            // Remove 3 periods.
-            return DataUtils.toNumbersFromString(component.substr(3, component.length - 3));
-    }
-    else
-        return DataUtils.toNumbersFromString(component);
-}
-
-Name.prototype.match = function(/*Name*/ name) {
-	var i_name = this.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.
- * This class represents ContentObject Objects
- */
-var ContentObject = function ContentObject(_name,_signedInfo,_content,_signature){
-	
-	
-	if (typeof _name == 'string') {
-		this.name = new Name(_name);
-	}
-	else{
-		//TODO Check the class of _name
-		this.name = _name;
-	}
-	this.signedInfo = _signedInfo;
-	
-	if (typeof _content == 'string') {
-		this.content = DataUtils.toNumbersFromString(_content);
-	} else {
-		this.content = _content;
-	}
-	
-	this.signature = _signature;
-
-	
-	this.startSIG = null;
-	this.endSIG = null;
-	
-	//this.startSignedInfo = null;
-	this.endContent = null;
-	
-	this.rawSignatureData = null;
-};
-
-ContentObject.prototype.sign = function(){
-
-	var n1 = this.encodeObject(this.name);
-	var n2 = this.encodeObject(this.signedInfo);
-	var n3 = this.encodeContent();
-	/*console.log('sign: ');
-	console.log(n1);
-	console.log(n2);
-	console.log(n3);*/
-	
-	//var n = n1.concat(n2,n3);
-	var tempBuf = new ArrayBuffer(n1.length + n2.length + n3.length);
-	var n = new Uint8Array(tempBuf);
-	//console.log(n);
-	n.set(n1, 0);
-	//console.log(n);
-	n.set(n2, n1.length);
-	//console.log(n);
-	n.set(n3, n1.length + n2.length);
-	//console.log(n);
-	
-	if(LOG>4)console.log('Signature Data is (binary) '+n);
-	
-	if(LOG>4)console.log('Signature Data is (RawString)');
-	
-	if(LOG>4)console.log( DataUtils.toString(n) );
-	
-	//var sig = DataUtils.toString(n);
-
-	
-	var rsa = new RSAKey();
-			
-	rsa.readPrivateKeyFromPEMString(globalKeyManager.privateKey);
-	
-	//var hSig = rsa.signString(sig, "sha256");
-
-	var hSig = rsa.signByteArrayWithSHA256(n);
-
-	
-	if(LOG>4)console.log('SIGNATURE SAVED IS');
-	
-	if(LOG>4)console.log(hSig);
-	
-	if(LOG>4)console.log(  DataUtils.toNumbers(hSig.trim()));
-
-	this.signature.signature = DataUtils.toNumbers(hSig.trim());
-	
-
-};
-
-ContentObject.prototype.encodeObject = function encodeObject(obj){
-	var enc = new BinaryXMLEncoder();
- 
-	obj.to_ndnb(enc);
-	
-	var num = enc.getReducedOstream();
-
-	return num;
-
-	
-};
-
-ContentObject.prototype.encodeContent = function encodeContent(obj){
-	var enc = new BinaryXMLEncoder();
-	 
-	enc.writeElement(NDNProtocolDTags.Content, this.content);
-
-	var num = enc.getReducedOstream();
-
-	return num;
-
-	
-};
-
-ContentObject.prototype.saveRawData = function(bytes){
-	
-	var sigBits = bytes.subarray(this.startSIG, this.endSIG);
-
-	this.rawSignatureData = sigBits;
-};
-
-ContentObject.prototype.from_ndnb = function(/*XMLDecoder*/ decoder) {
-
-	// TODO VALIDATE THAT ALL FIELDS EXCEPT SIGNATURE ARE PRESENT
-
-		decoder.readStartElement(this.getElementLabel());
-
-
-		if( decoder.peekStartElement(NDNProtocolDTags.Signature) ){
-			this.signature = new Signature();
-			this.signature.from_ndnb(decoder);
-		}
-		
-		//this.endSIG = decoder.offset;
-
-		this.startSIG = decoder.offset;
-
-		this.name = new Name();
-		this.name.from_ndnb(decoder);
-		
-		//this.startSignedInfo = decoder.offset;
-	
-		
-		if( decoder.peekStartElement(NDNProtocolDTags.SignedInfo) ){
-			this.signedInfo = new SignedInfo();
-			this.signedInfo.from_ndnb(decoder);
-		}
-		
-		this.content = decoder.readBinaryElement(NDNProtocolDTags.Content);
-
-		
-		//this.endContent = decoder.offset;
-		this.endSIG = decoder.offset;
-
-		
-		decoder.readEndElement();
-		
-		this.saveRawData(decoder.istream);
-};
-
-ContentObject.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)  {
-
-	//TODO verify name, SignedInfo and Signature is present
-
-
-	encoder.writeStartElement(this.getElementLabel());
-
-	
-
-
-	if(null!=this.signature) this.signature.to_ndnb(encoder);
-	
-	
-	this.startSIG = encoder.offset;
-	
-
-	if(null!=this.name) this.name.to_ndnb(encoder);
-	
-	//this.endSIG = encoder.offset;
-	//this.startSignedInfo = encoder.offset;
-	
-	
-	if(null!=this.signedInfo) this.signedInfo.to_ndnb(encoder);
-
-	encoder.writeElement(NDNProtocolDTags.Content, this.content);
-
-	
-	this.endSIG = encoder.offset;
-	
-	//this.endContent = encoder.offset;
-	
-
-	encoder.writeEndElement();
-	
-	this.saveRawData(encoder.ostream);
-	
-};
-
-ContentObject.prototype.getElementLabel= function(){return NDNProtocolDTags.ContentObject;};
-
-/**
- * Signature
- */
-var Signature = function Signature(_witness,_signature,_digestAlgorithm) {
-	
-    this.Witness = _witness;//byte [] _witness;
-	this.signature = _signature;//byte [] _signature;
-	this.digestAlgorithm = _digestAlgorithm//String _digestAlgorithm;
-};
-
-Signature.prototype.from_ndnb =function( decoder) {
-		decoder.readStartElement(this.getElementLabel());
-		
-		if(LOG>4)console.log('STARTED DECODING SIGNATURE');
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.DigestAlgorithm)) {
-			if(LOG>4)console.log('DIGIEST ALGORITHM FOUND');
-			this.digestAlgorithm = decoder.readUTF8Element(NDNProtocolDTags.DigestAlgorithm); 
-		}
-		if (decoder.peekStartElement(NDNProtocolDTags.Witness)) {
-			if(LOG>4)console.log('WITNESS FOUND');
-			this.Witness = decoder.readBinaryElement(NDNProtocolDTags.Witness); 
-		}
-		
-		//FORCE TO READ A SIGNATURE
-
-			if(LOG>4)console.log('SIGNATURE FOUND');
-			this.signature = decoder.readBinaryElement(NDNProtocolDTags.SignatureBits);
-
-		decoder.readEndElement();
-	
-};
-
-
-Signature.prototype.to_ndnb= function( encoder){
-    	
-	if (!this.validate()) {
-		throw new Error("Cannot encode: field values missing.");
-	}
-	
-	encoder.writeStartElement(this.getElementLabel());
-	
-	if ((null != this.digestAlgorithm) && (!this.digestAlgorithm.equals(NDNDigestHelper.DEFAULT_DIGEST_ALGORITHM))) {
-		encoder.writeElement(NDNProtocolDTags.DigestAlgorithm, OIDLookup.getDigestOID(this.DigestAlgorithm));
-	}
-	
-	if (null != this.Witness) {
-		// needs to handle null witness
-		encoder.writeElement(NDNProtocolDTags.Witness, this.Witness);
-	}
-
-	encoder.writeElement(NDNProtocolDTags.SignatureBits, this.signature);
-
-	encoder.writeEndElement();   		
-};
-
-Signature.prototype.getElementLabel = function() { return NDNProtocolDTags.Signature; };
-
-
-Signature.prototype.validate = function() {
-		return null != this.signature;
-};
-
-
-/**
- * SignedInfo
- */
-var ContentType = {DATA:0, ENCR:1, GONE:2, KEY:3, LINK:4, NACK:5};
-var ContentTypeValue = {0:0x0C04C0, 1:0x10D091,2:0x18E344,3:0x28463F,4:0x2C834A,5:0x34008A};
-var ContentTypeValueReverse = {0x0C04C0:0, 0x10D091:1,0x18E344:2,0x28463F:3,0x2C834A:4,0x34008A:5};
-
-var SignedInfo = function SignedInfo(_publisher,_timestamp,_type,_locator,_freshnessSeconds,_finalBlockID){
-
-	//TODO, Check types
-
-    this.publisher = _publisher; //publisherPublicKeyDigest
-    this.timestamp=_timestamp; // NDN Time
-    this.type=_type; // ContentType
-    this.locator =_locator;//KeyLocator
-    this.freshnessSeconds =_freshnessSeconds; // Integer
-    this.finalBlockID=_finalBlockID; //byte array
-    
-    // SWT: merge setFields() method into constructor
-    this.setFields();
-
-};
-
-SignedInfo.prototype.setFields = function(){
-	//BASE64 -> RAW STRING
-	
-	//this.locator = new KeyLocator(  DataUtils.toNumbersFromString(stringCertificate)  ,KeyLocatorType.CERTIFICATE );
-	
-	var publicKeyHex = globalKeyManager.publicKey;
-
-	if(LOG>4)console.log('PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ');
-	if(LOG>4)console.log(publicKeyHex);
-	
-	var publicKeyBytes = DataUtils.toNumbers(globalKeyManager.publicKey) ; 
-
-	
-
-	//var stringCertificate = DataUtils.base64toString(globalKeyManager.certificate);
-	
-	//if(LOG>3)console.log('string Certificate is '+stringCertificate);
-
-	//HEX -> BYTE ARRAY
-	//var publisherkey = DataUtils.toNumbers(hex_sha256(stringCertificate));
-	
-	//if(LOG>3)console.log('publisher key is ');
-	//if(LOG>3)console.log(publisherkey);
-	
-	var publisherKeyDigest = hex_sha256_from_bytes(publicKeyBytes);
-
-	this.publisher = new PublisherPublicKeyDigest(  DataUtils.toNumbers(  publisherKeyDigest )  );
-	
-	//this.publisher = new PublisherPublicKeyDigest(publisherkey);
-
-	var d = new Date();
-	
-	var time = d.getTime();
-	
-
-    this.timestamp = new NDNTime( time );
-    
-    if(LOG>4)console.log('TIME msec is');
-
-    if(LOG>4)console.log(this.timestamp.msec);
-
-    //DATA
-	this.type = 0;//0x0C04C0;//ContentTypeValue[ContentType.DATA];
-	
-	//if(LOG>4)console.log('toNumbersFromString(stringCertificate) '+DataUtils.toNumbersFromString(stringCertificate));
-	
-	if(LOG>4)console.log('PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ');
-	if(LOG>4)console.log(publicKeyBytes);
-
-	this.locator = new KeyLocator(  publicKeyBytes  ,KeyLocatorType.KEY );
-
-	//this.locator = new KeyLocator(  DataUtils.toNumbersFromString(stringCertificate)  ,KeyLocatorType.CERTIFICATE );
-
-};
-
-SignedInfo.prototype.from_ndnb = function( decoder){
-
-		decoder.readStartElement( this.getElementLabel() );
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)) {
-			if(LOG>4)console.log('DECODING PUBLISHER KEY');
-			this.publisher = new PublisherPublicKeyDigest();
-			this.publisher.from_ndnb(decoder);
-		}
-
-		if (decoder.peekStartElement(NDNProtocolDTags.Timestamp)) {
-			if(LOG>4)console.log('DECODING TIMESTAMP');
-			this.timestamp = decoder.readDateTime(NDNProtocolDTags.Timestamp);
-		}
-
-		if (decoder.peekStartElement(NDNProtocolDTags.Type)) {
-			var binType = decoder.readBinaryElement(NDNProtocolDTags.Type);//byte [] 
-		
-			
-			//TODO Implement type of Key Reading
-			
-			if(LOG>4)console.log('Binary Type of of Signed Info is '+binType);
-
-			this.type = binType;
-			
-			
-			//TODO Implement type of Key Reading
-			
-			
-			if (null == this.type) {
-				throw new Error("Cannot parse signedInfo type: bytes.");
-			}
-			
-		} else {
-			this.type = ContentType.DATA; // default
-		}
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.FreshnessSeconds)) {
-			this.freshnessSeconds = decoder.readIntegerElement(NDNProtocolDTags.FreshnessSeconds);
-			if(LOG>4)console.log('FRESHNESS IN SECONDS IS '+ this.freshnessSeconds);
-		}
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.FinalBlockID)) {
-			if(LOG>4)console.log('DECODING FINAL BLOCKID');
-			this.finalBlockID = decoder.readBinaryElement(NDNProtocolDTags.FinalBlockID);
-		}
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.KeyLocator)) {
-			if(LOG>4)console.log('DECODING KEY LOCATOR');
-			this.locator = new KeyLocator();
-			this.locator.from_ndnb(decoder);
-		}
-				
-		decoder.readEndElement();
-};
-
-SignedInfo.prototype.to_ndnb = function( encoder)  {
-		if (!this.validate()) {
-			throw new Error("Cannot encode : field values missing.");
-		}
-		encoder.writeStartElement(this.getElementLabel());
-		
-		if (null!=this.publisher) {
-			if(LOG>3) console.log('ENCODING PUBLISHER KEY' + this.publisher.publisherPublicKeyDigest);
-
-			this.publisher.to_ndnb(encoder);
-		}
-
-		if (null!=this.timestamp) {
-			encoder.writeDateTime(NDNProtocolDTags.Timestamp, this.timestamp );
-		}
-		
-		if (null!=this.type && this.type !=0) {
-			
-			encoder.writeElement(NDNProtocolDTags.type, this.type);
-		}
-		
-		if (null!=this.freshnessSeconds) {
-			encoder.writeElement(NDNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
-		}
-
-		if (null!=this.finalBlockID) {
-			encoder.writeElement(NDNProtocolDTags.FinalBlockID, this.finalBlockID);
-		}
-
-		if (null!=this.locator) {
-			this.locator.to_ndnb(encoder);
-		}
-
-		encoder.writeEndElement();   		
-};
-	
-SignedInfo.prototype.valueToType = function(){
-	//for (Entry<byte [], ContentType> entry : ContentValueTypes.entrySet()) {
-		//if (Arrays.equals(value, entry.getKey()))
-			//return entry.getValue();
-		//}
-	return null;
-	
-};
-
-SignedInfo.prototype.getElementLabel = function() { 
-	return NDNProtocolDTags.SignedInfo;
-};
-
-SignedInfo.prototype.validate = function() {
-		// We don't do partial matches any more, even though encoder/decoder
-		// is still pretty generous.
-		if (null ==this.publisher || null==this.timestamp ||null== this.locator)
-			return false;
-		return true;
-};
-/*
- * Date Format 1.2.3
- * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
- * MIT license
- *
- * Includes enhancements by Scott Trenda <scott.trenda.net>
- * and Kris Kowal <cixar.com/~kris.kowal/>
- *
- * Accepts a date, a mask, or a date and a mask.
- * Returns a formatted version of the given date.
- * The date defaults to the current date/time.
- * The mask defaults to dateFormat.masks.default.
- */
-
-var DateFormat = function () {
-	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
-		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
-		timezoneClip = /[^-+\dA-Z]/g,
-		pad = function (val, len) {
-			val = String(val);
-			len = len || 2;
-			while (val.length < len) val = "0" + val;
-			return val;
-		};
-
-	// Regexes and supporting functions are cached through closure
-	return function (date, mask, utc) {
-		var dF = dateFormat;
-
-		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
-		if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
-			mask = date;
-			date = undefined;
-		}
-
-		// Passing date through Date applies Date.parse, if necessary
-		date = date ? new Date(date) : new Date;
-		if (isNaN(date)) throw SyntaxError("invalid date");
-
-		mask = String(dF.masks[mask] || mask || dF.masks["default"]);
-
-		// Allow setting the utc argument via the mask
-		if (mask.slice(0, 4) == "UTC:") {
-			mask = mask.slice(4);
-			utc = true;
-		}
-
-		var	_ = utc ? "getUTC" : "get",
-			d = date[_ + "Date"](),
-			D = date[_ + "Day"](),
-			m = date[_ + "Month"](),
-			y = date[_ + "FullYear"](),
-			H = date[_ + "Hours"](),
-			M = date[_ + "Minutes"](),
-			s = date[_ + "Seconds"](),
-			L = date[_ + "Milliseconds"](),
-			o = utc ? 0 : date.getTimezoneOffset(),
-			flags = {
-				d:    d,
-				dd:   pad(d),
-				ddd:  dF.i18n.dayNames[D],
-				dddd: dF.i18n.dayNames[D + 7],
-				m:    m + 1,
-				mm:   pad(m + 1),
-				mmm:  dF.i18n.monthNames[m],
-				mmmm: dF.i18n.monthNames[m + 12],
-				yy:   String(y).slice(2),
-				yyyy: y,
-				h:    H % 12 || 12,
-				hh:   pad(H % 12 || 12),
-				H:    H,
-				HH:   pad(H),
-				M:    M,
-				MM:   pad(M),
-				s:    s,
-				ss:   pad(s),
-				l:    pad(L, 3),
-				L:    pad(L > 99 ? Math.round(L / 10) : L),
-				t:    H < 12 ? "a"  : "p",
-				tt:   H < 12 ? "am" : "pm",
-				T:    H < 12 ? "A"  : "P",
-				TT:   H < 12 ? "AM" : "PM",
-				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
-				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
-				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
-			};
-
-		return mask.replace(token, function ($0) {
-			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
-		});
-	};
-}();
-
-// Some common format strings
-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'"
-};
-
-// Internationalization strings
-DateFormat.i18n = {
-	dayNames: [
-		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
-		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
-	],
-	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"
-	]
-};
-
-// For convenience...
-Date.prototype.format = function (mask, utc) {
-	return dateFormat(this, mask, utc);
-};
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Interest Objects
- */
-
-// _interestLifetime is in milliseconds.
-var Interest = function Interest
-   (_name, _faceInstance, _minSuffixComponents, _maxSuffixComponents, _publisherPublicKeyDigest, _exclude, 
-    _childSelector, _answerOriginKind, _scope, _interestLifetime, _nonce) {
-		
-	this.name = _name;
-	this.faceInstance = _faceInstance;
-	this.maxSuffixComponents = _maxSuffixComponents;
-	this.minSuffixComponents = _minSuffixComponents;
-	
-	this.publisherPublicKeyDigest = _publisherPublicKeyDigest;
-	this.exclude = _exclude;
-	this.childSelector = _childSelector;
-	this.answerOriginKind = _answerOriginKind;
-	this.scope = _scope;
-	this.interestLifetime = _interestLifetime;  // milli seconds
-	this.nonce = _nonce;	
-};
-
-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;		// Stale answer OK
-Interest.MARK_STALE = 16;		// Must have scope 0.  Michael calls this a "hack"
-
-Interest.DEFAULT_ANSWER_ORIGIN_KIND = Interest.ANSWER_CONTENT_STORE | Interest.ANSWER_GENERATED;
-
-
-Interest.prototype.from_ndnb = function(/*XMLDecoder*/ decoder) {
-
-		decoder.readStartElement(NDNProtocolDTags.Interest);
-
-		this.name = new Name();
-		this.name.from_ndnb(decoder);
-
-		if (decoder.peekStartElement(NDNProtocolDTags.MinSuffixComponents))
-			this.minSuffixComponents = decoder.readIntegerElement(NDNProtocolDTags.MinSuffixComponents);
-
-		if (decoder.peekStartElement(NDNProtocolDTags.MaxSuffixComponents)) 
-			this.maxSuffixComponents = decoder.readIntegerElement(NDNProtocolDTags.MaxSuffixComponents);
-			
-		if (decoder.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)) {
-			this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
-			this.publisherPublicKeyDigest.from_ndnb(decoder);
-		}
-
-		if (decoder.peekStartElement(NDNProtocolDTags.Exclude)) {
-			this.exclude = new Exclude();
-			this.exclude.from_ndnb(decoder);
-		}
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.ChildSelector))
-			this.childSelector = decoder.readIntegerElement(NDNProtocolDTags.ChildSelector);
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.AnswerOriginKind))
-			this.answerOriginKind = decoder.readIntegerElement(NDNProtocolDTags.AnswerOriginKind);
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.Scope))
-			this.scope = decoder.readIntegerElement(NDNProtocolDTags.Scope);
-
-		if (decoder.peekStartElement(NDNProtocolDTags.InterestLifetime))
-			this.interestLifetime = 1000.0 * DataUtils.bigEndianToUnsignedInt
-                (decoder.readBinaryElement(NDNProtocolDTags.InterestLifetime)) / 4096;
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.Nonce))
-			this.nonce = decoder.readBinaryElement(NDNProtocolDTags.Nonce);
-		
-		decoder.readEndElement();
-};
-
-Interest.prototype.to_ndnb = function(/*XMLEncoder*/ encoder){
-		//Could check if name is present
-		
-		encoder.writeStartElement(NDNProtocolDTags.Interest);
-		
-		this.name.to_ndnb(encoder);
-	
-		if (null != this.minSuffixComponents) 
-			encoder.writeElement(NDNProtocolDTags.MinSuffixComponents, this.minSuffixComponents);	
-
-		if (null != this.maxSuffixComponents) 
-			encoder.writeElement(NDNProtocolDTags.MaxSuffixComponents, this.maxSuffixComponents);
-
-		if (null != this.publisherPublicKeyDigest)
-			this.publisherPublicKeyDigest.to_ndnb(encoder);
-		
-		if (null != this.exclude)
-			this.exclude.to_ndnb(encoder);
-		
-		if (null != this.childSelector) 
-			encoder.writeElement(NDNProtocolDTags.ChildSelector, this.childSelector);
-
-		if (this.DEFAULT_ANSWER_ORIGIN_KIND != this.answerOriginKind && this.answerOriginKind!=null) 
-			encoder.writeElement(NDNProtocolDTags.AnswerOriginKind, this.answerOriginKind);
-		
-		if (null != this.scope) 
-			encoder.writeElement(NDNProtocolDTags.Scope, this.scope);
-		
-		if (null != this.interestLifetime) 
-			encoder.writeElement(NDNProtocolDTags.InterestLifetime, 
-                DataUtils.nonNegativeIntToBigEndian((this.interestLifetime / 1000.0) * 4096));
-		
-		if (null != this.nonce)
-			encoder.writeElement(NDNProtocolDTags.Nonce, this.nonce);
-		
-		encoder.writeEndElement();
-
-};
-
-/*
- * Return true if this.name.match(name) and the name conforms to the interest selectors.
- */
-Interest.prototype.matches_name = function(/*Name*/ name) {
-    if (!this.name.match(name))
-        return false;
-    
-    if (this.minSuffixComponents != null &&
-        // Add 1 for the implicit digest.
-        !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
-        return false;
-    if (this.maxSuffixComponents != null &&
-        // Add 1 for the implicit digest.
-        !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
-        return false;
-    if (this.exclude != null && name.components.length > this.name.components.length &&
-        this.exclude.matches(name.components[this.name.components.length]))
-        return false;
-    
-    return true;
-};
-
-/*
- * Return a new Interest with the same fields as this Interest.  
- * Note: This does NOT make a deep clone of the name, exclue or other objects.
- */
-Interest.prototype.clone = function() {
-    return new Interest
-       (this.name, this.faceInstance, this.minSuffixComponents, this.maxSuffixComponents, 
-        this.publisherPublicKeyDigest, this.exclude, this.childSelector, this.answerOriginKind, 
-        this.scope, this.interestLifetime, this.nonce);
-};
-
-/*
- * Handle the interest Exclude element.
- * _values is an array where each element is either Uint8Array component or Exclude.ANY.
- */
-var Exclude = function Exclude(_values) { 
-	this.values = (_values || []);
-}
-
-Exclude.ANY = "*";
-
-Exclude.prototype.from_ndnb = function(/*XMLDecoder*/ decoder) {
-	decoder.readStartElement(NDNProtocolDTags.Exclude);
-
-	while (true) {
-        if (decoder.peekStartElement(NDNProtocolDTags.Component))
-            this.values.push(decoder.readBinaryElement(NDNProtocolDTags.Component));
-        else if (decoder.peekStartElement(NDNProtocolDTags.Any)) {
-            decoder.readStartElement(NDNProtocolDTags.Any);
-            decoder.readEndElement();
-            this.values.push(Exclude.ANY);
-        }
-        else if (decoder.peekStartElement(NDNProtocolDTags.Bloom)) {
-            // Skip the Bloom and treat it as Any.
-            decoder.readBinaryElement(NDNProtocolDTags.Bloom);
-            this.values.push(Exclude.ANY);
-        }
-        else
-            break;
-	}
-    
-    decoder.readEndElement();
-};
-
-Exclude.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)  {
-	if (this.values == null || this.values.length == 0)
-		return;
-
-	encoder.writeStartElement(NDNProtocolDTags.Exclude);
-    
-    // TODO: Do we want to order the components (except for ANY)?
-    for (var i = 0; i < this.values.length; ++i) {
-        if (this.values[i] == Exclude.ANY) {
-            encoder.writeStartElement(NDNProtocolDTags.Any);
-            encoder.writeEndElement();
-        }
-        else
-            encoder.writeElement(NDNProtocolDTags.Component, this.values[i]);
-    }
-
-	encoder.writeEndElement();
-};
-
-/*
- * Return a string with elements separated by "," and Exclude.ANY shown as "*". 
- */
-Exclude.prototype.to_uri = function() {
-	if (this.values == null || this.values.length == 0)
-		return "";
-
-    var result = "";
-    for (var i = 0; i < this.values.length; ++i) {
-        if (i > 0)
-            result += ",";
-        
-        if (this.values[i] == Exclude.ANY)
-            result += "*";
-        else
-            result += Name.toEscapedString(this.values[i]);
-    }
-    return result;
-};
-
-/*
- * Return true if the component matches any of the exclude criteria.
- */
-Exclude.prototype.matches = function(/*Uint8Array*/ component) {
-    for (var i = 0; i < this.values.length; ++i) {
-        if (this.values[i] == Exclude.ANY) {
-            var lowerBound = null;
-            if (i > 0)
-                lowerBound = this.values[i - 1];
-            
-            // Find the upper bound, possibly skipping over multiple ANY in a row.
-            var iUpperBound;
-            var upperBound = null;
-            for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
-                if (this.values[iUpperBound] != Exclude.ANY) {
-                    upperBound = this.values[iUpperBound];
-                    break;
-                }
-            }
-            
-            // If lowerBound != null, we already checked component equals lowerBound on the last pass.
-            // If upperBound != null, we will check component equals upperBound on the next pass.
-            if (upperBound != null) {
-                if (lowerBound != null) {
-                    if (Exclude.compareComponents(component, lowerBound) > 0 &&
-                        Exclude.compareComponents(component, upperBound) < 0)
-                        return true;
-                }
-                else {
-                    if (Exclude.compareComponents(component, upperBound) < 0)
-                        return true;
-                }
-                
-                // Make i equal iUpperBound on the next pass.
-                i = iUpperBound - 1;
-            }
-            else {
-                if (lowerBound != null) {
-                    if (Exclude.compareComponents(component, lowerBound) > 0)
-                        return true;
-                }
-                else
-                    // this.values has only ANY.
-                    return true;
-            }
-        }
-        else {
-            if (DataUtils.arraysEqual(component, this.values[i]))
-                return true;
-        }
-    }
-    
-    return false;
-};
-
-/*
- * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
- * A component is less if it is shorter, otherwise if equal length do a byte comparison.
- */
-Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
-    if (component1.length < component2.length)
-        return -1;
-    if (component1.length > component2.length)
-        return 1;
-    
-    for (var i = 0; i < component1.length; ++i) {
-        if (component1[i] < component2[i])
-            return -1;
-        if (component1[i] > component2[i])
-            return 1;
-    }
-
-    return 0;
-};
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Key Objects
- */
-
-var Key = function Key(){
-    /* TODO: Port from PyNDN:
-	generateRSA()
-	privateToDER()
-	publicToDER()
-	privateToPEM()
-	publicToPEM()
-	fromDER()
-	fromPEM()
+}(this, function() {
+    /**
+     * Main function giving a function stack trace with a forced or passed in Error
+     *
+     * @cfg {Error} e The error to create a stacktrace from (optional)
+     * @cfg {Boolean} guess If we should try to resolve the names of anonymous functions
+     * @return {Array} of Strings with functions, lines, files, and arguments where possible
      */
-}
-
-/**
- * KeyLocator
- */
-var KeyLocatorType = {
-	KEY:1,
-	CERTIFICATE:2,
-	KEYNAME:3
-};
-
-var KeyLocator = function KeyLocator(_input,_type){ 
-
-    this.type = _type;
-    
-    if (_type == KeyLocatorType.KEYNAME){
-    	if (LOG>3) console.log('KeyLocator: SET KEYNAME');
-    	this.keyName = _input;
-    }
-    else if (_type == KeyLocatorType.KEY){
-    	if (LOG>3) console.log('KeyLocator: SET KEY');
-    	this.publicKey = _input;
-    }
-    else if (_type == KeyLocatorType.CERTIFICATE){
-    	if (LOG>3) console.log('KeyLocator: SET CERTIFICATE');
-    	this.certificate = _input;
+    function printStackTrace(options) {
+        options = options || {guess: true};
+        var ex = options.e || null, guess = !!options.guess, mode = options.mode || null;
+        var p = new printStackTrace.implementation(), result = p.run(ex, mode);
+        return (guess) ? p.guessAnonymousFunctions(result) : result;
     }
 
-};
+    printStackTrace.implementation = function() {
+    };
 
-KeyLocator.prototype.from_ndnb = function(decoder) {
+    printStackTrace.implementation.prototype = {
+        /**
+         * @param {Error} [ex] The error to create a stacktrace from (optional)
+         * @param {String} [mode] Forced mode (optional, mostly for unit tests)
+         */
+        run: function(ex, mode) {
+            ex = ex || this.createException();
+            mode = mode || this.mode(ex);
+            if (mode === 'other') {
+                return this.other(arguments.callee);
+            } else {
+                return this[mode](ex);
+            }
+        },
 
-	decoder.readStartElement(this.getElementLabel());
+        createException: function() {
+            try {
+                this.undef();
+            } catch (e) {
+                return e;
+            }
+        },
 
-	if (decoder.peekStartElement(NDNProtocolDTags.Key)) {
-		try {
-			var encodedKey = decoder.readBinaryElement(NDNProtocolDTags.Key);
-			// This is a DER-encoded SubjectPublicKeyInfo.
-			
-			//TODO FIX THIS, This should create a Key Object instead of keeping bytes
+        /**
+         * Mode could differ for different exception, e.g.
+         * exceptions in Chrome may or may not have arguments or stack.
+         *
+         * @return {String} mode of operation for the exception
+         */
+        mode: function(e) {
+            if (typeof window !== 'undefined' && window.navigator.userAgent.indexOf('PhantomJS') > -1) {
+                return 'phantomjs';
+            }
 
-			this.publicKey =   encodedKey;//CryptoUtil.getPublicKey(encodedKey);
-			this.type = KeyLocatorType.KEY;
-			
+            if (e['arguments'] && e.stack) {
+                return 'chrome';
+            }
 
-			if(LOG>4) console.log('PUBLIC KEY FOUND: '+ this.publicKey);
-			//this.publicKey = encodedKey;
-			
-			
-		} catch (e) {
-			throw new Error("Cannot parse key: ", e);
-		} 
+            if (e.stack && e.sourceURL) {
+                return 'safari';
+            }
 
-		if (null == this.publicKey) {
-			throw new Error("Cannot parse key: ");
-		}
+            if (e.stack && e.number) {
+                return 'ie';
+            }
 
-	} else if ( decoder.peekStartElement(NDNProtocolDTags.Certificate)) {
-		try {
-			var encodedCert = decoder.readBinaryElement(NDNProtocolDTags.Certificate);
-			
-			/*
-			 * Certificates not yet working
-			 */
-			
-			//CertificateFactory factory = CertificateFactory.getInstance("X.509");
-			//this.certificate = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(encodedCert));
-			
+            if (e.stack && e.fileName) {
+                return 'firefox';
+            }
 
-			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_ndnb(decoder);
-	}
-	decoder.readEndElement();
-};
-	
-
-KeyLocator.prototype.to_ndnb = 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(NDNProtocolDTags.Key, this.publicKey);
-		
-	} else if (this.type == KeyLocatorType.CERTIFICATE) {
-		
-		try {
-			encoder.writeElement(NDNProtocolDTags.Certificate, this.certificate);
-		} catch ( e) {
-			throw new Error("CertificateEncodingException attempting to write key locator: " + e);
-		}
-		
-	} else if (this.type == KeyLocatorType.KEYNAME) {
-		
-		this.keyName.to_ndnb(encoder);
-	}
-	encoder.writeEndElement();
-	
-};
-
-KeyLocator.prototype.getElementLabel = function() {
-	return NDNProtocolDTags.KeyLocator; 
-};
-
-KeyLocator.prototype.validate = function() {
-	return (  (null != this.keyName) || (null != this.publicKey) || (null != this.certificate)   );
-};
-
-/**
- * KeyName is only used by KeyLocator.
- */
-var KeyName = function KeyName() {
-	this.contentName = this.contentName;  //contentName
-	this.publisherID = this.publisherID;  //publisherID
-
-};
-
-KeyName.prototype.from_ndnb=function( decoder){
-	
-
-	decoder.readStartElement(this.getElementLabel());
-
-	this.contentName = new Name();
-	this.contentName.from_ndnb(decoder);
-	
-	if(LOG>4) console.log('KEY NAME FOUND: ');
-	
-	if ( PublisherID.peek(decoder) ) {
-		this.publisherID = new PublisherID();
-		this.publisherID.from_ndnb(decoder);
-	}
-	
-	decoder.readEndElement();
-};
-
-KeyName.prototype.to_ndnb = function( encoder) {
-	if (!this.validate()) {
-		throw new Error("Cannot encode : field values missing.");
-	}
-	
-	encoder.writeStartElement(this.getElementLabel());
-	
-	this.contentName.to_ndnb(encoder);
-	if (null != this.publisherID)
-		this.publisherID.to_ndnb(encoder);
-
-	encoder.writeEndElement();   		
-};
-	
-KeyName.prototype.getElementLabel = function() { return NDNProtocolDTags.KeyName; };
-
-KeyName.prototype.validate = function() {
-		// DKS -- do we do recursive validation?
-		// null signedInfo ok
-		return (null != this.contentName);
-};
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Publisher and PublisherType Objects
- */
-
-
-var PublisherType = function PublisherType(_tag){
-    	this.KEY =(NDNProtocolDTags.PublisherPublicKeyDigest);
-    	this.CERTIFICATE= (NDNProtocolDTags.PublisherCertificateDigest);
-    	this.ISSUER_KEY=	(NDNProtocolDTags.PublisherIssuerKeyDigest);
-    	this.ISSUER_CERTIFICATE	=(NDNProtocolDTags.PublisherIssuerCertificateDigest);
-
-    	this.Tag = _tag;
-}; 
-
-var isTypeTagVal = function(tagVal) {
-		if ((tagVal == NDNProtocolDTags.PublisherPublicKeyDigest) ||
-			(tagVal == NDNProtocolDTags.PublisherCertificateDigest) ||
-			(tagVal == NDNProtocolDTags.PublisherIssuerKeyDigest) ||
-			(tagVal == NDNProtocolDTags.PublisherIssuerCertificateDigest)) {
-			return true;
-		}
-		return false;
-};
-
-
-
-
-var PublisherID = function PublisherID() {
-
-	this.PUBLISHER_ID_DIGEST_ALGORITHM = "SHA-256";
-	this.PUBLISHER_ID_LEN = 256/8;
-    
-	//TODO, implement publisherID creation and key creation
-
-    //TODO implement generatePublicKeyDigest
-    this.publisherID =null;//= generatePublicKeyDigest(key);//ByteArray
-    
-    //TODO implement generate key
-    //CryptoUtil.generateKeyID(PUBLISHER_ID_DIGEST_ALGORITHM, key);
-    this.publisherType = null;//isIssuer ? PublisherType.ISSUER_KEY : PublisherType.KEY;//publisher Type
-    
-};
-
-
-PublisherID.prototype.from_ndnb = function(decoder) {
-		
-		// We have a choice here of one of 4 binary element types.
-		var nextTag = decoder.peekStartElementAsLong();
-		
-		if (null == nextTag) {
-			throw new Error("Cannot parse publisher ID.");
-		} 
-		
-		this.publisherType = new PublisherType(nextTag); 
-		
-		if (!isTypeTagVal(nextTag)) {
-			throw new Error("Invalid publisher ID, got unexpected type: " + nextTag);
-		}
-		this.publisherID = decoder.readBinaryElement(nextTag);
-		if (null == this.publisherID) {
-			throw new ContentDecodingException(new Error("Cannot parse publisher ID of type : " + nextTag + "."));
-		}
-};
-
-PublisherID.prototype.to_ndnb = function(encoder) {
-	if (!this.validate()) {
-		throw new Error("Cannot encode " + this.getClass().getName() + ": field values missing.");
-	}
-
-	encoder.writeElement(this.getElementLabel(), this.publisherID);
-};
-	
-PublisherID.peek = function(/* XMLDecoder */ decoder) {
-
-		//Long
-		var nextTag = decoder.peekStartElementAsLong();
-		
-		if (null == nextTag) {
-			// on end element
-			return false;
-		}
-		return (isTypeTagVal(nextTag));
-	};
-
-PublisherID.prototype.getElementLabel = function() { 
-	return this.publisherType.Tag;
-};
-
-PublisherID.prototype.validate = function(){
-	return ((null != id() && (null != type())));
-};
-
-
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents PublisherPublicKeyDigest Objects
- */
-var PublisherPublicKeyDigest = function PublisherPublicKeyDigest(_pkd){ 
-	
- 	 //this.PUBLISHER_ID_LEN = 256/8;
-	 this.PUBLISHER_ID_LEN = 512/8;
- 	 
-
-	 this.publisherPublicKeyDigest = _pkd;
- 	 //if( typeof _pkd == "object") this.publisherPublicKeyDigest = _pkd; // Byte Array
- 	 //else if( typeof _pkd == "PublicKey") ;//TODO...
-    
-};
-
-PublisherPublicKeyDigest.prototype.from_ndnb = function( decoder) {		
-
-		this.publisherPublicKeyDigest = decoder.readBinaryElement(this.getElementLabel());
-		
-		if(LOG>4)console.log('Publisher public key digest is ' + this.publisherPublicKeyDigest);
-
-		if (null == this.publisherPublicKeyDigest) {
-			throw new Error("Cannot parse publisher key digest.");
-		}
-		
-		//TODO check if the length of the PublisherPublicKeyDigest is correct ( Security reason)
-
-		if (this.publisherPublicKeyDigest.length != this.PUBLISHER_ID_LEN) {
-			if (LOG > 0)
-                console.log('LENGTH OF PUBLISHER ID IS WRONG! Expected ' + this.PUBLISHER_ID_LEN + ", got " + this.publisherPublicKeyDigest.length);
-			
-			//this.publisherPublicKeyDigest = new PublisherPublicKeyDigest(this.PublisherPublicKeyDigest).PublisherKeyDigest;		
-		}
-	};
-
-PublisherPublicKeyDigest.prototype.to_ndnb= function( encoder) {
-		//TODO Check that the ByteArray for the key is present
-		if (!this.validate()) {
-			throw new Error("Cannot encode : field values missing.");
-		}
-		if(LOG>3) console.log('PUBLISHER KEY DIGEST IS'+this.publisherPublicKeyDigest);
-		encoder.writeElement(this.getElementLabel(), this.publisherPublicKeyDigest);
-};
-	
-PublisherPublicKeyDigest.prototype.getElementLabel = function() { return NDNProtocolDTags.PublisherPublicKeyDigest; };
-
-PublisherPublicKeyDigest.prototype.validate =function() {
-		return (null != this.publisherPublicKeyDigest);
-};
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Face Instances
- */
-
-var NetworkProtocol = { TCP:6, UDP:17};
-
-var FaceInstance  = function FaceInstance(
-	    _action,
-		_publisherPublicKeyDigest,
-		_faceID,
-		_ipProto,
-		_host,
-		_port,
-		_multicastInterface,
-		_multicastTTL,
-		_freshnessSeconds){
-	
-
-	this.action = _action;
-	this.publisherPublicKeyDigest = _publisherPublicKeyDigest;
-	this.faceID = _faceID;
-	this.ipProto = _ipProto;
-	this.host = _host;
-	this.Port = _port;
-	this.multicastInterface =_multicastInterface;
-	this.multicastTTL =_multicastTTL;
-	this.freshnessSeconds = _freshnessSeconds;
-	
-	//action           ::= ("newface" | "destroyface" | "queryface")
-	//publisherPublicKeyDigest ::= SHA-256 digest
-	//faceID           ::= nonNegativeInteger
-	//ipProto          ::= nonNegativeInteger [IANA protocol number, 6=TCP, 17=UDP]
-	//Host             ::= textual representation of numeric IPv4 or IPv6 address
-	//Port             ::= nonNegativeInteger [1..65535]
-	//MulticastInterface ::= textual representation of numeric IPv4 or IPv6 address
-	//MulticastTTL     ::= nonNegativeInteger [1..255]
-	//freshnessSeconds ::= nonNegativeInteger
-
-};
-
-/**
- * Used by NetworkObject to decode the object from a network stream.
- */
-FaceInstance.prototype.from_ndnb = function(//XMLDecoder 
-	decoder) {
-
-	decoder.readStartElement(this.getElementLabel());
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.Action)) {
-		
-		this.action = decoder.readUTF8Element(NDNProtocolDTags.Action);
-		
-	}
-	if (decoder.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)) {
-		
-		this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
-		this.publisherPublicKeyDigest.from_ndnb(decoder);
-		
-	}
-	if (decoder.peekStartElement(NDNProtocolDTags.FaceID)) {
-		
-		this.faceID = decoder.readIntegerElement(NDNProtocolDTags.FaceID);
-		
-	}
-	if (decoder.peekStartElement(NDNProtocolDTags.IPProto)) {
-		
-		//int
-		var pI = decoder.readIntegerElement(NDNProtocolDTags.IPProto);
-		
-		this.ipProto = null;
-		
-		if (NetworkProtocol.TCP == pI) {
-			
-			this.ipProto = NetworkProtocol.TCP;
-			
-		} else if (NetworkProtocol.UDP == pI) {
-			
-			this.ipProto = NetworkProtocol.UDP;
-			
-		} else {
-			
-			throw new Error("FaceInstance.decoder.  Invalid " + 
-					NDNProtocolDTags.tagToString(NDNProtocolDTags.IPProto) + " field: " + pI);
-			
-		}
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.Host)) {
-		
-		this.host = decoder.readUTF8Element(NDNProtocolDTags.Host);
-		
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.Port)) {
-		this.Port = decoder.readIntegerElement(NDNProtocolDTags.Port); 
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.MulticastInterface)) {
-		this.multicastInterface = decoder.readUTF8Element(NDNProtocolDTags.MulticastInterface); 
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.MulticastTTL)) {
-		this.multicastTTL = decoder.readIntegerElement(NDNProtocolDTags.MulticastTTL); 
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.FreshnessSeconds)) {
-		this.freshnessSeconds = decoder.readIntegerElement(NDNProtocolDTags.FreshnessSeconds); 
-	}
-	decoder.readEndElement();
-}
-
-/**
- * Used by NetworkObject to encode the object to a network stream.
- */
-FaceInstance.prototype.to_ndnb = function(//XMLEncoder
-	encoder){
-
-	//if (!this.validate()) {
-		//throw new Error("Cannot encode : field values missing.");
-		//throw new Error("")
-	//}
-	encoder.writeStartElement(this.getElementLabel());
-	
-	if (null != this.action && this.action.length != 0)
-		encoder.writeElement(NDNProtocolDTags.Action, this.action);	
-	
-	if (null != this.publisherPublicKeyDigest) {
-		this.publisherPublicKeyDigest.to_ndnb(encoder);
-	}
-	if (null != this.faceID) {
-		encoder.writeElement(NDNProtocolDTags.FaceID, this.faceID);
-	}
-	if (null != this.ipProto) {
-		//encoder.writeElement(NDNProtocolDTags.IPProto, this.IpProto.value());
-		encoder.writeElement(NDNProtocolDTags.IPProto, this.ipProto);
-	}
-	if (null != this.host && this.host.length != 0) {
-		encoder.writeElement(NDNProtocolDTags.Host, this.host);	
-	}
-	if (null != this.Port) {
-		encoder.writeElement(NDNProtocolDTags.Port, this.Port);
-	}
-	if (null != this.multicastInterface && this.multicastInterface.length != 0) {
-		encoder.writeElement(NDNProtocolDTags.MulticastInterface, this.multicastInterface);
-	}
-	if (null !=  this.multicastTTL) {
-		encoder.writeElement(NDNProtocolDTags.MulticastTTL, this.multicastTTL);
-	}
-	if (null != this.freshnessSeconds) {
-		encoder.writeElement(NDNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
-	}
-	encoder.writeEndElement();   			
-}
-
-
-FaceInstance.prototype.getElementLabel= function(){return NDNProtocolDTags.FaceInstance;};
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Forwarding Entries
- */
-
-var ForwardingEntry = function ForwardingEntry(
-                                               //ActionType 
-		_action, 
-		//Name 
-		_prefixName, 
-		//PublisherPublicKeyDigest
-		_ndndId, 
-		//Integer 
-		_faceID, 
-		//Integer 
-		_flags, 
-		//Integer 
-		_lifetime){
-		
-		
-	
-		//String
-	this.action = _action;
-		//Name\
-	this.prefixName = _prefixName;
-		//PublisherPublicKeyDigest 
-	this.ndndID = _ndndId;
-		//Integer		
-	this.faceID = _faceID;
-		//Integer		
-	this.flags = _flags;
-		//Integer 		
-	this.lifetime = _lifetime;  // in seconds
-
-};
-
-ForwardingEntry.prototype.from_ndnb =function(
-	//XMLDecoder 
-	decoder) 
-	//throws ContentDecodingException
-	{
-			decoder.readStartElement(this.getElementLabel());
-			if (decoder.peekStartElement(NDNProtocolDTags.Action)) {
-				this.action = decoder.readUTF8Element(NDNProtocolDTags.Action); 
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.Name)) {
-				this.prefixName = new Name();
-				this.prefixName.from_ndnb(decoder) ;
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)) {
-				this.NdndId = new PublisherPublicKeyDigest();
-				this.NdndId.from_ndnb(decoder);
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.FaceID)) {
-				this.faceID = decoder.readIntegerElement(NDNProtocolDTags.FaceID); 
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.ForwardingFlags)) {
-				this.flags = decoder.readIntegerElement(NDNProtocolDTags.ForwardingFlags); 
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.FreshnessSeconds)) {
-				this.lifetime = decoder.readIntegerElement(NDNProtocolDTags.FreshnessSeconds); 
-			}
-			decoder.readEndElement();
-		};
-
-		/**
-		 * Used by NetworkObject to encode the object to a network stream.
-		 */
-ForwardingEntry.prototype.to_ndnb =function(
-	//XMLEncoder 
-encoder) 
-{
-
-
-			//if (!validate()) {
-				//throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
-			//}
-			encoder.writeStartElement(this.getElementLabel());
-			if (null != this.action && this.action.length != 0)
-				encoder.writeElement(NDNProtocolDTags.Action, this.action);	
-			if (null != this.prefixName) {
-				this.prefixName.to_ndnb(encoder);
-			}
-			if (null != this.NdndId) {
-				this.NdndId.to_ndnb(encoder);
-			}
-			if (null != this.faceID) {
-				encoder.writeElement(NDNProtocolDTags.FaceID, this.faceID);
-			}
-			if (null != this.flags) {
-				encoder.writeElement(NDNProtocolDTags.ForwardingFlags, this.flags);
-			}
-			if (null != this.lifetime) {
-				encoder.writeElement(NDNProtocolDTags.FreshnessSeconds, this.lifetime);
-			}
-			encoder.writeEndElement();   			
-		};
-
-ForwardingEntry.prototype.getElementLabel = function() { return NDNProtocolDTags.ForwardingEntry; }
-/**
- * @author: Jeff Thompson
- * See COPYING for copyright and distribution information.
- * Encapsulate an Uint8Array and support dynamic reallocation.
- */
-
-/*
- * Create a DynamicUint8Array where this.array is a Uint8Array of size length.
- * If length is not supplied, use a default initial length.
- * The methods will update this.length.
- * To access the array, use this.array or call subarray.
- */
-var DynamicUint8Array = function DynamicUint8Array(length) {
-	if (!length)
-        length = 16;
-    
-    this.array = new Uint8Array(length);
-    this.length = length;
-};
-
-/*
- * Ensure that this.array has the length, reallocate and copy if necessary.
- * Update this.length which may be greater than length.
- */
-DynamicUint8Array.prototype.ensureLength = function(length) {
-    if (this.array.length >= length)
-        return;
-    
-    // See if double is enough.
-    var newLength = this.array.length * 2;
-    if (length > newLength)
-        // The needed length is much greater, so use it.
-        newLength = length;
-    
-    var newArray = new Uint8Array(newLength);
-    newArray.set(this.array);
-    this.array = newArray;
-    this.length = newLength;
-};
-
-/*
- * Call this.array.set(value, offset), reallocating if necessary. 
- */
-DynamicUint8Array.prototype.set = function(value, offset) {
-    this.ensureLength(value.length + offset);
-    this.array.set(value, offset);
-};
-
-/*
- * Return this.array.subarray(begin, end);
- */
-DynamicUint8Array.prototype.subarray = function(begin, end) {
-    return this.array.subarray(begin, end);
-}
-/**
- * This class is used to encode ndnb binary elements (blob, type/value pairs).
- * 
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- */
-
-var XML_EXT = 0x00; 
-	
-var XML_TAG = 0x01; 
-	
-var XML_DTAG = 0x02; 
-	
-var XML_ATTR = 0x03; 
- 
-var XML_DATTR = 0x04; 
-	
-var XML_BLOB = 0x05; 
-	
-var XML_UDATA = 0x06; 
-	
-var XML_CLOSE = 0x0;
-
-var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
-
-
-var XML_TT_BITS = 3;
-var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
-var XML_TT_VAL_BITS = XML_TT_BITS + 1;
-var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
-var XML_REG_VAL_BITS = 7;
-var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
-var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
-var BYTE_MASK = 0xFF;
-var LONG_BYTES = 8;
-var LONG_BITS = 64;
-	
-var bits_11 = 0x0000007FF;
-var bits_18 = 0x00003FFFF;
-var bits_32 = 0x0FFFFFFFF;
-
-
-var BinaryXMLEncoder = function BinaryXMLEncoder(){
-	this.ostream = new DynamicUint8Array(100);
-	this.offset =0;
-	this.CODEC_NAME = "Binary";
-};
-
-/*
- * Encode utf8Content as utf8.
- */
-BinaryXMLEncoder.prototype.writeUString = function(/*String*/ utf8Content) {
-	this.encodeUString(utf8Content, XML_UDATA);
-};
-
-
-BinaryXMLEncoder.prototype.writeBlob = function(
-		/*Uint8Array*/ binaryContent
-		) {
-	
-	if(LOG >3) console.log(binaryContent);
-	
-	this.encodeBlob(binaryContent, binaryContent.length);
-};
-
-
-BinaryXMLEncoder.prototype.writeStartElement = function(
-	/*String*/ tag, 
-	/*TreeMap<String,String>*/ attributes
-	) {
-
-	/*Long*/ var dictionaryVal = tag; //stringToTag(tag);
-	
-	if (null == dictionaryVal) {
-		this.encodeUString(tag, XML_TAG);
-	} else {
-		this.encodeTypeAndVal(XML_DTAG, dictionaryVal);
-	}
-	
-	if (null != attributes) {
-		this.writeAttributes(attributes); 
-	}
-};
-
-
-BinaryXMLEncoder.prototype.writeEndElement = function() {
-    this.ostream.ensureLength(this.offset + 1);
-	this.ostream.array[this.offset] = XML_CLOSE;
-	this.offset += 1;
-}
-
-
-BinaryXMLEncoder.prototype.writeAttributes = function(/*TreeMap<String,String>*/ attributes) {
-	if (null == attributes) {
-		return;
-	}
-
-	// the keySet of a TreeMap is sorted.
-
-	for(var i=0; i<attributes.length;i++){
-		var strAttr = attributes[i].k;
-		var strValue = attributes[i].v;
-
-		var dictionaryAttr = stringToTag(strAttr);
-		if (null == dictionaryAttr) {
-			// not in dictionary, encode as attr
-			// compressed format wants length of tag represented as length-1
-			// to save that extra bit, as tag cannot be 0 length.
-			// encodeUString knows to do that.
-			this.encodeUString(strAttr, XML_ATTR);
-		} else {
-			this.encodeTypeAndVal(XML_DATTR, dictionaryAttr);
-		}
-		// Write value
-		this.encodeUString(strValue);
-		
-	}
-}
-
-
-//returns a string
-stringToTag = function(/*long*/ tagVal) {
-	if ((tagVal >= 0) && (tagVal < NDNProtocolDTagsStrings.length)) {
-		return NDNProtocolDTagsStrings[tagVal];
-	} else if (tagVal == NDNProtocolDTags.NDNProtocolDataUnit) {
-		return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT;
-	}
-	return null;
-};
-
-//returns a Long
-tagToString =  function(/*String*/ tagName) {
-	// the slow way, but right now we don't care.... want a static lookup for the forward direction
-	for (var i=0; i < NDNProtocolDTagsStrings.length; ++i) {
-		if ((null != NDNProtocolDTagsStrings[i]) && (NDNProtocolDTagsStrings[i] == tagName)) {
-			return i;
-		}
-	}
-	if (NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT == tagName) {
-		return NDNProtocolDTags.NDNProtocolDataUnit;
-	}
-	return null;
-};
-
-/*
- * If Content is a string, then encode as utf8 and write UDATA.
- */
-BinaryXMLEncoder.prototype.writeElement = function(
-		//long 
-		tag, 
-		//byte[] 
-		Content,
-		//TreeMap<String, String> 
-		attributes
-		) {
-	this.writeStartElement(tag, attributes);
-	// Will omit if 0-length
-	
-	if(typeof Content === 'number') {
-		if(LOG>4) console.log('GOING TO WRITE THE NUMBER .charCodeAt(0) ' + Content.toString().charCodeAt(0) );
-		if(LOG>4) console.log('GOING TO WRITE THE NUMBER ' + Content.toString() );
-		if(LOG>4) console.log('type of number is ' + typeof Content.toString() );
-		
-		this.writeUString(Content.toString());
-		//whatever
-	}
-	else if(typeof Content === 'string'){
-		if(LOG>4) console.log('GOING TO WRITE THE STRING  ' + Content );
-		if(LOG>4) console.log('type of STRING is ' + typeof Content );
-		
-		this.writeUString(Content);
-	}
-	else{
-		if(LOG>4) console.log('GOING TO WRITE A BLOB  ' + Content );
-
-		this.writeBlob(Content);
-	}
-	
-	this.writeEndElement();
-}
-
-
-
-var TypeAndVal = function TypeAndVal(_type,_val) {
-	this.type = _type;
-	this.val = _val;
-	
-};
-
-
-BinaryXMLEncoder.prototype.encodeTypeAndVal = function(
-		//int
-		type, 
-		//long 
-		val
-		) {
-	
-	if(LOG>4) console.log('Encoding type '+ type+ ' and value '+ val);
-	
-	if(LOG>4) console.log('OFFSET IS ' + this.offset);
-	
-	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
-		throw new Error("Tag and value must be positive, and tag valid.");
-	}
-	
-	// Encode backwards. Calculate how many bytes we need:
-	var numEncodingBytes = this.numEncodingBytes(val);
-	this.ostream.ensureLength(this.offset + numEncodingBytes);
-
-	// Bottom 4 bits of val go in last byte with tag.
-	this.ostream.array[this.offset + numEncodingBytes - 1] = 
-		//(byte)
-			(BYTE_MASK &
-					(((XML_TT_MASK & type) | 
-					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
-					 XML_TT_NO_MORE); // set top bit for last byte
-	val = val >>> XML_TT_VAL_BITS;
-	
-	// Rest of val goes into preceding bytes, 7 bits per byte, top bit
-	// is "more" flag.
-	var i = this.offset + numEncodingBytes - 2;
-	while ((0 != val) && (i >= this.offset)) {
-		this.ostream.array[i] = //(byte)
-				(BYTE_MASK & (val & XML_REG_VAL_MASK)); // leave top bit unset
-		val = val >>> XML_REG_VAL_BITS;
-		--i;
-	}
-	if (val != 0) {
-		throw new Error( "This should not happen: miscalculated encoding");
-		//Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
-	}
-	this.offset+= numEncodingBytes;
-	
-	return numEncodingBytes;
-};
-
-/*
- * Encode ustring as utf8.
- */
-BinaryXMLEncoder.prototype.encodeUString = function(
-		//String 
-		ustring, 
-		//byte 
-		type) {
-	
-	if (null == ustring)
-		return;
-	if (type == XML_TAG || type == XML_ATTR && ustring.length == 0)
-		return;
-	
-	if(LOG>3) console.log("The string to write is ");
-	if(LOG>3) console.log(ustring);
-
-	var strBytes = DataUtils.stringToUtf8Array(ustring);
-	
-	this.encodeTypeAndVal(type, 
-						(((type == XML_TAG) || (type == XML_ATTR)) ?
-								(strBytes.length-1) :
-								strBytes.length));
-	
-	if(LOG>3) console.log("THE string to write is ");
-	
-	if(LOG>3) console.log(strBytes);
-	
-	this.writeString(strBytes);
-	this.offset+= strBytes.length;
-};
-
-
-
-BinaryXMLEncoder.prototype.encodeBlob = function(
-		//Uint8Array 
-		blob, 
-		//int 
-		length) {
-
-
-	if (null == blob)
-		return;
-	
-	if(LOG>4) console.log('LENGTH OF XML_BLOB IS '+length);
-	
-	/*blobCopy = new Array(blob.Length);
-	
-	for (i = 0; i < blob.length; i++) //in InStr.ToCharArray())
-	{
-		blobCopy[i] = blob[i];
-	}*/
-
-	this.encodeTypeAndVal(XML_BLOB, length);
-
-	this.writeBlobArray(blob);
-	this.offset += length;
-};
-
-var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
-var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
-var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
-
-BinaryXMLEncoder.prototype.numEncodingBytes = function(
-		//long
-		x) {
-	if (x <= ENCODING_LIMIT_1_BYTE) return (1);
-	if (x <= ENCODING_LIMIT_2_BYTES) return (2);
-	if (x <= ENCODING_LIMIT_3_BYTES) return (3);
-	
-	var numbytes = 1;
-	
-	// Last byte gives you XML_TT_VAL_BITS
-	// Remainder each give you XML_REG_VAL_BITS
-	x = x >>> XML_TT_VAL_BITS;
-	while (x != 0) {
-        numbytes++;
-		x = x >>> XML_REG_VAL_BITS;
-	}
-	return (numbytes);
-};
-
-BinaryXMLEncoder.prototype.writeDateTime = function(
-		//String 
-		tag, 
-		//NDNTime 
-		dateTime) {
-	
-	if(LOG>4)console.log('ENCODING DATE with LONG VALUE');
-	if(LOG>4)console.log(dateTime.msec);
-	
-	//var binarydate = DataUtils.unsignedLongToByteArray( Math.round((dateTime.msec/1000) * 4096)  );
-	
-
-	//parse to hex
-	var binarydate =  Math.round((dateTime.msec/1000) * 4096).toString(16)  ;
-
-	//HACK
-	var binarydate =  DataUtils.toNumbers( '0'.concat(binarydate,'0')) ;
-
-	
-	if(LOG>4)console.log('ENCODING DATE with BINARY VALUE');
-	if(LOG>4)console.log(binarydate);
-	if(LOG>4)console.log('ENCODING DATE with BINARY VALUE(HEX)');
-	if(LOG>4)console.log(DataUtils.toHex(binarydate));
-	
-	this.writeElement(tag, binarydate);
-};
-
-// This does not update this.offset.
-BinaryXMLEncoder.prototype.writeString = function(input) {
-	
-    if(typeof input === 'string'){
-		//console.log('went here');
-    	if(LOG>4) console.log('GOING TO WRITE A STRING');
-    	if(LOG>4) console.log(input);
-        
-        this.ostream.ensureLength(this.offset + input.length);
-		for (var i = 0; i < input.length; i++) {
-			if(LOG>4) console.log('input.charCodeAt(i)=' + input.charCodeAt(i));
-		    this.ostream.array[this.offset + i] = (input.charCodeAt(i));
-		}
-	}
-    else{
-		if(LOG>4) console.log('GOING TO WRITE A STRING IN BINARY FORM');
-		if(LOG>4) console.log(input);
-		
-		this.writeBlobArray(input);
-    }
-    /*
-	else if(typeof input === 'object'){
-		
-	}	
-	*/
-};
-
-
-BinaryXMLEncoder.prototype.writeBlobArray = function(
-		//Uint8Array 
-		blob) {
-	
-	if(LOG>4) console.log('GOING TO WRITE A BLOB');
-    
-	this.ostream.set(blob, this.offset);
-};
-
-
-BinaryXMLEncoder.prototype.getReducedOstream = function() {
-	return this.ostream.subarray(0, this.offset);
-};
-
-/**
- * This class is used to decode ndnb binary elements (blob, type/value pairs).
- * 
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- */
-
-var XML_EXT = 0x00; 
-	
-var XML_TAG = 0x01; 
-	
-var XML_DTAG = 0x02; 
-	
-var XML_ATTR = 0x03; 
- 
-var XML_DATTR = 0x04; 
-	
-var XML_BLOB = 0x05; 
-	
-var XML_UDATA = 0x06; 
-	
-var XML_CLOSE = 0x0;
-
-var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
-	
-
-var XML_TT_BITS = 3;
-var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
-var XML_TT_VAL_BITS = XML_TT_BITS + 1;
-var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
-var XML_REG_VAL_BITS = 7;
-var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
-var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
-var BYTE_MASK = 0xFF;
-var LONG_BYTES = 8;
-var LONG_BITS = 64;
-	
-var bits_11 = 0x0000007FF;
-var bits_18 = 0x00003FFFF;
-var bits_32 = 0x0FFFFFFFF;
-
-
-
-//returns a string
-tagToString = function(/*long*/ tagVal) {
-	if ((tagVal >= 0) && (tagVal < NDNProtocolDTagsStrings.length)) {
-		return NDNProtocolDTagsStrings[tagVal];
-	} else if (tagVal == NDNProtocolDTags.NDNProtocolDataUnit) {
-		return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT;
-	}
-	return null;
-};
-
-//returns a Long
-stringToTag =  function(/*String*/ tagName) {
-	// the slow way, but right now we don't care.... want a static lookup for the forward direction
-	for (var i=0; i < NDNProtocolDTagsStrings.length; ++i) {
-		if ((null != NDNProtocolDTagsStrings[i]) && (NDNProtocolDTagsStrings[i] == tagName)) {
-			return i;
-		}
-	}
-	if (NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT == tagName) {
-		return NDNProtocolDTags.NDNProtocolDataUnit;
-	}
-	return null;
-};
-
-//console.log(stringToTag(64));
-var BinaryXMLDecoder = function BinaryXMLDecoder(istream){
-	var MARK_LEN=512;
-	var DEBUG_MAX_LEN =  32768;
-	
-	this.istream = istream;
-	this.offset = 0;
-};
-
-BinaryXMLDecoder.prototype.initializeDecoding = function() {
-		//if (!this.istream.markSupported()) {
-			//throw new IllegalArgumentException(this.getClass().getName() + ": input stream must support marking!");
-		//}
-}
-
-BinaryXMLDecoder.prototype.readStartDocument = function(){
-		// Currently no start document in binary encoding.
-	}
-
-BinaryXMLDecoder.prototype.readEndDocument = function() {
-		// Currently no end document in binary encoding.
-	};
-
-BinaryXMLDecoder.prototype.readStartElement = function(
-		//String 
-		startTag,
-		//TreeMap<String, String> 
-		attributes) {
-	
-		
-		//NOT SURE
-		//if(typeof startTag == 'number')
-			//startTag = tagToString(startTag);
-		
-			//TypeAndVal 
-			var tv = this.decodeTypeAndVal();
-			
-			if (null == tv) {
-				throw new ContentDecodingException(new Error("Expected start element: " + startTag + " got something not a tag."));
-			}
-			
-			//String 
-			var decodedTag = null;
-			//console.log(tv);
-			//console.log(typeof tv);
-			
-			//console.log(XML_TAG);
-			if (tv.type() == XML_TAG) {
-				//console.log('got here');
-				//Log.info(Log.FAC_ENCODING, "Unexpected: got tag in readStartElement; looking for tag " + startTag + " got length: " + (int)tv.val()+1);
-				// Tag value represents length-1 as tags can never be empty.
-				var valval ;
-				if(typeof tv.val() == 'string'){
-					valval = (parseInt(tv.val())) + 1;
-				}
-				else
-					valval = (tv.val())+ 1;
-				
-				//console.log('valval is ' +valval);
-				
-				decodedTag = this.decodeUString(valval);
-				
-			} else if (tv.type() == XML_DTAG) {
-				//console.log('gothere');
-				//console.log(tv.val());
-				//decodedTag = tagToString(tv.val());
-				//console.log()
-				decodedTag = tv.val();
-			}
-			
-			//console.log(decodedTag);
-			//console.log('startTag is '+startTag);
-			
-			
-			if ((null ==  decodedTag) || decodedTag != startTag ) {
-				console.log('expecting '+ startTag + ' but got '+ decodedTag);
-				throw new ContentDecodingException(new Error("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")"));
-			}
-			
-			// DKS: does not read attributes out of stream if caller doesn't
-			// ask for them. Should possibly peek and skip over them regardless.
-			// TODO: fix this
-			if (null != attributes) {
-				readAttributes(attributes); 
-			}
-	}
-	
-
-BinaryXMLDecoder.prototype.readAttributes = function(
-	// array of [attributeName, attributeValue] 
-	attributes) {
-	
-	if (null == attributes) {
-		return;
-	}
-
-	try {
-		// Now need to get attributes.
-		//TypeAndVal 
-		var nextTV = this.peekTypeAndVal();
-
-		while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
-				(XML_DATTR == nextTV.type()))) {
-
-			// Decode this attribute. First, really read the type and value.
-			//this.TypeAndVal 
-			var thisTV = this.decodeTypeAndVal();
-
-			//String 
-			var attributeName = null;
-			if (XML_ATTR == thisTV.type()) {
-				// Tag value represents length-1 as attribute names cannot be empty.
-				var valval ;
-				if(typeof thisTV.val() == 'string'){
-					valval = (parseInt(thisTV.val())) + 1;
-				}
-				else
-					valval = (thisTV.val())+ 1;
-				
-				attributeName = this.decodeUString(valval);
-
-			} else if (XML_DATTR == thisTV.type()) {
-				// DKS TODO are attributes same or different dictionary?
-				attributeName = tagToString(thisTV.val());
-				if (null == attributeName) {
-					throw new ContentDecodingException(new Error("Unknown DATTR value" + thisTV.val()));
-				}
-			}
-			// Attribute values are always UDATA
-			//String
-			var attributeValue = this.decodeUString();
-
-			//
-			attributes.push([attributeName, attributeValue]);
-
-			nextTV = this.peekTypeAndVal();
-		}
-	} catch ( e) {
-		throw new ContentDecodingException(new Error("readStartElement", e));
-	}
-};
-
-//returns a string
-BinaryXMLDecoder.prototype.peekStartElementAsString = function() {
-	//this.istream.mark(MARK_LEN);
-
-	//String 
-	var decodedTag = null;
-	var previousOffset = this.offset;
-	try {
-		// Have to distinguish genuine errors from wrong tags. Could either use
-		// a special exception subtype, or redo the work here.
-		//this.TypeAndVal 
-		var tv = this.decodeTypeAndVal();
-
-		if (null != tv) {
-
-			if (tv.type() == XML_TAG) {
-				/*if (tv.val()+1 > DEBUG_MAX_LEN) {
-					throw new ContentDecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!")(;
-				}*/
-
-				// Tag value represents length-1 as tags can never be empty.
-				var valval ;
-				if(typeof tv.val() == 'string'){
-					valval = (parseInt(tv.val())) + 1;
-				}
-				else
-					valval = (tv.val())+ 1;
-				
-				decodedTag = this.decodeUString(valval);
-				
-				//Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
-
-			} else if (tv.type() == XML_DTAG) {
-				decodedTag = tagToString(tv.val());					
-			}
-
-		} // else, not a type and val, probably an end element. rewind and return false.
-
-	} catch ( e) {
-
-	} finally {
-		try {
-			this.offset = previousOffset;
-		} catch ( e) {
-			Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
-			throw new ContentDecodingException(new Error("Cannot reset stream! " + e.getMessage(), e));
-		}
-	}
-	return decodedTag;
-};
-
-BinaryXMLDecoder.prototype.peekStartElement = function(
-		//String 
-		startTag) {
-	//String 
-	if(typeof startTag == 'string'){
-		var decodedTag = this.peekStartElementAsString();
-		
-		if ((null !=  decodedTag) && decodedTag == startTag) {
-			return true;
-		}
-		return false;
-	}
-	else if(typeof startTag == 'number'){
-		var decodedTag = this.peekStartElementAsLong();
-		if ((null !=  decodedTag) && decodedTag == startTag) {
-			return true;
-		}
-		return false;
-	}
-	else{
-		throw new ContentDecodingException(new Error("SHOULD BE STRING OR NUMBER"));
-	}
-}
-//returns Long
-BinaryXMLDecoder.prototype.peekStartElementAsLong = function() {
-		//this.istream.mark(MARK_LEN);
-
-		//Long
-		var decodedTag = null;
-		
-		var previousOffset = this.offset;
-		
-		try {
-			// Have to distinguish genuine errors from wrong tags. Could either use
-			// a special exception subtype, or redo the work here.
-			//this.TypeAndVal
-			var tv = this.decodeTypeAndVal();
-
-			if (null != tv) {
-
-				if (tv.type() == XML_TAG) {
-					if (tv.val()+1 > DEBUG_MAX_LEN) {
-						throw new ContentDecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!"));
-					}
-
-					var valval ;
-					if(typeof tv.val() == 'string'){
-						valval = (parseInt(tv.val())) + 1;
-					}
-					else
-						valval = (tv.val())+ 1;
-					
-					// Tag value represents length-1 as tags can never be empty.
-					//String 
-					var strTag = this.decodeUString(valval);
-					
-					decodedTag = stringToTag(strTag);
-					
-					//Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
-					
-				} else if (tv.type() == XML_DTAG) {
-					decodedTag = tv.val();					
-				}
-
-			} // else, not a type and val, probably an end element. rewind and return false.
-
-		} catch ( e) {
-			
-		} finally {
-			try {
-				//this.istream.reset();
-				this.offset = previousOffset;
-			} catch ( e) {
-				Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
-				throw new Error("Cannot reset stream! " + e.getMessage(), e);
-			}
-		}
-		return decodedTag;
-	};
-
-
-// returns a byte[]
-BinaryXMLDecoder.prototype.readBinaryElement = function(
-		//long 
-		startTag,
-		//TreeMap<String, String> 
-		attributes){
-	//byte [] 
-	var blob = null;
-	
-	this.readStartElement(startTag, attributes);
-	blob = this.readBlob();	
-
-	return blob;
-};
-	
-	
-BinaryXMLDecoder.prototype.readEndElement = function(){
-			if(LOG>4)console.log('this.offset is '+this.offset);
-			
-			var next = this.istream[this.offset]; 
-			
-			this.offset++;
-			//read();
-			
-			if(LOG>4)console.log('XML_CLOSE IS '+XML_CLOSE);
-			if(LOG>4)console.log('next is '+next);
-			
-			if (next != XML_CLOSE) {
-				console.log("Expected end element, got: " + next);
-				throw new ContentDecodingException(new Error("Expected end element, got: " + next));
-			}
-	};
-
-
-//String	
-BinaryXMLDecoder.prototype.readUString = function(){
-			//String 
-			var ustring = this.decodeUString();	
-			this.readEndElement();
-			return ustring;
-
-	};
-	
-
-//returns a uint8array
-BinaryXMLDecoder.prototype.readBlob = function() {
-			//uint8array
-			
-			var blob = this.decodeBlob();	
-			this.readEndElement();
-			return blob;
-
-	};
-
-
-//NDNTime
-BinaryXMLDecoder.prototype.readDateTime = function(
-	//long 
-	startTag)  {
-	//byte [] 
-	
-	var byteTimestamp = this.readBinaryElement(startTag);
-
-	//var lontimestamp = DataUtils.byteArrayToUnsignedLong(byteTimestamp);
-
-	byteTimestamp = DataUtils.toHex(byteTimestamp);
-	
-	
-	byteTimestamp = parseInt(byteTimestamp, 16);
-
-	var lontimestamp = (byteTimestamp/ 4096) * 1000;
-
-	//if(lontimestamp<0) lontimestamp =  - lontimestamp;
-
-	if(LOG>3) console.log('DECODED DATE WITH VALUE');
-	if(LOG>3) console.log(lontimestamp);
-	
-
-	//NDNTime 
-	var timestamp = new NDNTime(lontimestamp);
-	//timestamp.setDateBinary(byteTimestamp);
-	
-	if (null == timestamp) {
-		throw new ContentDecodingException(new Error("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp)));
-	}		
-	return timestamp;
-};
-
-BinaryXMLDecoder.prototype.decodeTypeAndVal = function() {
-	
-	/*int*/var type = -1;
-	/*long*/var val = 0;
-	/*boolean*/var more = true;
-
-	do {
-		
-		var next = this.istream[this.offset ];
-		
-		
-		if (next < 0) {
-			return null; 
-		}
-
-		if ((0 == next) && (0 == val)) {
-			return null;
-		}
-		
-		more = (0 == (next & XML_TT_NO_MORE));
-		
-		if  (more) {
-			val = val << XML_REG_VAL_BITS;
-			val |= (next & XML_REG_VAL_MASK);
-		} else {
-
-			type = next & XML_TT_MASK;
-			val = val << XML_TT_VAL_BITS;
-			val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
-		}
-		
-		this.offset++;
-		
-	} while (more);
-	
-	if(LOG>3)console.log('TYPE is '+ type + ' VAL is '+ val);
-
-	return new TypeAndVal(type, val);
-};
-
-
-
-//TypeAndVal
-BinaryXMLDecoder.peekTypeAndVal = function() {
-	//TypeAndVal 
-	var tv = null;
-	
-	//this.istream.mark(LONG_BYTES*2);		
-	
-	var previousOffset = this.offset;
-	
-	try {
-		tv = this.decodeTypeAndVal();
-	} finally {
-		//this.istream.reset();
-		this.offset = previousOffset;
-	}
-	
-	return tv;
-};
-
-
-//Uint8Array
-BinaryXMLDecoder.prototype.decodeBlob = function(
-		//int 
-		blobLength) {
-	
-	if(null == blobLength){
-		//TypeAndVal
-		var tv = this.decodeTypeAndVal();
-
-		var valval ;
-		
-		if(typeof tv.val() == 'string'){
-			valval = (parseInt(tv.val()));
-		}
-		else
-			valval = (tv.val());
-		
-		//console.log('valval here is ' + valval);
-		return  this.decodeBlob(valval);
-	}
-	
-	//
-	//Uint8Array
-	var bytes = this.istream.subarray(this.offset, this.offset+ blobLength);
-	this.offset += blobLength;
-	
-	return bytes;
-};
-
-//String
-BinaryXMLDecoder.prototype.decodeUString = function(
-		//int 
-		byteLength) {
-	if(null == byteLength ){
-		var tempStreamPosition = this.offset;
-			
-		//TypeAndVal 
-		var tv = this.decodeTypeAndVal();
-		
-		if(LOG>3)console.log('TV is '+tv);
-		if(LOG>3)console.log(tv);
-		
-		if(LOG>3)console.log('Type of TV is '+typeof tv);
-	
-		if ((null == tv) || (XML_UDATA != tv.type())) { // if we just have closers left, will get back null
-			//if (Log.isLoggable(Log.FAC_ENCODING, Level.FINEST))
-				//Log.finest(Log.FAC_ENCODING, "Expected UDATA, got " + ((null == tv) ? " not a tag " : tv.type()) + ", assuming elided 0-length blob.");
-			
-			this.offset = tempStreamPosition;
-			
-			return "";
-		}
-			
-		return this.decodeUString(tv.val());
-	}
-	else{
-		//uint8array 
-		var stringBytes = this.decodeBlob(byteLength);
-		
-		//return DataUtils.getUTF8StringFromBytes(stringBytes);
-		return  DataUtils.toString(stringBytes);
-		
-	}
-};
-
-//OBject containg a pair of type and value
-var TypeAndVal = function TypeAndVal(_type,_val) {
-	this.t = _type;
-	this.v = _val;
-};
-
-TypeAndVal.prototype.type = function(){
-	return this.t;
-};
-
-TypeAndVal.prototype.val = function(){
-	return this.v;
-};
-
-
-
-
-BinaryXMLDecoder.prototype.readIntegerElement =function(
-	//String 
-	startTag) {
-
-	//String 
-	if(LOG>4) console.log('READING INTEGER '+ startTag);
-	if(LOG>4) console.log('TYPE OF '+ typeof startTag);
-	
-	var strVal = this.readUTF8Element(startTag);
-	
-	return parseInt(strVal);
-};
-
-
-BinaryXMLDecoder.prototype.readUTF8Element =function(
-			//String 
-			startTag,
-			//TreeMap<String, String> 
-			attributes) {
-			//throws Error where name == "ContentDecodingException" 
-
-		this.readStartElement(startTag, attributes); // can't use getElementText, can't get attributes
-		//String 
-		var strElementText = this.readUString();
-		return strElementText;
-};
-
-
-/* 
- * Set the offset into the input, used for the next read.
- */
-BinaryXMLDecoder.prototype.seek = function(
-        //int
-        offset) {
-    this.offset = offset;
-}
-
-/*
- * Call with: throw new ContentDecodingException(new Error("message")).
- */
-function ContentDecodingException(error) {
-    this.message = error.message;
-    // Copy lineNumber, etc. from where new Error was called.
-    for (var prop in error)
-        this[prop] = error[prop];
-}
-ContentDecodingException.prototype = new Error();
-ContentDecodingException.prototype.name = "ContentDecodingException";
-
-/**
- * This class uses BinaryXMLDecoder to follow the structure of a ndnb binary element to 
- * determine its end.
- * 
- * @author: Jeff Thompson
- * See COPYING for copyright and distribution information.
- */
-
-var BinaryXMLStructureDecoder = function BinaryXMLDecoder() {
-    this.gotElementEnd = false;
-	this.offset = 0;
-    this.level = 0;
-    this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
-    this.headerLength = 0;
-    this.useHeaderBuffer = false;
-    this.headerBuffer = new DynamicUint8Array(5);
-    this.nBytesToRead = 0;
-};
-
-BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE = 0;
-BinaryXMLStructureDecoder.READ_BYTES = 1;
-
-/*
- * Continue scanning input starting from this.offset.  If found the end of the element
- *   which started at offset 0 then return true, else false.
- * If this returns false, you should read more into input and call again.
- * You have to pass in input each time because the array could be reallocated.
- * This throws an exception for badly formed ndnb.
- */
-BinaryXMLStructureDecoder.prototype.findElementEnd = function(
-    // Uint8Array
-    input)
-{
-    if (this.gotElementEnd)
-        // Someone is calling when we already got the end.
-        return true;
-    
-    var decoder = new BinaryXMLDecoder(input);
-    
-    while (true) {
-        if (this.offset >= input.length)
-            // All the cases assume we have some input.
-            return false;
-        
-        switch (this.state) {
-            case BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE:               
-                // First check for XML_CLOSE.
-                if (this.headerLength == 0 && input[this.offset] == XML_CLOSE) {
-                    ++this.offset;
-                    // Close the level.
-                    --this.level;
-                    if (this.level == 0)
-                        // Finished.
-                        return true;
-                    if (this.level < 0)
-                        throw new Error("BinaryXMLStructureDecoder: Unexepected close tag at offset " +
-                            (this.offset - 1));
-                    
-                    // Get ready for the next header.
-                    this.startHeader();
-                    break;
+            if (e.message && e['opera#sourceloc']) {
+                // e.message.indexOf("Backtrace:") > -1 -> opera9
+                // 'opera#sourceloc' in e -> opera9, opera10a
+                // !e.stacktrace -> opera9
+                if (!e.stacktrace) {
+                    return 'opera9'; // use e.message
                 }
-                
-                var startingHeaderLength = this.headerLength;
-                while (true) {
-                    if (this.offset >= input.length) {
-                        // We can't get all of the header bytes from this input. Save in headerBuffer.
-                        this.useHeaderBuffer = true;
-                        var nNewBytes = this.headerLength - startingHeaderLength;
-                        this.headerBuffer.set
-                            (input.subarray(this.offset - nNewBytes, nNewBytes), startingHeaderLength);
-                        
-                        return false;
-                    }
-                    var headerByte = input[this.offset++];
-                    ++this.headerLength;
-                    if (headerByte & XML_TT_NO_MORE)
-                        // Break and read the header.
-                        break;
+                if (e.message.indexOf('\n') > -1 && e.message.split('\n').length > e.stacktrace.split('\n').length) {
+                    // e.message may have more stack entries than e.stacktrace
+                    return 'opera9'; // use e.message
                 }
-                
-                var typeAndVal;
-                if (this.useHeaderBuffer) {
-                    // Copy the remaining bytes into headerBuffer.
-                    nNewBytes = this.headerLength - startingHeaderLength;
-                    this.headerBuffer.set
-                        (input.subarray(this.offset - nNewBytes, nNewBytes), startingHeaderLength);
+                return 'opera10a'; // use e.stacktrace
+            }
 
-                    typeAndVal = new BinaryXMLDecoder(this.headerBuffer.array).decodeTypeAndVal();
+            if (e.message && e.stack && e.stacktrace) {
+                // e.stacktrace && e.stack -> opera10b
+                if (e.stacktrace.indexOf("called from line") < 0) {
+                    return 'opera10b'; // use e.stacktrace, format differs from 'opera10a'
+                }
+                // e.stacktrace && e.stack -> opera11
+                return 'opera11'; // use e.stacktrace, format differs from 'opera10a', 'opera10b'
+            }
+
+            if (e.stack && !e.fileName) {
+                // Chrome 27 does not have e.arguments as earlier versions,
+                // but still does not have e.fileName as Firefox
+                return 'chrome';
+            }
+
+            return 'other';
+        },
+
+        /**
+         * Given a context, function name, and callback function, overwrite it so that it calls
+         * printStackTrace() first with a callback and then runs the rest of the body.
+         *
+         * @param {Object} context of execution (e.g. window)
+         * @param {String} functionName to instrument
+         * @param {Function} callback function to call with a stack trace on invocation
+         */
+        instrumentFunction: function(context, functionName, callback) {
+            context = context || window;
+            var original = context[functionName];
+            context[functionName] = function instrumented() {
+                callback.call(this, printStackTrace().slice(4));
+                return context[functionName]._instrumented.apply(this, arguments);
+            };
+            context[functionName]._instrumented = original;
+        },
+
+        /**
+         * Given a context and function name of a function that has been
+         * instrumented, revert the function to it's original (non-instrumented)
+         * state.
+         *
+         * @param {Object} context of execution (e.g. window)
+         * @param {String} functionName to de-instrument
+         */
+        deinstrumentFunction: function(context, functionName) {
+            if (context[functionName].constructor === Function &&
+                context[functionName]._instrumented &&
+                context[functionName]._instrumented.constructor === Function) {
+                context[functionName] = context[functionName]._instrumented;
+            }
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on Chrome's stack string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        chrome: function(e) {
+            return (e.stack + '\n')
+                .replace(/^[\s\S]+?\s+at\s+/, ' at ') // remove message
+                .replace(/^\s+(at eval )?at\s+/gm, '') // remove 'at' and indentation
+                .replace(/^([^\(]+?)([\n$])/gm, '{anonymous}() ($1)$2')
+                .replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}() ($1)')
+                .replace(/^(.+) \((.+)\)$/gm, '$1@$2')
+                .split('\n')
+                .slice(0, -1);
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on Safari's stack string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        safari: function(e) {
+            return e.stack.replace(/\[native code\]\n/m, '')
+                .replace(/^(?=\w+Error\:).*$\n/m, '')
+                .replace(/^@/gm, '{anonymous}()@')
+                .split('\n');
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on IE's stack string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        ie: function(e) {
+            return e.stack
+                .replace(/^\s*at\s+(.*)$/gm, '$1')
+                .replace(/^Anonymous function\s+/gm, '{anonymous}() ')
+                .replace(/^(.+)\s+\((.+)\)$/gm, '$1@$2')
+                .split('\n')
+                .slice(1);
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on Firefox's stack string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        firefox: function(e) {
+            return e.stack.replace(/(?:\n@:0)?\s+$/m, '')
+                .replace(/^(?:\((\S*)\))?@/gm, '{anonymous}($1)@')
+                .split('\n');
+        },
+
+        opera11: function(e) {
+            var ANON = '{anonymous}', lineRE = /^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/;
+            var lines = e.stacktrace.split('\n'), result = [];
+
+            for (var i = 0, len = lines.length; i < len; i += 2) {
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    var location = match[4] + ':' + match[1] + ':' + match[2];
+                    var fnName = match[3] || "global code";
+                    fnName = fnName.replace(/<anonymous function: (\S+)>/, "$1").replace(/<anonymous function>/, ANON);
+                    result.push(fnName + '@' + location + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
+                }
+            }
+
+            return result;
+        },
+
+        opera10b: function(e) {
+            // "<anonymous function: run>([arguments not available])@file://localhost/G:/js/stacktrace.js:27\n" +
+            // "printStackTrace([arguments not available])@file://localhost/G:/js/stacktrace.js:18\n" +
+            // "@file://localhost/G:/js/test/functional/testcase1.html:15"
+            var lineRE = /^(.*)@(.+):(\d+)$/;
+            var lines = e.stacktrace.split('\n'), result = [];
+
+            for (var i = 0, len = lines.length; i < len; i++) {
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    var fnName = match[1] ? (match[1] + '()') : "global code";
+                    result.push(fnName + '@' + match[2] + ':' + match[3]);
+                }
+            }
+
+            return result;
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on Opera 10's stacktrace string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        opera10a: function(e) {
+            // "  Line 27 of linked script file://localhost/G:/js/stacktrace.js\n"
+            // "  Line 11 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html: In function foo\n"
+            var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;
+            var lines = e.stacktrace.split('\n'), result = [];
+
+            for (var i = 0, len = lines.length; i < len; i += 2) {
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    var fnName = match[3] || ANON;
+                    result.push(fnName + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
+                }
+            }
+
+            return result;
+        },
+
+        // Opera 7.x-9.2x only!
+        opera9: function(e) {
+            // "  Line 43 of linked script file://localhost/G:/js/stacktrace.js\n"
+            // "  Line 7 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html\n"
+            var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)/i;
+            var lines = e.message.split('\n'), result = [];
+
+            for (var i = 2, len = lines.length; i < len; i += 2) {
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    result.push(ANON + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
+                }
+            }
+
+            return result;
+        },
+
+        phantomjs: function(e) {
+            var ANON = '{anonymous}', lineRE = /(\S+) \((\S+)\)/i;
+            var lines = e.stack.split('\n'), result = [];
+
+            for (var i = 1, len = lines.length; i < len; i++) {
+                lines[i] = lines[i].replace(/^\s+at\s+/gm, '');
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    result.push(match[1] + '()@' + match[2]);
                 }
                 else {
-                    // We didn't have to use the headerBuffer.
-                    decoder.seek(this.offset - this.headerLength);
-                    typeAndVal = decoder.decodeTypeAndVal();
+                    result.push(ANON + '()@' + lines[i]);
                 }
-                
-                if (typeAndVal == null)
-                    throw new Error("BinaryXMLStructureDecoder: Can't read header starting at offset " +
-                        (this.offset - this.headerLength));
-                
-                // Set the next state based on the type.
-                var type = typeAndVal.t;
-                if (type == XML_DATTR)
-                    // We already consumed the item. READ_HEADER_OR_CLOSE again.
-                    // ndnb has rules about what must follow an attribute, but we are just scanning.
-                    this.startHeader();
-                else if (type == XML_DTAG || type == XML_EXT) {
-                    // Start a new level and READ_HEADER_OR_CLOSE again.
-                    ++this.level;
-                    this.startHeader();
+            }
+
+            return result;
+        },
+
+        // Safari 5-, IE 9-, and others
+        other: function(curr) {
+            var ANON = '{anonymous}', fnRE = /function(?:\s+([\w$]+))?\s*\(/, stack = [], fn, args, maxStackSize = 10;
+            var slice = Array.prototype.slice;
+            while (curr && stack.length < maxStackSize) {
+                fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
+                try {
+                    args = slice.call(curr['arguments'] || []);
+                } catch (e) {
+                    args = ['Cannot access arguments: ' + e];
                 }
-                else if (type == XML_TAG || type == XML_ATTR) {
-                    if (type == XML_TAG)
-                        // Start a new level and read the tag.
-                        ++this.level;
-                    // Minimum tag or attribute length is 1.
-                    this.nBytesToRead = typeAndVal.v + 1;
-                    this.state = BinaryXMLStructureDecoder.READ_BYTES;
-                    // ndnb has rules about what must follow an attribute, but we are just scanning.
+                stack[stack.length] = fn + '(' + this.stringifyArguments(args) + ')';
+                try {
+                    curr = curr.caller;
+                } catch (e) {
+                    stack[stack.length] = 'Cannot access caller: ' + e;
+                    break;
                 }
-                else if (type == XML_BLOB || type == XML_UDATA) {
-                    this.nBytesToRead = typeAndVal.v;
-                    this.state = BinaryXMLStructureDecoder.READ_BYTES;
+            }
+            return stack;
+        },
+
+        /**
+         * Given arguments array as a String, substituting type names for non-string types.
+         *
+         * @param {Arguments,Array} args
+         * @return {String} stringified arguments
+         */
+        stringifyArguments: function(args) {
+            var result = [];
+            var slice = Array.prototype.slice;
+            for (var i = 0; i < args.length; ++i) {
+                var arg = args[i];
+                if (arg === undefined) {
+                    result[i] = 'undefined';
+                } else if (arg === null) {
+                    result[i] = 'null';
+                } else if (arg.constructor) {
+                    // TODO constructor comparison does not work for iframes
+                    if (arg.constructor === Array) {
+                        if (arg.length < 3) {
+                            result[i] = '[' + this.stringifyArguments(arg) + ']';
+                        } else {
+                            result[i] = '[' + this.stringifyArguments(slice.call(arg, 0, 1)) + '...' + this.stringifyArguments(slice.call(arg, -1)) + ']';
+                        }
+                    } else if (arg.constructor === Object) {
+                        result[i] = '#object';
+                    } else if (arg.constructor === Function) {
+                        result[i] = '#function';
+                    } else if (arg.constructor === String) {
+                        result[i] = '"' + arg + '"';
+                    } else if (arg.constructor === Number) {
+                        result[i] = arg;
+                    } else {
+                        result[i] = '?';
+                    }
                 }
-                else
-                    throw new Error("BinaryXMLStructureDecoder: Unrecognized header type " + type);
-                break;
-            
-            case BinaryXMLStructureDecoder.READ_BYTES:
-                var nRemainingBytes = input.length - this.offset;
-                if (nRemainingBytes < this.nBytesToRead) {
-                    // Need more.
-                    this.offset += nRemainingBytes;
-                    this.nBytesToRead -= nRemainingBytes;
-                    return false;
+            }
+            return result.join(',');
+        },
+
+        sourceCache: {},
+
+        /**
+         * @return {String} the text from a given URL
+         */
+        ajax: function(url) {
+            var req = this.createXMLHTTPObject();
+            if (req) {
+                try {
+                    req.open('GET', url, false);
+                    //req.overrideMimeType('text/plain');
+                    //req.overrideMimeType('text/javascript');
+                    req.send(null);
+                    //return req.status == 200 ? req.responseText : '';
+                    return req.responseText;
+                } catch (e) {
                 }
-                // Got the bytes.  Read a new header or close.
-                this.offset += this.nBytesToRead;
-                this.startHeader();
-                break;
-            
-            default:
-                // We don't expect this to happen.
-                throw new Error("BinaryXMLStructureDecoder: Unrecognized state " + this.state);
+            }
+            return '';
+        },
+
+        /**
+         * Try XHR methods in order and store XHR factory.
+         *
+         * @return {XMLHttpRequest} XHR function or equivalent
+         */
+        createXMLHTTPObject: function() {
+            var xmlhttp, XMLHttpFactories = [
+                function() {
+                    return new XMLHttpRequest();
+                }, function() {
+                    return new ActiveXObject('Msxml2.XMLHTTP');
+                }, function() {
+                    return new ActiveXObject('Msxml3.XMLHTTP');
+                }, function() {
+                    return new ActiveXObject('Microsoft.XMLHTTP');
+                }
+            ];
+            for (var i = 0; i < XMLHttpFactories.length; i++) {
+                try {
+                    xmlhttp = XMLHttpFactories[i]();
+                    // Use memoization to cache the factory
+                    this.createXMLHTTPObject = XMLHttpFactories[i];
+                    return xmlhttp;
+                } catch (e) {
+                }
+            }
+        },
+
+        /**
+         * Given a URL, check if it is in the same domain (so we can get the source
+         * via Ajax).
+         *
+         * @param url {String} source url
+         * @return {Boolean} False if we need a cross-domain request
+         */
+        isSameDomain: function(url) {
+            return typeof location !== "undefined" && url.indexOf(location.hostname) !== -1; // location may not be defined, e.g. when running from nodejs.
+        },
+
+        /**
+         * Get source code from given URL if in the same domain.
+         *
+         * @param url {String} JS source URL
+         * @return {Array} Array of source code lines
+         */
+        getSource: function(url) {
+            // TODO reuse source from script tags?
+            if (!(url in this.sourceCache)) {
+                this.sourceCache[url] = this.ajax(url).split('\n');
+            }
+            return this.sourceCache[url];
+        },
+
+        guessAnonymousFunctions: function(stack) {
+            for (var i = 0; i < stack.length; ++i) {
+                var reStack = /\{anonymous\}\(.*\)@(.*)/,
+                    reRef = /^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/,
+                    frame = stack[i], ref = reStack.exec(frame);
+
+                if (ref) {
+                    var m = reRef.exec(ref[1]);
+                    if (m) { // If falsey, we did not get any file/line information
+                        var file = m[1], lineno = m[2], charno = m[3] || 0;
+                        if (file && this.isSameDomain(file) && lineno) {
+                            var functionName = this.guessAnonymousFunction(file, lineno, charno);
+                            stack[i] = frame.replace('{anonymous}', functionName);
+                        }
+                    }
+                }
+            }
+            return stack;
+        },
+
+        guessAnonymousFunction: function(url, lineNo, charNo) {
+            var ret;
+            try {
+                ret = this.findFunctionName(this.getSource(url), lineNo);
+            } catch (e) {
+                ret = 'getSource failed with url: ' + url + ', exception: ' + e.toString();
+            }
+            return ret;
+        },
+
+        findFunctionName: function(source, lineNo) {
+            // FIXME findFunctionName fails for compressed source
+            // (more than one function on the same line)
+            // function {name}({args}) m[1]=name m[2]=args
+            var reFunctionDeclaration = /function\s+([^(]*?)\s*\(([^)]*)\)/;
+            // {name} = function ({args}) TODO args capture
+            // /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*function(?:[^(]*)/
+            var reFunctionExpression = /['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*function\b/;
+            // {name} = eval()
+            var reFunctionEvaluation = /['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*(?:eval|new Function)\b/;
+            // Walk backwards in the source lines until we find
+            // the line which matches one of the patterns above
+            var code = "", line, maxLines = Math.min(lineNo, 20), m, commentPos;
+            for (var i = 0; i < maxLines; ++i) {
+                // lineNo is 1-based, source[] is 0-based
+                line = source[lineNo - i - 1];
+                commentPos = line.indexOf('//');
+                if (commentPos >= 0) {
+                    line = line.substr(0, commentPos);
+                }
+                // TODO check other types of comments? Commented code may lead to false positive
+                if (line) {
+                    code = line + code;
+                    m = reFunctionExpression.exec(code);
+                    if (m && m[1]) {
+                        return m[1];
+                    }
+                    m = reFunctionDeclaration.exec(code);
+                    if (m && m[1]) {
+                        //return m[1] + "(" + (m[2] || "") + ")";
+                        return m[1];
+                    }
+                    m = reFunctionEvaluation.exec(code);
+                    if (m && m[1]) {
+                        return m[1];
+                    }
+                }
+            }
+            return '(?)';
         }
-    }
-};
+    };
 
-/*
- * Set the state to READ_HEADER_OR_CLOSE and set up to start reading the header
- */
-BinaryXMLStructureDecoder.prototype.startHeader = function() {
-    this.headerLength = 0;
-    this.useHeaderBuffer = false;
-    this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;    
-}
-
-/*
- *  Set the offset into the input, used for the next read.
- */
-BinaryXMLStructureDecoder.prototype.seek = function(
-        //int
-        offset) {
-    this.offset = offset;
-}
+    return printStackTrace;
+}));
 /**
- * This class contains utilities to help parse the data
- * author: Meki Cheraoui, Jeff Thompson
- * See COPYING for copyright and distribution information.
- */
- 
-var DataUtils = function DataUtils(){
-	
-	
-};
-
-
-/*
- * NOTE THIS IS CURRENTLY NOT BEHING USED
- * 
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Ryan Bennett
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
  */
 
-DataUtils.keyStr = "ABCDEFGHIJKLMNOP" +
-               "QRSTUVWXYZabcdef" +
-               "ghijklmnopqrstuv" +
-               "wxyz0123456789+/" +
-               "=";
+// define a shim require function so that a node/browserify require calls dont cause errors when ndn-js is used via <script> tag
 
-               
+/** @ignore */
+var ndn = ndn || {}
+/** @ignore */
+var exports = ndn;
+
+/** @ignore */
+var module = {}
+/** @ignore */
+function require(){return ndn;}
 /**
- * Raw String to Base 64
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
  */
-DataUtils.stringtoBase64=function stringtoBase64(input) {
-     input = escape(input);
-     var output = "";
-     var chr1, chr2, chr3 = "";
-     var enc1, enc2, enc3, enc4 = "";
-     var i = 0;
 
-     do {
-        chr1 = input.charCodeAt(i++);
-        chr2 = input.charCodeAt(i++);
-        chr3 = input.charCodeAt(i++);
+// This is included after stacktrace.js and browserify-require.js so that
+// require().printStackTrace works.
 
-        enc1 = chr1 >> 2;
-        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
-        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
-        enc4 = chr3 & 63;
+exports.printStackTrace = printStackTrace;
+/**
+ * This module checks for the availability of various crypto.subtle api's at runtime,
+ * exporting a function that returns the known availability of necessary NDN crypto apis
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Ryan Bennett <nomad.ry@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
 
-        if (isNaN(chr2)) {
-           enc3 = enc4 = 64;
-        } else if (isNaN(chr3)) {
-           enc4 = 64;
-        }
-
-        output = output +
-           DataUtils.keyStr.charAt(enc1) +
-           DataUtils.keyStr.charAt(enc2) +
-           DataUtils.keyStr.charAt(enc3) +
-           DataUtils.keyStr.charAt(enc4);
-        chr1 = chr2 = chr3 = "";
-        enc1 = enc2 = enc3 = enc4 = "";
-     } while (i < input.length);
-
-     return output;
+function DetectSubtleCrypto(){
+  var use = false;
+  var baselineSupport = (
+                            (typeof crypto !== 'undefined' && crypto && crypto.subtle)
+                            && (
+                                (location.protocol === "https:" || "chrome-extension:" || "chrome:")
+                                || (location.hostname === "localhost" || location.hostname === "127.0.0.1")
+                               )
+                        ) ? true : false ;
+  if (baselineSupport) {
+    var algo = { name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, hash:{name:"SHA-256"}, publicExponent: new Uint8Array([0x01, 0x00, 0x01])};
+    var keypair;
+    //try to perform every RSA crypto operation we need, if everything works, set use = true
+    crypto.subtle.generateKey(
+      algo,
+      true, //exportable;
+      ["sign", "verify"]).then(function(key){
+        keypair = key;
+        return crypto.subtle.sign(algo, key.privateKey, new Uint8Array([1,2,3,4,5]));
+      }).then(function(signature){
+        return crypto.subtle.verify(algo, keypair.publicKey, signature, new Uint8Array([1,2,3,4,5]));
+      }).then(function(verified){
+        return crypto.subtle.exportKey("pkcs8",keypair.privateKey);
+      }).then(function(pkcs8){
+        return crypto.subtle.importKey("pkcs8", pkcs8, algo, true, ["sign"]);
+      }).then(function(importedKey){
+        return crypto.subtle.exportKey("spki", keypair.publicKey);
+      }).then(function(spki){
+        return crypto.subtle.importKey("spki", spki, algo, true, ["verify"]);
+      }).then(function(importedKey){
+        var testDigest = new Uint8Array([1,2,3,4,5]);
+        return crypto.subtle.digest({name:"SHA-256"}, testDigest.buffer);
+      }).then(function(result){
+        use = true;
+      }, function(err){
+        console.log("DetectSubtleCrypto encountered error, not using crypto.subtle: ", err)
+      });
   }
-
-/**
- * Base 64 to Raw String 
- */
-DataUtils.base64toString = function base64toString(input) {
-     var output = "";
-     var chr1, chr2, chr3 = "";
-     var enc1, enc2, enc3, enc4 = "";
-     var i = 0;
-
-     // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
-     var base64test = /[^A-Za-z0-9\+\/\=]/g;
-     /* Test for invalid characters. */
-     if (base64test.exec(input)) {
-        alert("There were invalid base64 characters in the input text.\n" +
-              "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
-              "Expect errors in decoding.");
-     }
-     
-     input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
-
-     do {
-        enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
-        enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
-        enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
-        enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));
-
-        chr1 = (enc1 << 2) | (enc2 >> 4);
-        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
-        chr3 = ((enc3 & 3) << 6) | enc4;
-
-        output = output + String.fromCharCode(chr1);
-
-        if (enc3 != 64) {
-           output = output + String.fromCharCode(chr2);
-        }
-        if (enc4 != 64) {
-           output = output + String.fromCharCode(chr3);
-        }
-
-        chr1 = chr2 = chr3 = "";
-        enc1 = enc2 = enc3 = enc4 = "";
-
-     } while (i < input.length);
-
-     return unescape(output);
-  };
-
-//byte [] 
-
-/**
- * NOT WORKING!!!!!
- * 
- * Unsiged Long Number to Byte Array
- */
-	
- /*
-DataUtils.unsignedLongToByteArray= function( value) {
-	
-	if(LOG>4)console.log('INPUT IS '+value);
-	
-	if( 0 == value )
-		return [0];
-
-	if( 0 <= value && value <= 0x00FF ) {
-		//byte [] 
-		var bb = new Array(1);
-		bb[0] = (value & 0x00FF);
-		return bb;
-	}
-
-	if(LOG>4) console.log('type of value is '+typeof value);
-	if(LOG>4) console.log('value is '+value);
-	//byte [] 
-	var out = null;
-	//int
-	var offset = -1;
-	for(var i = 7; i >=0; --i) {
-		//byte
-		console.log(i);
-		console.log('value is '+value);
-		console.log('(value >> (i * 8)) '+ (value >> (i * 8))  );
-		console.log(' ((value >> (i * 8)) & 0xFF) '+ ((value >> (i * 8)) & 0xFF)  );
-
-		var b = ((value >> (i * 8)) & 0xFF)  ;
-		
-		if(LOG>4) console.log('b is '+b);
-		
-		if( out == null && b != 0 ) {
-			//out = new byte[i+1];
-			out = new Array(i+1);
-			offset = i;
-		}
-		
-		if( out != null )
-			out[ offset - i ] = b;
-	}
-	if(LOG>4)console.log('OUTPUT IS ');
-	if(LOG>4)console.log(out);
-	return out;
+  return function useSubtleCrypto(){
+    return use;
+  }
 }
+
+var UseSubtleCrypto = DetectSubtleCrypto();
+
+exports.UseSubtleCrypto = UseSubtleCrypto;
+/*! CryptoJS v3.1.2 core-fix.js
+ * code.google.com/p/crypto-js
+ * (c) 2009-2013 by Jeff Mott. All rights reserved.
+ * code.google.com/p/crypto-js/wiki/License
+ * THIS IS FIX of 'core.js' to fix Hmac issue.
+ * https://code.google.com/p/crypto-js/issues/detail?id=84
+ * https://crypto-js.googlecode.com/svn-history/r667/branches/3.x/src/core.js
+ */
+/**
+ * CryptoJS core components.
+ */
+var CryptoJS = CryptoJS || (function (Math, undefined) {
+    /**
+     * CryptoJS namespace.
+     */
+    var C = {};
+
+    /**
+     * Library namespace.
+     */
+    var C_lib = C.lib = {};
+
+    /**
+     * Base object for prototypal inheritance.
+     */
+    var Base = C_lib.Base = (function () {
+        function F() {}
+
+        return {
+            /**
+             * Creates a new object that inherits from this object.
+             *
+             * @param {Object} overrides Properties to copy into the new object.
+             *
+             * @return {Object} The new object.
+             *
+             * @static
+             *
+             * @example
+             *
+             *     var MyType = CryptoJS.lib.Base.extend({
+             *         field: 'value',
+             *
+             *         method: function () {
+             *         }
+             *     });
+             */
+            extend: function (overrides) {
+                // Spawn
+                F.prototype = this;
+                var subtype = new F();
+
+                // Augment
+                if (overrides) {
+                    subtype.mixIn(overrides);
+                }
+
+                // Create default initializer
+                if (!subtype.hasOwnProperty('init')) {
+                    subtype.init = function () {
+                        subtype.$super.init.apply(this, arguments);
+                    };
+                }
+
+                // Initializer's prototype is the subtype object
+                subtype.init.prototype = subtype;
+
+                // Reference supertype
+                subtype.$super = this;
+
+                return subtype;
+            },
+
+            /**
+             * Extends this object and runs the init method.
+             * Arguments to create() will be passed to init().
+             *
+             * @return {Object} The new object.
+             *
+             * @static
+             *
+             * @example
+             *
+             *     var instance = MyType.create();
+             */
+            create: function () {
+                var instance = this.extend();
+                instance.init.apply(instance, arguments);
+
+                return instance;
+            },
+
+            /**
+             * Initializes a newly created object.
+             * Override this method to add some logic when your objects are created.
+             *
+             * @example
+             *
+             *     var MyType = CryptoJS.lib.Base.extend({
+             *         init: function () {
+             *             // ...
+             *         }
+             *     });
+             */
+            init: function () {
+            },
+
+            /**
+             * Copies properties into this object.
+             *
+             * @param {Object} properties The properties to mix in.
+             *
+             * @example
+             *
+             *     MyType.mixIn({
+             *         field: 'value'
+             *     });
+             */
+            mixIn: function (properties) {
+                for (var propertyName in properties) {
+                    if (properties.hasOwnProperty(propertyName)) {
+                        this[propertyName] = properties[propertyName];
+                    }
+                }
+
+                // IE won't copy toString using the loop above
+                if (properties.hasOwnProperty('toString')) {
+                    this.toString = properties.toString;
+                }
+            },
+
+            /**
+             * Creates a copy of this object.
+             *
+             * @return {Object} The clone.
+             *
+             * @example
+             *
+             *     var clone = instance.clone();
+             */
+            clone: function () {
+                return this.init.prototype.extend(this);
+            }
+        };
+    }());
+
+    /**
+     * An array of 32-bit words.
+     *
+     * @property {Array} words The array of 32-bit words.
+     * @property {number} sigBytes The number of significant bytes in this word array.
+     */
+    var WordArray = C_lib.WordArray = Base.extend({
+        /**
+         * Initializes a newly created word array.
+         *
+         * @param {Array} words (Optional) An array of 32-bit words.
+         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.lib.WordArray.create();
+         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
+         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
+         */
+        init: function (words, sigBytes) {
+            words = this.words = words || [];
+
+            if (sigBytes != undefined) {
+                this.sigBytes = sigBytes;
+            } else {
+                this.sigBytes = words.length * 4;
+            }
+        },
+
+        /**
+         * Converts this word array to a string.
+         *
+         * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
+         *
+         * @return {string} The stringified word array.
+         *
+         * @example
+         *
+         *     var string = wordArray + '';
+         *     var string = wordArray.toString();
+         *     var string = wordArray.toString(CryptoJS.enc.Utf8);
+         */
+        toString: function (encoder) {
+            return (encoder || Hex).stringify(this);
+        },
+
+        /**
+         * Concatenates a word array to this word array.
+         *
+         * @param {WordArray} wordArray The word array to append.
+         *
+         * @return {WordArray} This word array.
+         *
+         * @example
+         *
+         *     wordArray1.concat(wordArray2);
+         */
+        concat: function (wordArray) {
+            // Shortcuts
+            var thisWords = this.words;
+            var thatWords = wordArray.words;
+            var thisSigBytes = this.sigBytes;
+            var thatSigBytes = wordArray.sigBytes;
+
+            // Clamp excess bits
+            this.clamp();
+
+            // Concat
+            if (thisSigBytes % 4) {
+                // Copy one byte at a time
+                for (var i = 0; i < thatSigBytes; i++) {
+                    var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+                    thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
+                }
+            } else {
+                // Copy one word at a time
+                for (var i = 0; i < thatSigBytes; i += 4) {
+                    thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
+                }
+            }
+            this.sigBytes += thatSigBytes;
+
+            // Chainable
+            return this;
+        },
+
+        /**
+         * Removes insignificant bits.
+         *
+         * @example
+         *
+         *     wordArray.clamp();
+         */
+        clamp: function () {
+            // Shortcuts
+            var words = this.words;
+            var sigBytes = this.sigBytes;
+
+            // Clamp
+            words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
+            words.length = Math.ceil(sigBytes / 4);
+        },
+
+        /**
+         * Creates a copy of this word array.
+         *
+         * @return {WordArray} The clone.
+         *
+         * @example
+         *
+         *     var clone = wordArray.clone();
+         */
+        clone: function () {
+            var clone = Base.clone.call(this);
+            clone.words = this.words.slice(0);
+
+            return clone;
+        },
+
+        /**
+         * Creates a word array filled with random bytes.
+         *
+         * @param {number} nBytes The number of random bytes to generate.
+         *
+         * @return {WordArray} The random word array.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.lib.WordArray.random(16);
+         */
+        random: function (nBytes) {
+            var words = [];
+            for (var i = 0; i < nBytes; i += 4) {
+                words.push((Math.random() * 0x100000000) | 0);
+            }
+
+            return new WordArray.init(words, nBytes);
+        }
+    });
+
+    /**
+     * Encoder namespace.
+     */
+    var C_enc = C.enc = {};
+
+    /**
+     * Hex encoding strategy.
+     */
+    var Hex = C_enc.Hex = {
+        /**
+         * Converts a word array to a hex string.
+         *
+         * @param {WordArray} wordArray The word array.
+         *
+         * @return {string} The hex string.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
+         */
+        stringify: function (wordArray) {
+            // Shortcuts
+            var words = wordArray.words;
+            var sigBytes = wordArray.sigBytes;
+
+            // Convert
+            var hexChars = [];
+            for (var i = 0; i < sigBytes; i++) {
+                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+                hexChars.push((bite >>> 4).toString(16));
+                hexChars.push((bite & 0x0f).toString(16));
+            }
+
+            return hexChars.join('');
+        },
+
+        /**
+         * Converts a hex string to a word array.
+         *
+         * @param {string} hexStr The hex string.
+         *
+         * @return {WordArray} The word array.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
+         */
+        parse: function (hexStr) {
+            // Shortcut
+            var hexStrLength = hexStr.length;
+
+            // Convert
+            var words = [];
+            for (var i = 0; i < hexStrLength; i += 2) {
+                words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
+            }
+
+            return new WordArray.init(words, hexStrLength / 2);
+        }
+    };
+
+    /**
+     * Latin1 encoding strategy.
+     */
+    var Latin1 = C_enc.Latin1 = {
+        /**
+         * Converts a word array to a Latin1 string.
+         *
+         * @param {WordArray} wordArray The word array.
+         *
+         * @return {string} The Latin1 string.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
+         */
+        stringify: function (wordArray) {
+            // Shortcuts
+            var words = wordArray.words;
+            var sigBytes = wordArray.sigBytes;
+
+            // Convert
+            var latin1Chars = [];
+            for (var i = 0; i < sigBytes; i++) {
+                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+                latin1Chars.push(String.fromCharCode(bite));
+            }
+
+            return latin1Chars.join('');
+        },
+
+        /**
+         * Converts a Latin1 string to a word array.
+         *
+         * @param {string} latin1Str The Latin1 string.
+         *
+         * @return {WordArray} The word array.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
+         */
+        parse: function (latin1Str) {
+            // Shortcut
+            var latin1StrLength = latin1Str.length;
+
+            // Convert
+            var words = [];
+            for (var i = 0; i < latin1StrLength; i++) {
+                words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
+            }
+
+            return new WordArray.init(words, latin1StrLength);
+        }
+    };
+
+    /**
+     * UTF-8 encoding strategy.
+     */
+    var Utf8 = C_enc.Utf8 = {
+        /**
+         * Converts a word array to a UTF-8 string.
+         *
+         * @param {WordArray} wordArray The word array.
+         *
+         * @return {string} The UTF-8 string.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
+         */
+        stringify: function (wordArray) {
+            try {
+                return decodeURIComponent(escape(Latin1.stringify(wordArray)));
+            } catch (e) {
+                throw new Error('Malformed UTF-8 data');
+            }
+        },
+
+        /**
+         * Converts a UTF-8 string to a word array.
+         *
+         * @param {string} utf8Str The UTF-8 string.
+         *
+         * @return {WordArray} The word array.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
+         */
+        parse: function (utf8Str) {
+            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
+        }
+    };
+
+    /**
+     * Abstract buffered block algorithm template.
+     *
+     * The property blockSize must be implemented in a concrete subtype.
+     *
+     * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
+     */
+    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
+        /**
+         * Resets this block algorithm's data buffer to its initial state.
+         *
+         * @example
+         *
+         *     bufferedBlockAlgorithm.reset();
+         */
+        reset: function () {
+            // Initial values
+            this._data = new WordArray.init();
+            this._nDataBytes = 0;
+        },
+
+        /**
+         * Adds new data to this block algorithm's buffer.
+         *
+         * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
+         *
+         * @example
+         *
+         *     bufferedBlockAlgorithm._append('data');
+         *     bufferedBlockAlgorithm._append(wordArray);
+         */
+        _append: function (data) {
+            // Convert string to WordArray, else assume WordArray already
+            if (typeof data == 'string') {
+                data = Utf8.parse(data);
+            }
+
+            // Append
+            this._data.concat(data);
+            this._nDataBytes += data.sigBytes;
+        },
+
+        /**
+         * Processes available data blocks.
+         *
+         * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
+         *
+         * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
+         *
+         * @return {WordArray} The processed data.
+         *
+         * @example
+         *
+         *     var processedData = bufferedBlockAlgorithm._process();
+         *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
+         */
+        _process: function (doFlush) {
+            // Shortcuts
+            var data = this._data;
+            var dataWords = data.words;
+            var dataSigBytes = data.sigBytes;
+            var blockSize = this.blockSize;
+            var blockSizeBytes = blockSize * 4;
+
+            // Count blocks ready
+            var nBlocksReady = dataSigBytes / blockSizeBytes;
+            if (doFlush) {
+                // Round up to include partial blocks
+                nBlocksReady = Math.ceil(nBlocksReady);
+            } else {
+                // Round down to include only full blocks,
+                // less the number of blocks that must remain in the buffer
+                nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
+            }
+
+            // Count words ready
+            var nWordsReady = nBlocksReady * blockSize;
+
+            // Count bytes ready
+            var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
+
+            // Process blocks
+            if (nWordsReady) {
+                for (var offset = 0; offset < nWordsReady; offset += blockSize) {
+                    // Perform concrete-algorithm logic
+                    this._doProcessBlock(dataWords, offset);
+                }
+
+                // Remove processed words
+                var processedWords = dataWords.splice(0, nWordsReady);
+                data.sigBytes -= nBytesReady;
+            }
+
+            // Return processed words
+            return new WordArray.init(processedWords, nBytesReady);
+        },
+
+        /**
+         * Creates a copy of this object.
+         *
+         * @return {Object} The clone.
+         *
+         * @example
+         *
+         *     var clone = bufferedBlockAlgorithm.clone();
+         */
+        clone: function () {
+            var clone = Base.clone.call(this);
+            clone._data = this._data.clone();
+
+            return clone;
+        },
+
+        _minBufferSize: 0
+    });
+
+    /**
+     * Abstract hasher template.
+     *
+     * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
+     */
+    var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
+        /**
+         * Configuration options.
+         */
+        cfg: Base.extend(),
+
+        /**
+         * Initializes a newly created hasher.
+         *
+         * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
+         *
+         * @example
+         *
+         *     var hasher = CryptoJS.algo.SHA256.create();
+         */
+        init: function (cfg) {
+            // Apply config defaults
+            this.cfg = this.cfg.extend(cfg);
+
+            // Set initial values
+            this.reset();
+        },
+
+        /**
+         * Resets this hasher to its initial state.
+         *
+         * @example
+         *
+         *     hasher.reset();
+         */
+        reset: function () {
+            // Reset data buffer
+            BufferedBlockAlgorithm.reset.call(this);
+
+            // Perform concrete-hasher logic
+            this._doReset();
+        },
+
+        /**
+         * Updates this hasher with a message.
+         *
+         * @param {WordArray|string} messageUpdate The message to append.
+         *
+         * @return {Hasher} This hasher.
+         *
+         * @example
+         *
+         *     hasher.update('message');
+         *     hasher.update(wordArray);
+         */
+        update: function (messageUpdate) {
+            // Append
+            this._append(messageUpdate);
+
+            // Update the hash
+            this._process();
+
+            // Chainable
+            return this;
+        },
+
+        /**
+         * Finalizes the hash computation.
+         * Note that the finalize operation is effectively a destructive, read-once operation.
+         *
+         * @param {WordArray|string} messageUpdate (Optional) A final message update.
+         *
+         * @return {WordArray} The hash.
+         *
+         * @example
+         *
+         *     var hash = hasher.finalize();
+         *     var hash = hasher.finalize('message');
+         *     var hash = hasher.finalize(wordArray);
+         */
+        finalize: function (messageUpdate) {
+            // Final message update
+            if (messageUpdate) {
+                this._append(messageUpdate);
+            }
+
+            // Perform concrete-hasher logic
+            var hash = this._doFinalize();
+
+            return hash;
+        },
+
+        blockSize: 512/32,
+
+        /**
+         * Creates a shortcut function to a hasher's object interface.
+         *
+         * @param {Hasher} hasher The hasher to create a helper for.
+         *
+         * @return {Function} The shortcut function.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
+         */
+        _createHelper: function (hasher) {
+            return function (message, cfg) {
+                return new hasher.init(cfg).finalize(message);
+            };
+        },
+
+        /**
+         * Creates a shortcut function to the HMAC's object interface.
+         *
+         * @param {Hasher} hasher The hasher to use in this HMAC helper.
+         *
+         * @return {Function} The shortcut function.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
+         */
+        _createHmacHelper: function (hasher) {
+            return function (message, key) {
+                return new C_algo.HMAC.init(hasher, key).finalize(message);
+            };
+        }
+    });
+
+    /**
+     * Algorithm namespace.
+     */
+    var C_algo = C.algo = {};
+
+    return C;
+}(Math));
+
+exports.CryptoJS = CryptoJS;
+module.exports = exports;
+/*
+CryptoJS v3.1.2
+code.google.com/p/crypto-js
+(c) 2009-2013 by Jeff Mott. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
+associated documentation files (the "Software"), to deal in the Software without restriction, including 
+without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
+sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+code.google.com/p/crypto-js/wiki/License
+*/
+
+var C = require('./core.js').CryptoJS;
+(function (Math) {
+    // Shortcuts
+    var C_lib = C.lib;
+    var WordArray = C_lib.WordArray;
+    var Hasher = C_lib.Hasher;
+    var C_algo = C.algo;
+
+    // Initialization and round constants tables
+    var H = [];
+    var K = [];
+
+    // Compute constants
+    (function () {
+        function isPrime(n) {
+            var sqrtN = Math.sqrt(n);
+            for (var factor = 2; factor <= sqrtN; factor++) {
+                if (!(n % factor)) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        function getFractionalBits(n) {
+            return ((n - (n | 0)) * 0x100000000) | 0;
+        }
+
+        var n = 2;
+        var nPrime = 0;
+        while (nPrime < 64) {
+            if (isPrime(n)) {
+                if (nPrime < 8) {
+                    H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
+                }
+                K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
+
+                nPrime++;
+            }
+
+            n++;
+        }
+    }());
+
+    // Reusable object
+    var W = [];
+
+    /**
+     * SHA-256 hash algorithm.
+     */
+    var SHA256 = C_algo.SHA256 = Hasher.extend({
+        _doReset: function () {
+            this._hash = new WordArray.init(H.slice(0));
+        },
+
+        _doProcessBlock: function (M, offset) {
+            // Shortcut
+            var H = this._hash.words;
+
+            // Working variables
+            var a = H[0];
+            var b = H[1];
+            var c = H[2];
+            var d = H[3];
+            var e = H[4];
+            var f = H[5];
+            var g = H[6];
+            var h = H[7];
+
+            // Computation
+            for (var i = 0; i < 64; i++) {
+                if (i < 16) {
+                    W[i] = M[offset + i] | 0;
+                } else {
+                    var gamma0x = W[i - 15];
+                    var gamma0  = ((gamma0x << 25) | (gamma0x >>> 7))  ^
+                                  ((gamma0x << 14) | (gamma0x >>> 18)) ^
+                                   (gamma0x >>> 3);
+
+                    var gamma1x = W[i - 2];
+                    var gamma1  = ((gamma1x << 15) | (gamma1x >>> 17)) ^
+                                  ((gamma1x << 13) | (gamma1x >>> 19)) ^
+                                   (gamma1x >>> 10);
+
+                    W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
+                }
+
+                var ch  = (e & f) ^ (~e & g);
+                var maj = (a & b) ^ (a & c) ^ (b & c);
+
+                var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
+                var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7)  | (e >>> 25));
+
+                var t1 = h + sigma1 + ch + K[i] + W[i];
+                var t2 = sigma0 + maj;
+
+                h = g;
+                g = f;
+                f = e;
+                e = (d + t1) | 0;
+                d = c;
+                c = b;
+                b = a;
+                a = (t1 + t2) | 0;
+            }
+
+            // Intermediate hash value
+            H[0] = (H[0] + a) | 0;
+            H[1] = (H[1] + b) | 0;
+            H[2] = (H[2] + c) | 0;
+            H[3] = (H[3] + d) | 0;
+            H[4] = (H[4] + e) | 0;
+            H[5] = (H[5] + f) | 0;
+            H[6] = (H[6] + g) | 0;
+            H[7] = (H[7] + h) | 0;
+        },
+
+        _doFinalize: function () {
+            // Shortcuts
+            var data = this._data;
+            var dataWords = data.words;
+
+            var nBitsTotal = this._nDataBytes * 8;
+            var nBitsLeft = data.sigBytes * 8;
+
+            // Add padding
+            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
+            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
+            data.sigBytes = dataWords.length * 4;
+
+            // Hash final blocks
+            this._process();
+
+            // Return final computed hash
+            return this._hash;
+        },
+
+        clone: function () {
+            var clone = Hasher.clone.call(this);
+            clone._hash = this._hash.clone();
+
+            return clone;
+        }
+    });
+
+    /**
+     * Shortcut function to the hasher's object interface.
+     *
+     * @param {WordArray|string} message The message to hash.
+     *
+     * @return {WordArray} The hash.
+     *
+     * @static
+     *
+     * @example
+     *
+     *     var hash = CryptoJS.SHA256('message');
+     *     var hash = CryptoJS.SHA256(wordArray);
+     */
+    C.SHA256 = Hasher._createHelper(SHA256);
+
+    /**
+     * Shortcut function to the HMAC's object interface.
+     *
+     * @param {WordArray|string} message The message to hash.
+     * @param {WordArray|string} key The secret key.
+     *
+     * @return {WordArray} The HMAC.
+     *
+     * @static
+     *
+     * @example
+     *
+     *     var hmac = CryptoJS.HmacSHA256(message, key);
+     */
+    C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
+}(Math));
+
+exports.CryptoJS = C;
+module.exports = exports;
+/*
+CryptoJS v3.1.2
+code.google.com/p/crypto-js
+(c) 2009-2013 by Jeff Mott. All rights reserved.
+code.google.com/p/crypto-js/wiki/License
 */
-	
-/**
- * NOT WORKING!!!!!
- * 
- * Unsiged Long Number to Byte Array
- *//*
-DataUtils.byteArrayToUnsignedLong = function(//final byte [] 
-	src) {
-		if(LOG>4) console.log('INPUT IS ');
-		if(LOG>4) console.log(src);
-		
-		var value = 0;
-		for(var i = 0; i < src.length; i++) {
-			value = value << 8;
-			// Java will assume the byte is signed, so extend it and trim it.
-			
-			
-			var b = ((src[i]) & 0xFF );
-			value |= b;
-		}
-		
-		if(LOG>4) console.log('OUTPUT IS ');
-		
-		if(LOG>4) console.log(value);
-
-		return value;
-	}*/
-
-
-/**
- * Hex String to Byte Array
+(function () {
+    // Shortcuts
+    var C = CryptoJS;
+    var C_lib = C.lib;
+    var Base = C_lib.Base;
+    var C_enc = C.enc;
+    var Utf8 = C_enc.Utf8;
+    var C_algo = C.algo;
+
+    /**
+     * HMAC algorithm.
+     */
+    var HMAC = C_algo.HMAC = Base.extend({
+        /**
+         * Initializes a newly created HMAC.
+         *
+         * @param {Hasher} hasher The hash algorithm to use.
+         * @param {WordArray|string} key The secret key.
+         *
+         * @example
+         *
+         *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
+         */
+        init: function (hasher, key) {
+            // Init hasher
+            hasher = this._hasher = new hasher.init();
+
+            // Convert string to WordArray, else assume WordArray already
+            if (typeof key == 'string') {
+                key = Utf8.parse(key);
+            }
+
+            // Shortcuts
+            var hasherBlockSize = hasher.blockSize;
+            var hasherBlockSizeBytes = hasherBlockSize * 4;
+
+            // Allow arbitrary length keys
+            if (key.sigBytes > hasherBlockSizeBytes) {
+                key = hasher.finalize(key);
+            }
+
+            // Clamp excess bits
+            key.clamp();
+
+            // Clone key for inner and outer pads
+            var oKey = this._oKey = key.clone();
+            var iKey = this._iKey = key.clone();
+
+            // Shortcuts
+            var oKeyWords = oKey.words;
+            var iKeyWords = iKey.words;
+
+            // XOR keys with pad constants
+            for (var i = 0; i < hasherBlockSize; i++) {
+                oKeyWords[i] ^= 0x5c5c5c5c;
+                iKeyWords[i] ^= 0x36363636;
+            }
+            oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;
+
+            // Set initial values
+            this.reset();
+        },
+
+        /**
+         * Resets this HMAC to its initial state.
+         *
+         * @example
+         *
+         *     hmacHasher.reset();
+         */
+        reset: function () {
+            // Shortcut
+            var hasher = this._hasher;
+
+            // Reset
+            hasher.reset();
+            hasher.update(this._iKey);
+        },
+
+        /**
+         * Updates this HMAC with a message.
+         *
+         * @param {WordArray|string} messageUpdate The message to append.
+         *
+         * @return {HMAC} This HMAC instance.
+         *
+         * @example
+         *
+         *     hmacHasher.update('message');
+         *     hmacHasher.update(wordArray);
+         */
+        update: function (messageUpdate) {
+            this._hasher.update(messageUpdate);
+
+            // Chainable
+            return this;
+        },
+
+        /**
+         * Finalizes the HMAC computation.
+         * Note that the finalize operation is effectively a destructive, read-once operation.
+         *
+         * @param {WordArray|string} messageUpdate (Optional) A final message update.
+         *
+         * @return {WordArray} The HMAC.
+         *
+         * @example
+         *
+         *     var hmac = hmacHasher.finalize();
+         *     var hmac = hmacHasher.finalize('message');
+         *     var hmac = hmacHasher.finalize(wordArray);
+         */
+        finalize: function (messageUpdate) {
+            // Shortcut
+            var hasher = this._hasher;
+
+            // Compute HMAC
+            var innerHash = hasher.finalize(messageUpdate);
+            hasher.reset();
+            var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
+
+            return hmac;
+        }
+    });
+}());
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
  */
-	//THIS IS NOT WORKING
-/*
-DataUtils.HexStringtoByteArray = function(str) {
-    var byteArray = [];
-    for (var i = 0; i < str.length; i++)
-        if (str.charCodeAt(i) <= 0x7F)
-            byteArray.push(str.charCodeAt(i));
-        else {
-            var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
-            for (var j = 0; j < h.length; j++)
-                byteArray.push(parseInt(h[j], 16));
-        }
-    return byteArray;
-};
-*/
-
-/**
- * Uint8Array to Hex String
- */
-//http://ejohn.org/blog/numbers-hex-and-colors/
-DataUtils.toHex = function(args){
-	if (LOG>4) console.log('ABOUT TO CONVERT '+ args);
-	//console.log(args);
-  	var ret = "";
-  	for ( var i = 0; i < args.length; i++ )
-    	ret += (args[i] < 16 ? "0" : "") + args[i].toString(16);
-  	if (LOG>4) console.log('Converted to: ' + ret);
-  	return ret; //.toUpperCase();
-}
-
-/**
- * Raw string to hex string.
- */
-DataUtils.stringToHex = function(args){
-	var ret = "";
-	for (var i = 0; i < args.length; ++i) {
-		var value = args.charCodeAt(i);
-		ret += (value < 16 ? "0" : "") + value.toString(16);
-	}
-	return ret;
-}
-
-/**
- * Uint8Array to raw string.
- */
-DataUtils.toString = function(args){
-  //console.log(arguments);
-  var ret = "";
-  for ( var i = 0; i < args.length; i++ )
-    ret += String.fromCharCode(args[i]);
-  return ret;
-}
-
-/**
- * Hex String to Uint8Array.
- */
-DataUtils.toNumbers = function(str) {
-	if (typeof str == 'string') {
-		var ret = new Uint8Array(Math.floor(str.length / 2));
-        var i = 0;
-		str.replace(/(..)/g, function(str) {
-		    ret[i++] = parseInt(str, 16);
-		});
-		return ret;
-    }
-}
-
-/**
- * Hex String to raw string.
- */
-DataUtils.hexToRawString = function(str) {
-    if(typeof str =='string') {
-		var ret = "";
-		str.replace(/(..)/g, function(s) {
-			ret += String.fromCharCode(parseInt(s, 16));
-		});
-		return ret;
-    }
-}
-
-/**
- * Raw String to Uint8Array.
- */
-DataUtils.toNumbersFromString = function(str) {
-	var bytes = new Uint8Array(str.length);
-	for(var i=0;i<str.length;i++)
-		bytes[i] = str.charCodeAt(i);
-	return bytes;
-}
-
-/*
- * Encode str as utf8 and return as Uint8Array.
- * TODO: Use TextEncoder when available.
- */
-DataUtils.stringToUtf8Array = function(str) {
-    return DataUtils.toNumbersFromString(str2rstr_utf8(str));
-}
-
-/*
- * arrays is an array of Uint8Array. Return a new Uint8Array which is the concatenation of all.
- */
-DataUtils.concatArrays = function(arrays) {
-    var totalLength = 0;
-	for (var i = 0; i < arrays.length; ++i)
-        totalLength += arrays[i].length;
-    
-    var result = new Uint8Array(totalLength);
-    var offset = 0;
-	for (var i = 0; i < arrays.length; ++i) {
-        result.set(arrays[i], offset);
-        offset += arrays[i].length;
-    }
-    return result;
-    
-}
- 
-// TODO: Take Uint8Array and use TextDecoder when available.
-DataUtils.decodeUtf8 = function (utftext) {
-		var string = "";
-		var i = 0;
-		var c = 0;
-        var c1 = 0;
-        var c2 = 0;
- 
-		while ( i < utftext.length ) {
- 
-			c = utftext.charCodeAt(i);
- 
-			if (c < 128) {
-				string += String.fromCharCode(c);
-				i++;
-			}
-			else if((c > 191) && (c < 224)) {
-				c2 = utftext.charCodeAt(i+1);
-				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
-				i += 2;
-			}
-			else {
-				c2 = utftext.charCodeAt(i+1);
-				var c3 = utftext.charCodeAt(i+2);
-				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
-				i += 3;
-			}
- 
-		}
- 
-		return string;
-	};
-
-//NOT WORKING
-/*
-DataUtils.getUTF8StringFromBytes = function(bytes) {
-	
-	bytes = toString(bytes);
-
-    var ix = 0;
- 
-    if( bytes.slice(0,3) == "\xEF\xBB\xBF") {
-        ix = 3;
-    }
- 
-    var string = "";
-    for( ; ix < bytes.length; ix++ ) {
-        var byte1 = bytes[ix].charCodeAt(0);
-        if( byte1 < 0x80 ) {
-            string += String.fromCharCode(byte1);
-        } else if( byte1 >= 0xC2 && byte1 < 0xE0 ) {
-            var byte2 = bytes[++ix].charCodeAt(0);
-            string += String.fromCharCode(((byte1&0x1F)<<6) + (byte2&0x3F));
-        } else if( byte1 >= 0xE0 && byte1 < 0xF0 ) {
-            var byte2 = bytes[++ix].charCodeAt(0);
-            var byte3 = bytes[++ix].charCodeAt(0);
-            string += String.fromCharCode(((byte1&0xFF)<<12) + ((byte2&0x3F)<<6) + (byte3&0x3F));
-        } else if( byte1 >= 0xF0 && byte1 < 0xF5) {
-            var byte2 = bytes[++ix].charCodeAt(0);
-            var byte3 = bytes[++ix].charCodeAt(0);
-            var byte4 = bytes[++ix].charCodeAt(0);
-            var codepoint = ((byte1&0x07)<<18) + ((byte2&0x3F)<<12)+ ((byte3&0x3F)<<6) + (byte4&0x3F);
-            codepoint -= 0x10000;
-            string += String.fromCharCode(
-                (codepoint>>10) + 0xD800,
-                (codepoint&0x3FF) + 0xDC00
-            );
-        }
-    }
- 
-    return string;
-}*/
-
-/**
- * Return true if a1 and a2 are the same length with equal elements.
- */
-DataUtils.arraysEqual = function(a1, a2){
-    if (a1.length != a2.length)
-        return false;
-    
-    for (var i = 0; i < a1.length; ++i) {
-        if (a1[i] != a2[i])
-            return false;
-    }
-
-    return true;
-};
-
-/*
- * Convert the big endian Uint8Array to an unsigned int.
- * Don't check for overflow.
- */
-DataUtils.bigEndianToUnsignedInt = function(bytes) {
-    var result = 0;
-    for (var i = 0; i < bytes.length; ++i) {
-        result <<= 8;
-        result += bytes[i];
-    }
-    return result;
-};
-
-/*
- * Convert the int value to a new big endian Uint8Array and return.
- * If value is 0 or negative, return Uint8Array(0). 
- */
-DataUtils.nonNegativeIntToBigEndian = function(value) {
-    value = Math.round(value);
-    if (value <= 0)
-        return new Uint8Array(0);
-    
-    // Assume value is not over 64 bits.
-    var size = 8;
-    var result = new Uint8Array(size);
-    var i = 0;
-    while (value != 0) {
-        ++i;
-        result[size - i] = value & 0xff;
-        value >>= 8;
-    }
-    return result.subarray(size - i, size);
-};
-
-/*
- * Modify array to randomly shuffle the elements.
- */
-DataUtils.shuffle = function(array) {
-    for (var i = array.length - 1; i >= 1; --i) {
-        // j is from 0 to i.
-        var j = Math.floor(Math.random() * (i + 1));
-        var temp = array[i];
-        array[i] = array[j];
-        array[j] = temp;
-    }
-}
-/**
- * This file contains utilities to help encode and decode NDN objects.
- * author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- */
-
-function encodeToHexInterest(interest){
-    return DataUtils.toHex(encodeToBinaryInterest(interest));
-}
-
-
-function encodeToBinaryInterest(interest) {
-	var enc = new BinaryXMLEncoder();
-	interest.to_ndnb(enc);
-	
-	return enc.getReducedOstream();
-}
-
-
-function encodeToHexContentObject(co){
-    return DataUtils.toHex(encodeToBinaryContentObject(co));
-}
-
-function encodeToBinaryContentObject(co){
-	var enc = new BinaryXMLEncoder();
-	co.to_ndnb(enc);
-
-	return enc.getReducedOstream();
-}
-
-function encodeForwardingEntry(co){
-	var enc = new BinaryXMLEncoder();
- 
-	co.to_ndnb(enc);
-	
-	var bytes = enc.getReducedOstream();
-
-	return bytes;
-
-	
-}
-
-
-
-function decodeHexFaceInstance(result){
-	
-	var numbers = DataUtils.toNumbers(result);
-			
-	
-	var decoder = new BinaryXMLDecoder(numbers);
-	
-	if(LOG>3)console.log('DECODING HEX FACE INSTANCE  \n'+numbers);
-
-	var faceInstance = new FaceInstance();
-
-	faceInstance.from_ndnb(decoder);
-
-	return faceInstance;
-	
-}
-
-
-
-function decodeHexInterest(result){
-	var numbers = DataUtils.toNumbers(result);	
-	
-	var decoder = new BinaryXMLDecoder(numbers);
-	
-	if(LOG>3)console.log('DECODING HEX INTERST  \n'+numbers);
-
-	var interest = new Interest();
-
-	interest.from_ndnb(decoder);
-
-	return interest;
-	
-}
-
-
-
-function decodeHexContentObject(result){
-	var numbers = DataUtils.toNumbers(result);
-	
-	var decoder = new BinaryXMLDecoder(numbers);
-	
-	if(LOG>3)console.log('DECODED HEX CONTENT OBJECT \n'+numbers);
-	
-	var co = new ContentObject();
-
-	co.from_ndnb(decoder);
-
-	return co;
-	
-}
-
-
-
-function decodeHexForwardingEntry(result){
-	var numbers = DataUtils.toNumbers(result);
-
-	var decoder = new BinaryXMLDecoder(numbers);
-	
-	if(LOG>3)console.log('DECODED HEX FORWARDING ENTRY \n'+numbers);
-	
-	var forwardingEntry = new ForwardingEntry();
-
-	forwardingEntry.from_ndnb(decoder);
-
-	return forwardingEntry;
-	
-}
-
-/*
- * Decode the Uint8Array which holds SubjectPublicKeyInfo and return an RSAKey.
- */
-function decodeSubjectPublicKeyInfo(array) {
-    var hex = DataUtils.toHex(array).toLowerCase();
-    var a = _x509_getPublicKeyHexArrayFromCertHex(hex, _x509_getSubjectPublicKeyPosFromCertHex(hex, 0));
-    var rsaKey = new RSAKey();
-    rsaKey.setPublic(a[0], a[1]);
-    return rsaKey;
-}
-
-/* Return a user friendly HTML string with the contents of co.
-   This also outputs to console.log.
- */
-function contentObjectToHtml(/* ContentObject */ co) {
-    var output ="";
-			
-    if(co==-1)
-	output+= "NO CONTENT FOUND"
-    else if (co==-2)
-	output+= "CONTENT NAME IS EMPTY"
-    else{
-	if(co.name!=null && co.name.components!=null){
-	    output+= "NAME: " + co.name.to_uri();
-        
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	
-	if(co.content !=null){
-	    output += "CONTENT(ASCII): "+ DataUtils.toString(co.content);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	if(co.content !=null){
-	    output += "CONTENT(hex): "+ DataUtils.toHex(co.content);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	if(co.signature !=null && co.signature.signature!=null){
-	    output += "SIGNATURE(hex): "+ DataUtils.toHex(co.signature.signature);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	if(co.signedInfo !=null && co.signedInfo.publisher!=null && co.signedInfo.publisher.publisherPublicKeyDigest!=null){
-	    output += "Publisher Public Key Digest(hex): "+ DataUtils.toHex(co.signedInfo.publisher.publisherPublicKeyDigest);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	if(co.signedInfo !=null && co.signedInfo.timestamp!=null){
-	    var d = new Date();
-	    d.setTime( co.signedInfo.timestamp.msec );
-	    
-	    var bytes = [217, 185, 12, 225, 217, 185, 12, 225];
-	    
-	    output += "TimeStamp: "+d;
-	    output+= "<br />";
-	    output += "TimeStamp(number): "+ co.signedInfo.timestamp.msec;
-	    
-	    output+= "<br />";
-	}
-	if(co.signedInfo !=null && co.signedInfo.finalBlockID!=null){
-	    output += "FinalBlockID: "+ DataUtils.toHex(co.signedInfo.finalBlockID);
-	    output+= "<br />";
-	}
-	if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.certificate!=null){
-	    var certificateHex = DataUtils.toHex(co.signedInfo.locator.certificate).toLowerCase();
-	    var signature = DataUtils.toHex(co.signature.signature).toLowerCase();
-	    var input = DataUtils.toString(co.rawSignatureData);
-	    
-	    output += "Hex Certificate: "+ certificateHex ;
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	    
-	    var x509 = new X509();
-	    x509.readCertHex(certificateHex);
-	    output += "Public key (hex) modulus: " + x509.subjectPublicKeyRSA.n.toString(16) + "<br/>";
-	    output += "exponent: " + x509.subjectPublicKeyRSA.e.toString(16) + "<br/>";
-	    output += "<br/>";
-	    
-	    var result = x509.subjectPublicKeyRSA.verifyByteArray(co.rawSignatureData, null, signature);
-	    if(LOG>2) console.log('result is '+result);
-	    
-	    var n = x509.subjectPublicKeyRSA.n;
-	    var e =  x509.subjectPublicKeyRSA.e;
-	    
-	    if(LOG>2) console.log('PUBLIC KEY n after is ');
-	    if(LOG>2) console.log(n);
-
-	    if(LOG>2) console.log('EXPONENT e after is ');
-	    if(LOG>2) console.log(e);
-	    
-	    if(result)
-            output += 'SIGNATURE VALID';
-	    else
-            output += 'SIGNATURE INVALID';
-	    
-	    //output += "VALID: "+ toHex(co.signedInfo.locator.publicKey);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	    
-	    //if(LOG>4) console.log('str'[1]);
-	}
-	if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.publicKey!=null){
-	    var publickeyHex = DataUtils.toHex(co.signedInfo.locator.publicKey).toLowerCase();
-	    var publickeyString = DataUtils.toString(co.signedInfo.locator.publicKey);
-	    var signature = DataUtils.toHex(co.signature.signature).toLowerCase();
-	    var input = DataUtils.toString(co.rawSignatureData);
-	    
-	    var wit = null;
-	    var witHex = "";
-		if (co.signature.Witness != null) {
-			wit = new Witness();
-			wit.decode(co.signature.Witness);
-			witHex = DataUtils.toHex(co.signature.Witness);
-		}
-	    
-	    output += "Public key: " + publickeyHex;
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	    
-	    if(LOG>2) console.log(" ContentName + SignedInfo + Content = "+input);
-	    if(LOG>2) console.log(" PublicKeyHex = "+publickeyHex );
-	    if(LOG>2) console.log(" PublicKeyString = "+publickeyString );
-	    
-	    if(LOG>2) console.log(" Signature "+signature );
-	    if(LOG>2) console.log(" Witness "+witHex );
-	    
-	    if(LOG>2) console.log(" Signature NOW IS" );
-	    
-	    if(LOG>2) console.log(co.signature.signature);
-	   
-	    var rsakey = decodeSubjectPublicKeyInfo(co.signedInfo.locator.publicKey);
-
-	    output += "Public key (hex) modulus: " + rsakey.n.toString(16) + "<br/>";
-	    output += "exponent: " + rsakey.e.toString(16) + "<br/>";
-	    output += "<br/>";
-	   	    
-	    var result = rsakey.verifyByteArray(co.rawSignatureData, wit, signature);
-	    // var result = rsakey.verifyString(input, signature);
-	    
-	    if(LOG>2) console.log('PUBLIC KEY n after is ');
-	    if(LOG>2) console.log(rsakey.n);
-
-	    if(LOG>2) console.log('EXPONENT e after is ');
-	    if(LOG>2) console.log(rsakey.e);
-	    
-	    if(result)
-			output += 'SIGNATURE VALID';
-	    else
-			output += 'SIGNATURE INVALID';
-	    
-	    //output += "VALID: "+ toHex(co.signedInfo.locator.publicKey);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	    
-	    //if(LOG>4) console.log('str'[1]);
-	}
-    }
-
-    return output;
-}
-
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- */
-
-var KeyManager = function KeyManager(){
-
-	
-//Certificate
-
-this.certificate = 'MIIBmzCCAQQCCQC32FyQa61S7jANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwd'+
-
-'heGVsY2R2MB4XDTEyMDQyODIzNDQzN1oXDTEyMDUyODIzNDQzN1owEjEQMA4GA1'+
-
-'UEAxMHYXhlbGNkdjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4X0wp9goq'+
-
-'xuECxdULcr2IHr9Ih4Iaypg0Wy39URIup8/CLzQmdsh3RYqd55hqonu5VTTpH3i'+
-
-'MLx6xZDVJAZ8OJi7pvXcQ2C4Re2kjL2c8SanI0RfDhlS1zJadfr1VhRPmpivcYa'+
-
-'wJ4aFuOLAi+qHFxtN7lhcGCgpW1OV60oXd58CAwEAATANBgkqhkiG9w0BAQUFAA'+
-
-'OBgQDLOrA1fXzSrpftUB5Ro6DigX1Bjkf7F5Bkd69hSVp+jYeJFBBlsILQAfSxU'+
-
-'ZPQtD+2Yc3iCmSYNyxqu9PcufDRJlnvB7PG29+L3y9lR37tetzUV9eTscJ7rdp8'+
-
-'Wt6AzpW32IJ/54yKNfP7S6ZIoIG+LP6EIxq6s8K1MXRt8uBJKw==';
-
-
-//this.publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQAB';
-this.publicKey ='30819F300D06092A864886F70D010101050003818D0030818902818100E17D30A7D828AB1B840B17542DCAF6207AFD221E086B2A60D16CB7F54448BA9F3F08BCD099DB21DD162A779E61AA89EEE554D3A47DE230BC7AC590D524067C3898BBA6F5DC4360B845EDA48CBD9CF126A723445F0E1952D7325A75FAF556144F9A98AF7186B0278685B8E2C08BEA87171B4DEE585C1828295B5395EB4A17779F0203010001';
-//Private Key
-
-this.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';
-
-
-/*
-	this.certificate = 
-			'MIIBvTCCASYCCQD55fNzc0WF7TANBgkqhkiG9w0BAQUFADAjMQswCQYDVQQGEwJK'+
-			'UDEUMBIGA1UEChMLMDAtVEVTVC1SU0EwHhcNMTAwNTI4MDIwODUxWhcNMjAwNTI1'+
-			'MDIwODUxWjAjMQswCQYDVQQGEwJKUDEUMBIGA1UEChMLMDAtVEVTVC1SU0EwgZ8w'+
-			'DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANGEYXtfgDRlWUSDn3haY4NVVQiKI9Cz'+
-			'Thoua9+DxJuiseyzmBBe7Roh1RPqdvmtOHmEPbJ+kXZYhbozzPRbFGHCJyBfCLzQ'+
-			'fVos9/qUQ88u83b0SFA2MGmQWQAlRtLy66EkR4rDRwTj2DzR4EEXgEKpIvo8VBs/'+
-			'3+sHLF3ESgAhAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAEZ6mXFFq3AzfaqWHmCy1'+
-			'ARjlauYAa8ZmUFnLm0emg9dkVBJ63aEqARhtok6bDQDzSJxiLpCEF6G4b/Nv/M/M'+
-			'LyhP+OoOTmETMegAVQMq71choVJyOFE5BtQa6M/lCHEOya5QUfoRF2HF9EjRF44K'+
-			'3OK+u3ivTSj3zwjtpudY5Xo=';
-	
-	this.privateKey =
-			'MIICWwIBAAKBgQDRhGF7X4A0ZVlEg594WmODVVUIiiPQs04aLmvfg8SborHss5gQ'+
-			'Xu0aIdUT6nb5rTh5hD2yfpF2WIW6M8z0WxRhwicgXwi80H1aLPf6lEPPLvN29EhQ'+
-			'NjBpkFkAJUbS8uuhJEeKw0cE49g80eBBF4BCqSL6PFQbP9/rByxdxEoAIQIDAQAB'+
-			'AoGAA9/q3Zk6ib2GFRpKDLO/O2KMnAfR+b4XJ6zMGeoZ7Lbpi3MW0Nawk9ckVaX0'+
-			'ZVGqxbSIX5Cvp/yjHHpww+QbUFrw/gCjLiiYjM9E8C3uAF5AKJ0r4GBPl4u8K4bp'+
-			'bXeSxSB60/wPQFiQAJVcA5xhZVzqNuF3EjuKdHsw+dk+dPECQQDubX/lVGFgD/xY'+
-			'uchz56Yc7VHX+58BUkNSewSzwJRbcueqknXRWwj97SXqpnYfKqZq78dnEF10SWsr'+
-			'/NMKi+7XAkEA4PVqDv/OZAbWr4syXZNv/Mpl4r5suzYMMUD9U8B2JIRnrhmGZPzL'+
-			'x23N9J4hEJ+Xh8tSKVc80jOkrvGlSv+BxwJAaTOtjA3YTV+gU7Hdza53sCnSw/8F'+
-			'YLrgc6NOJtYhX9xqdevbyn1lkU0zPr8mPYg/F84m6MXixm2iuSz8HZoyzwJARi2p'+
-			'aYZ5/5B2lwroqnKdZBJMGKFpUDn7Mb5hiSgocxnvMkv6NjT66Xsi3iYakJII9q8C'+
-			'Ma1qZvT/cigmdbAh7wJAQNXyoizuGEltiSaBXx4H29EdXNYWDJ9SS5f070BRbAIl'+
-			'dqRh3rcNvpY6BKJqFapda1DjdcncZECMizT/GMrc1w==';
-			
-			*/
-};
-
-
-KeyManager.prototype.verify = function verify(message,signature){
-	
-	var input = message;
-
-	var  _PEM_X509CERT_STRING_ = this.certificate;
-	
-	var x509 = new X509();
-	
-	x509.readCertPEM(_PEM_X509CERT_STRING_);
-	
-	var result = x509.subjectPublicKeyRSA.verifyString(input, signature);
-	
-	return result;
-};
-
-KeyManager.prototype.sign= function sign(message){
-	
-	var input = message;
-		
-	var  _PEM_PRIVATE_KEY_STRING_ = this.privateKey;
-	
-	var rsa = new RSAKey();
-	
-	rsa.readPrivateKeyFromPEMString(_PEM_PRIVATE_KEY_STRING_);
-	
-	var hSig = rsa.signString(input, "sha256");
-	
-	return hSig;
-
-};
-
-
-
-var globalKeyManager = new KeyManager();
-//var KeyPair = { "public" : "PUBLIC KEY" , "private" : "PRIVATE KEY" };
-
-
-/** 
- * @author: Wentao Shang
- * See COPYING for copyright and distribution information.
- */
-
-var MerklePath = function MerkelPath() {
-	this.index = null;  // int
-	this.digestList = [];  // array of hex string
-};
-
-var Witness = function Witness() {
-	this.oid = null;  // string
-	this.path = new MerklePath();  // MerklePath
-};
-
-function parseOID(bytes, start, end) {
-    var s, n = 0, bits = 0;
-    for (var i = start; i < end; ++i) {
-        var v = bytes[i];
-        n = (n << 7) | (v & 0x7F);
-        bits += 7;
-        if (!(v & 0x80)) { // finished
-            if (s == undefined)
-                s = parseInt(n / 40) + "." + (n % 40);
-            else
-                s += "." + ((bits >= 31) ? "bigint" : n);
-            n = bits = 0;
-        }
-        s += String.fromCharCode();
-    }
-    return s;
-}
-
-function parseInteger(bytes, start, end) {
-    var n = 0;
-    for (var i = start; i < end; ++i)
-        n = (n << 8) | bytes[i];
-    return n;
-}
-
-Witness.prototype.decode = function(/* Uint8Array */ witness) {
-	/* The asn1.js decoder has some bug and 
-	 * cannot decode certain kind of witness.
-	 * So we use an alternative (and dirty) hack
-	 * to read witness from byte streams
-	 *      ------Wentao
-	 */
-	/*
-	var wit = DataUtils.toHex(witness).toLowerCase();
-	try {
-		var der = Hex.decode(wit);
-		var asn1 = ASN1.decode(der);
-	}
-	catch (e) {
-		console.log(e);
-		console.log(wit);
-	}
-	//console.log(asn1.toPrettyString());
-	
-	this.oid = asn1.sub[0].sub[0].content();  // OID
-	//console.log(this.oid);
-	this.path.index = asn1.sub[1].sub[0].sub[0].content();  // index
-	//console.log(this.path.index);
-	for (i = 0; i < asn1.sub[1].sub[0].sub[1].sub.length; i++) {
-		pos = asn1.sub[1].sub[0].sub[1].sub[i].stream.pos;
-		str = wit.substring(2 * pos + 4, 2 * pos + 68);
-		this.path.digestList.push(str);  // digest hex string
-		//console.log(str);
-	}
-	*/
-	
-	// FIXME: Need to be fixed to support arbitrary ASN1 encoding,
-	// But do we really nned that????  -------Wentao
-	
-	// The structure of Witness is fixed as follows:
-	// SEQUENCE  (2 elem)
-	//   SEQUENCE  (1 elem)
-	//     OBJECT IDENTIFIER  1.2.840.113550.11.1.2.2
-	//   OCTET STRING  (1 elem)
-	//     SEQUENCE  (2 elem)
-	//       INTEGER  index
-	//       SEQUENCE  (n elem)
-	//         OCTET STRING(32 byte) 345FB4B5E9A1D2FF450ECA87EB87601683027A1A...
-	//         OCTET STRING(32 byte) DBCEE5B7A6C2B851B029324197DDBD9A655723DC...
-	//         OCTET STRING(32 byte) 4C79B2D256E4CD657A27F01DCB51AC3C56A24E71...
-	//         OCTET STRING(32 byte) 7F7FB169604A87EAC94378F0BDB4FC5D5899AB88...
-	//         ......
-	// Hence we can follow this structure to extract witness fields at fixed level
-	// Tag numbers for ASN1:
-	//    SEQUENCE            0x10
-	//    OCT STRING          0x04
-	//    INTEGER             0x02
-	//    OBJECT IDENTIFIER   0x06
-	var i = 0;
-	var step = 0;  // count of sequence tag
-	while (i < witness.length) {
-		var len = 0;
-		
-		if (witness[i] == 0x30) {
-			// Sequence (constructed)
-			// There is no primitive sequence in Witness
-			if ((witness[i + 1] & 0x80) != 0) {
-				len = witness[i+1] & 0x7F;
-			}
-			step++;
-		} else if (witness[i] == 0x06) {
-			// Decode OID
-			len = witness[i+1];  // XXX: OID will not be longer than 127 bytes
-			this.oid = parseOID(witness, i + 2, i + 2 + len);
-			//console.log(this.oid);
-		} else if (witness[i] == 0x02) {
-			// Decode node index
-			len = witness[i+1];  // XXX: index will not be longer than 127 bytes
-			this.path.index = parseInteger(witness, i + 2, i + 2 + len);
-			//console.log(this.path.index);
-		} else if (witness[i] == 0x04) {
-			if ((witness[i + 1] & 0x80) != 0) {
-				len = witness[i+1] & 0x7F;
-			}
-			if (step == 4) {
-				// Start to decode digest hex string
-				len = witness[i+1];  // XXX: digest hex should always be 32 bytes
-				var str = DataUtils.toHex(witness.subarray(i + 2, i + 2 + len));
-				this.path.digestList.push(str);  // digest hex string
-				//console.log(str);
-			}
-		}
-		i = i + 2 + len;
-	}
-};
-/*
- * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
- * in FIPS 180-2
- * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
- * Distributed under the BSD License
- * See http://pajhome.org.uk/crypt/md5 for details.
- * Also http://anmar.eu.org/projects/jssha2/
- */
-
-/*
- * Configurable variables. You may need to tweak these to be compatible with
- * the server-side, but the defaults work in most cases.
- */
-var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
-var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
-
-/*
- * These are the functions you'll usually want to call
- * They take string arguments and return either hex or base-64 encoded strings
- */
-
-//@author axelcdv
-/**
- * Computes the Sha-256 hash of the given byte array
- * @param {byte[]} 
- * @return the hex string corresponding to the Sha-256 hash of the byte array
- */
-function hex_sha256_from_bytes(byteArray){
-	return rstr2hex(binb2rstr(binb_sha256( byteArray2binb(byteArray), byteArray.length * 8)));
-}
-
-function hex_sha256(s)    { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); }
-function b64_sha256(s)    { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); }
-function any_sha256(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); }
-function hex_hmac_sha256(k, d)
-  { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
-function b64_hmac_sha256(k, d)
-  { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
-function any_hmac_sha256(k, d, e)
-  { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
-
-	
-/*
-	function hex_sha256(s)    { return rstr2hex(rstr_sha256(s)); }
-function b64_sha256(s)    { return rstr2b64(rstr_sha256(s)); }
-function any_sha256(s, e) { return rstr2any(rstr_sha256(s), e); }
-function hex_hmac_sha256(k, d)
-  { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), d)); }
-function b64_hmac_sha256(k, d)
-  { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), d)); }
-function any_hmac_sha256(k, d, e)
-  { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), d), e); }
-*/
-	
-/*
- * Perform a simple self-test to see if the VM is working
- */
-function sha256_vm_test()
-{
-  return hex_sha256("abc").toLowerCase() ==
-            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
-}
-
-/**
- * Calculate the sha256 of a raw string
- * @param s: the raw string
- */
-function rstr_sha256(s)
-{
-  return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8));
-}
-
-/**
- * Calculate the HMAC-sha256 of a key and some data (raw strings)
- */
-function rstr_hmac_sha256(key, data)
-{
-  var bkey = rstr2binb(key);
-  if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8);
-
-  var ipad = Array(16), opad = Array(16);
-  for(var i = 0; i < 16; i++)
-  {
-    ipad[i] = bkey[i] ^ 0x36363636;
-    opad[i] = bkey[i] ^ 0x5C5C5C5C;
-  }
-
-  var hash = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
-  return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256));
-}
-
-/**
- * Convert a raw string to a hex string
- */
-function rstr2hex(input)
-{
-  try { hexcase } catch(e) { hexcase=0; }
-  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
-  var output = "";
-  var x;
-  for(var i = 0; i < input.length; i++)
-  {
-    x = input.charCodeAt(i);
-    output += hex_tab.charAt((x >>> 4) & 0x0F)
-           +  hex_tab.charAt( x        & 0x0F);
-  }
-  return output;
-}
-
-/*
- * Convert a raw string to a base-64 string
- */
-function rstr2b64(input)
-{
-  try { b64pad } catch(e) { b64pad=''; }
-  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-  var output = "";
-  var len = input.length;
-  for(var i = 0; i < len; i += 3)
-  {
-    var triplet = (input.charCodeAt(i) << 16)
-                | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
-                | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
-    for(var j = 0; j < 4; j++)
-    {
-      if(i * 8 + j * 6 > input.length * 8) output += b64pad;
-      else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
-    }
-  }
-  return output;
-}
-
-/*
- * Convert a raw string to an arbitrary string encoding
- */
-function rstr2any(input, encoding)
-{
-  var divisor = encoding.length;
-  var remainders = Array();
-  var i, q, x, quotient;
-
-  /* Convert to an array of 16-bit big-endian values, forming the dividend */
-  var dividend = Array(Math.ceil(input.length / 2));
-  for(i = 0; i < dividend.length; i++)
-  {
-    dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
-  }
-
-  /*
-   * Repeatedly perform a long division. The binary array forms the dividend,
-   * the length of the encoding is the divisor. Once computed, the quotient
-   * forms the dividend for the next step. We stop when the dividend is zero.
-   * All remainders are stored for later use.
-   */
-  while(dividend.length > 0)
-  {
-    quotient = Array();
-    x = 0;
-    for(i = 0; i < dividend.length; i++)
-    {
-      x = (x << 16) + dividend[i];
-      q = Math.floor(x / divisor);
-      x -= q * divisor;
-      if(quotient.length > 0 || q > 0)
-        quotient[quotient.length] = q;
-    }
-    remainders[remainders.length] = x;
-    dividend = quotient;
-  }
-
-  /* Convert the remainders to the output string */
-  var output = "";
-  for(i = remainders.length - 1; i >= 0; i--)
-    output += encoding.charAt(remainders[i]);
-
-  /* Append leading zero equivalents */
-  var full_length = Math.ceil(input.length * 8 /
-                                    (Math.log(encoding.length) / Math.log(2)))
-  for(i = output.length; i < full_length; i++)
-    output = encoding[0] + output;
-
-  return output;
-}
-
-/*
- * Encode a string as utf-8.
- * For efficiency, this assumes the input is valid utf-16.
- */
-function str2rstr_utf8(input)
-{
-  var output = "";
-  var i = -1;
-  var x, y;
-
-  while(++i < input.length)
-  {
-    /* Decode utf-16 surrogate pairs */
-    x = input.charCodeAt(i);
-    y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
-    if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
-    {
-      x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
-      i++;
-    }
-
-    /* Encode output as utf-8 */
-    if(x <= 0x7F)
-      output += String.fromCharCode(x);
-    else if(x <= 0x7FF)
-      output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
-                                    0x80 | ( x         & 0x3F));
-    else if(x <= 0xFFFF)
-      output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
-                                    0x80 | ((x >>> 6 ) & 0x3F),
-                                    0x80 | ( x         & 0x3F));
-    else if(x <= 0x1FFFFF)
-      output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
-                                    0x80 | ((x >>> 12) & 0x3F),
-                                    0x80 | ((x >>> 6 ) & 0x3F),
-                                    0x80 | ( x         & 0x3F));
-  }
-  return output;
-}
-
-/*
- * Encode a string as utf-16
- */
-function str2rstr_utf16le(input)
-{
-  var output = "";
-  for(var i = 0; i < input.length; i++)
-    output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
-                                  (input.charCodeAt(i) >>> 8) & 0xFF);
-  return output;
-}
-
-function str2rstr_utf16be(input)
-{
-  var output = "";
-  for(var i = 0; i < input.length; i++)
-    output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
-                                   input.charCodeAt(i)        & 0xFF);
-  return output;
-}
-
-/**
- * Convert a raw string to an array of big-endian words
- * Characters >255 have their high-byte silently ignored.
- */
-function rstr2binb(input)
-{
-  //console.log('Raw string comming is '+input);
-  var output = Array(input.length >> 2);
-  /* JavaScript automatically zeroizes a new array.
-  for(var i = 0; i < output.length; i++)
-    output[i] = 0;
-   */
-  for(var i = 0; i < input.length * 8; i += 8)
-    output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
-  return output;
-}
-
-/**
- * @author axelcdv
- * Convert a byte array to an array of big-endian words
- * @param {byte[]} input
- * @return the array of big-endian words
- */
-function byteArray2binb(input){
-	//console.log("Byte array coming is " + input);
-	var output = Array(input.length >> 2);
-      /* JavaScript automatically zeroizes a new array.
-	  for(var i = 0; i < output.length; i++)
-	    output[i] = 0;
-       */
-	  for(var i = 0; i < input.length * 8; i += 8)
-	    output[i>>5] |= (input[i / 8] & 0xFF) << (24 - i % 32);
-	  return output;
-}
-
-/*
- * Convert an array of big-endian words to a string
- */
-function binb2rstr(input)
-{
-  var output = "";
-  for(var i = 0; i < input.length * 32; i += 8)
-    output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
-  return output;
-}
-
-/*
- * Main sha256 function, with its support functions
- */
-function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
-function sha256_R (X, n) {return ( X >>> n );}
-function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
-function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
-function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
-function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
-function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
-function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
-function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
-function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
-function sha256_Gamma0512(x) {return (sha256_S(x, 1)  ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
-function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
-
-var sha256_K = new Array
-(
-  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(m, l)
-{
-  var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534,
-                       1359893119, -1694144372, 528734635, 1541459225);
-  var W = new Array(64);
-
-  /* append padding */
-  m[l >> 5] |= 0x80 << (24 - l % 32);
-  m[((l + 64 >> 9) << 4) + 15] = l;
- 
-  for(var offset = 0; offset < m.length; offset += 16)
-    processBlock_sha256(m, offset, HASH, W);
-
-  return HASH;
-}
-
-/*
- * Process a block of 16 4-byte words in m starting at offset and update HASH.  
- * offset must be a multiple of 16 and less than m.length.  W is a scratchpad Array(64).
- */
-function processBlock_sha256(m, offset, HASH, W) {
-    var a, b, c, d, e, f, g, h;
-    var j, T1, T2;
-    
-    a = HASH[0];
-    b = HASH[1];
-    c = HASH[2];
-    d = HASH[3];
-    e = HASH[4];
-    f = HASH[5];
-    g = HASH[6];
-    h = HASH[7];
-
-    for(j = 0; j < 64; j++)
-    {
-      if (j < 16) W[j] = m[j + offset];
-      else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
-                                            sha256_Gamma0256(W[j - 15])), W[j - 16]);
-
-      T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
-                                                          sha256_K[j]), W[j]);
-      T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
-      h = g;
-      g = f;
-      f = e;
-      e = safe_add(d, T1);
-      d = c;
-      c = b;
-      b = a;
-      a = safe_add(T1, T2);
-    }
-
-    HASH[0] = safe_add(a, HASH[0]);
-    HASH[1] = safe_add(b, HASH[1]);
-    HASH[2] = safe_add(c, HASH[2]);
-    HASH[3] = safe_add(d, HASH[3]);
-    HASH[4] = safe_add(e, HASH[4]);
-    HASH[5] = safe_add(f, HASH[5]);
-    HASH[6] = safe_add(g, HASH[6]);
-    HASH[7] = safe_add(h, HASH[7]);
-}
-
-function safe_add (x, y)
-{
-  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
-  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
-  return (msw << 16) | (lsw & 0xFFFF);
-}
-
-/*
- * Create a Sha256, call update(data) multiple times, then call finalize().
- */
-var Sha256 = function Sha256() {
-    this.W = new Array(64);
-    this.hash = new Array(1779033703, -1150833019, 1013904242, -1521486534,
-                          1359893119, -1694144372, 528734635, 1541459225);
-    this.nTotalBytes = 0;
-    this.buffer = new Uint8Array(16 * 4);
-    this.nBufferBytes = 0;
-}
-
-/*
- * Update the hash with data, which is Uint8Array.
- */
-Sha256.prototype.update = function(data) {
-    this.nTotalBytes += data.length;
-    
-    if (this.nBufferBytes > 0) {
-        // Fill up the buffer and process it first.
-        var bytesNeeded = this.buffer.length - this.nBufferBytes;
-        if (data.length < bytesNeeded) {
-            this.buffer.set(data, this.nBufferBytes);
-            this.nBufferBytes += data.length;
-            return;
-        }
-        else {
-            this.buffer.set(data.subarray(0, bytesNeeded), this.nBufferBytes);
-            processBlock_sha256(byteArray2binb(this.buffer), 0, this.hash, this.W);
-            this.nBufferBytes = 0;
-            // Consume the bytes from data.
-            data = data.subarray(bytesNeeded, data.length);
-            if (data.length == 0)
-                return;
-        }
-    }
-    
-    // 2^6 is 16 * 4.
-    var nBlocks = data.length >> 6;
-    if (nBlocks > 0) {
-        var nBytes = nBlocks * 16 * 4;
-        var m = byteArray2binb(data.subarray(0, nBytes));
-        for(var offset = 0; offset < m.length; offset += 16)
-            processBlock_sha256(m, offset, this.hash, this.W);
-
-        data = data.subarray(nBytes, data.length);
-    }
-    
-    if (data.length > 0) {
-        // Save the remainder in the buffer.
-        this.buffer.set(data);
-        this.nBufferBytes = data.length;
-    }
-}
-
-/*
- * Finalize the hash and return the result as Uint8Array.
- * Only call this once.  Return values on subsequent calls are undefined.
- */
-Sha256.prototype.finalize = function() {
-    var m = byteArray2binb(this.buffer.subarray(0, this.nBufferBytes));
-    /* append padding */
-    var l = this.nBufferBytes * 8;
-    m[l >> 5] |= 0x80 << (24 - l % 32);
-    m[((l + 64 >> 9) << 4) + 15] = this.nTotalBytes * 8;
-
-    for(var offset = 0; offset < m.length; offset += 16)
-        processBlock_sha256(m, offset, this.hash, this.W);
-
-    return Sha256.binb2Uint8Array(this.hash);
-}
-
-/*
- * Convert an array of big-endian words to Uint8Array.
- */
-Sha256.binb2Uint8Array = function(input)
-{
-    var output = new Uint8Array(input.length * 4);
-    var iOutput = 0;
-    for (var i = 0; i < input.length * 32; i += 8)
-        output[iOutput++] = (input[i>>5] >>> (24 - i % 32)) & 0xFF;
-    return output;
-}
 var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 var b64pad="=";
 
@@ -5031,7 +1693,7 @@
     c = parseInt(h.substring(i,i+2),16);
     ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
   }
-  while((ret.length & 3) > 0) ret += b64pad;
+  if (b64pad) while((ret.length & 3) > 0) ret += b64pad;
   return ret;
 }
 
@@ -5041,9 +1703,10 @@
   var i;
   var k = 0; // b64 state, 0-3
   var slop;
+  var v;
   for(i = 0; i < s.length; ++i) {
     if(s.charAt(i) == b64pad) break;
-    var v = b64map.indexOf(s.charAt(i));
+    v = b64map.indexOf(s.charAt(i));
     if(v < 0) continue;
     if(k == 0) {
       ret += int2char(v >> 2);
@@ -5083,10 +1746,137 @@
   }
   return a;
 }
+
+exports.b64tohex = b64tohex;
+exports.b64toBA  = b64toBA;
+exports.hex2b64  = hex2b64;
+
+module.exports = exports;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// prng4.js - uses Arcfour as a PRNG
+
+function Arcfour() {
+  this.i = 0;
+  this.j = 0;
+  this.S = new Array();
+}
+
+// Initialize arcfour context from key, an array of ints, each from [0..255]
+function ARC4init(key) {
+  var i, j, t;
+  for(i = 0; i < 256; ++i)
+    this.S[i] = i;
+  j = 0;
+  for(i = 0; i < 256; ++i) {
+    j = (j + this.S[i] + key[i % key.length]) & 255;
+    t = this.S[i];
+    this.S[i] = this.S[j];
+    this.S[j] = t;
+  }
+  this.i = 0;
+  this.j = 0;
+}
+
+function ARC4next() {
+  var t;
+  this.i = (this.i + 1) & 255;
+  this.j = (this.j + this.S[this.i]) & 255;
+  t = this.S[this.i];
+  this.S[this.i] = this.S[this.j];
+  this.S[this.j] = t;
+  return this.S[(t + this.S[this.i]) & 255];
+}
+
+Arcfour.prototype.init = ARC4init;
+Arcfour.prototype.next = ARC4next;
+
+// Plug in your RNG constructor here
+function prng_newstate() {
+  return new Arcfour();
+}
+
+// Pool size must be a multiple of 4 and greater than 32.
+// An array of bytes the size of the pool will be passed to init()
+var rng_psize = 256;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// Random number generator - requires a PRNG backend, e.g. prng4.js
+
+// For best results, put code like
+// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
+// in your main HTML document.
+
+var rng_state;
+var rng_pool;
+var rng_pptr;
+
+// Mix in a 32-bit integer into the pool
+function rng_seed_int(x) {
+  rng_pool[rng_pptr++] ^= x & 255;
+  rng_pool[rng_pptr++] ^= (x >> 8) & 255;
+  rng_pool[rng_pptr++] ^= (x >> 16) & 255;
+  rng_pool[rng_pptr++] ^= (x >> 24) & 255;
+  if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
+}
+
+// Mix in the current time (w/milliseconds) into the pool
+function rng_seed_time() {
+  rng_seed_int(new Date().getTime());
+}
+
+// Initialize the pool with junk if needed.
+if(rng_pool == null) {
+  rng_pool = new Array();
+  rng_pptr = 0;
+  var t;
+  if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
+    // Extract entropy (256 bits) from NS4 RNG if available
+    var z = window.crypto.random(32);
+    for(t = 0; t < z.length; ++t)
+      rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
+  }  
+  while(rng_pptr < rng_psize) {  // extract some randomness from Math.random()
+    t = Math.floor(65536 * Math.random());
+    rng_pool[rng_pptr++] = t >>> 8;
+    rng_pool[rng_pptr++] = t & 255;
+  }
+  rng_pptr = 0;
+  rng_seed_time();
+  //rng_seed_int(window.screenX);
+  //rng_seed_int(window.screenY);
+}
+
+function rng_get_byte() {
+  if(rng_state == null) {
+    rng_seed_time();
+    rng_state = prng_newstate();
+    rng_state.init(rng_pool);
+    for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
+      rng_pool[rng_pptr] = 0;
+    rng_pptr = 0;
+    //rng_pool = null;
+  }
+  // TODO: allow reseeding after first request
+  return rng_state.next();
+}
+
+function rng_get_bytes(ba) {
+  var i;
+  for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
+}
+
+function SecureRandom() {}
+
+SecureRandom.prototype.nextBytes = rng_get_bytes;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
 // Depends on jsbn.js and rng.js
 
 // Version 1.1: support utf-8 encoding in pkcs1pad2
 
+var intShim = require("jsbn");
+
 // convert a (hex) string to a bignum object
 function parseBigInt(str,r) {
   return new BigInteger(str,r);
@@ -5109,11 +1899,7 @@
     return b.toString(16);
 }
 
-/**
- * PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
- * @param s: the string to encode
- * @param n: the size in byte
- */ 
+// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
 function pkcs1pad2(s,n) {
   if(n < s.length + 11) { // TODO: fix for utf-8
     alert("Message too long for RSA");
@@ -5149,10 +1935,65 @@
   return new BigInteger(ba);
 }
 
-/** 
- * "empty" RSA key constructor
- * @returns {RSAKey}
- */
+// PKCS#1 (OAEP) mask generation function
+function oaep_mgf1_arr(seed, len, hash)
+{
+    var mask = '', i = 0;
+
+    while (mask.length < len)
+    {
+        mask += hash(String.fromCharCode.apply(String, seed.concat([
+                (i & 0xff000000) >> 24,
+                (i & 0x00ff0000) >> 16,
+                (i & 0x0000ff00) >> 8,
+                i & 0x000000ff])));
+        i += 1;
+    }
+
+    return mask;
+}
+
+var SHA1_SIZE = 20;
+
+// PKCS#1 (OAEP) pad input string s to n bytes, and return a bigint
+function oaep_pad(s, n, hash)
+{
+    if (s.length + 2 * SHA1_SIZE + 2 > n)
+    {
+        throw "Message too long for RSA";
+    }
+
+    var PS = '', i;
+
+    for (i = 0; i < n - s.length - 2 * SHA1_SIZE - 2; i += 1)
+    {
+        PS += '\x00';
+    }
+
+    var DB = rstr_sha1('') + PS + '\x01' + s;
+    var seed = new Array(SHA1_SIZE);
+    new SecureRandom().nextBytes(seed);
+    
+    var dbMask = oaep_mgf1_arr(seed, DB.length, hash || rstr_sha1);
+    var maskedDB = [];
+
+    for (i = 0; i < DB.length; i += 1)
+    {
+        maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+    }
+
+    var seedMask = oaep_mgf1_arr(maskedDB, seed.length, rstr_sha1);
+    var maskedSeed = [0];
+
+    for (i = 0; i < seed.length; i += 1)
+    {
+        maskedSeed[i + 1] = seed[i] ^ seedMask.charCodeAt(i);
+    }
+
+    return new BigInteger(maskedSeed.concat(maskedDB));
+}
+
+// "empty" RSA key constructor
 function RSAKey() {
   this.n = null;
   this.e = 0;
@@ -5164,14 +2005,15 @@
   this.coeff = null;
 }
 
-/** 
- * Set the public key fields N and e from hex strings
- * @param N
- * @param E
- * @returns {RSASetPublic}
- */
+// Set the public key fields N and e from hex strings
 function RSASetPublic(N,E) {
-  if(N != null && E != null && N.length > 0 && E.length > 0) {
+  this.isPublic = true;
+  if (typeof N !== "string") 
+  {
+    this.n = N;
+    this.e = E;
+  }
+  else if(N != null && E != null && N.length > 0 && E.length > 0) {
     this.n = parseBigInt(N,16);
     this.e = parseInt(E,16);
   }
@@ -5179,18 +2021,12 @@
     alert("Invalid RSA public key");
 }
 
-/** 
- * Perform raw public operation on "x": return x^e (mod n)
- * @param x
- * @returns x^e (mod n)
- */
+// Perform raw public operation on "x": return x^e (mod n)
 function RSADoPublic(x) {
   return x.modPowInt(this.e, this.n);
 }
 
-/**
- * Return the PKCS#1 RSA encryption of "text" as an even-length hex string
- */ 
+// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
 function RSAEncrypt(text) {
   var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
   if(m == null) return null;
@@ -5200,6 +2036,16 @@
   if((h.length & 1) == 0) return h; else return "0" + h;
 }
 
+// Return the PKCS#1 OAEP RSA encryption of "text" as an even-length hex string
+function RSAEncryptOAEP(text, hash) {
+  var m = oaep_pad(text, (this.n.bitLength()+7)>>3, hash);
+  if(m == null) return null;
+  var c = this.doPublic(m);
+  if(c == null) return null;
+  var h = c.toString(16);
+  if((h.length & 1) == 0) return h; else return "0" + h;
+}
+
 // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
 //function RSAEncryptB64(text) {
 //  var h = this.encrypt(text);
@@ -5212,11 +2058,23 @@
 // public
 RSAKey.prototype.setPublic = RSASetPublic;
 RSAKey.prototype.encrypt = RSAEncrypt;
+RSAKey.prototype.encryptOAEP = RSAEncryptOAEP;
 //RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
+
+RSAKey.prototype.type = "RSA";
+
+exports.RSAKey = RSAKey;
+module.exports = exports;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
 // Depends on rsa.js and jsbn2.js
 
 // Version 1.1: support utf-8 decoding in pkcs1unpad2
 
+var intShim = require("jsbn");
+var BigInteger = intShim.BigInteger ? intShim.BigInteger : intShim ;
+var RSAKey = require('./rsa.js').RSAKey;
+
 // Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
 function pkcs1unpad2(d,n) {
   var b = d.toByteArray();
@@ -5245,9 +2103,101 @@
   return ret;
 }
 
+// PKCS#1 (OAEP) mask generation function
+function oaep_mgf1_str(seed, len, hash)
+{
+    var mask = '', i = 0;
+
+    while (mask.length < len)
+    {
+        mask += hash(seed + String.fromCharCode.apply(String, [
+                (i & 0xff000000) >> 24,
+                (i & 0x00ff0000) >> 16,
+                (i & 0x0000ff00) >> 8,
+                i & 0x000000ff]));
+        i += 1;
+    }
+
+    return mask;
+}
+
+var SHA1_SIZE = 20;
+
+// Undo PKCS#1 (OAEP) padding and, if valid, return the plaintext
+function oaep_unpad(d, n, hash)
+{
+    d = d.toByteArray();
+
+    var i;
+
+    for (i = 0; i < d.length; i += 1)
+    {
+        d[i] &= 0xff;
+    }
+
+    while (d.length < n)
+    {
+        d.unshift(0);
+    }
+
+    d = String.fromCharCode.apply(String, d);
+
+    if (d.length < 2 * SHA1_SIZE + 2)
+    {
+        throw "Cipher too short";
+    }
+
+    var maskedSeed = d.substr(1, SHA1_SIZE)
+    var maskedDB = d.substr(SHA1_SIZE + 1);
+
+    var seedMask = oaep_mgf1_str(maskedDB, SHA1_SIZE, hash || rstr_sha1);
+    var seed = [], i;
+
+    for (i = 0; i < maskedSeed.length; i += 1)
+    {
+        seed[i] = maskedSeed.charCodeAt(i) ^ seedMask.charCodeAt(i);
+    }
+
+    var dbMask = oaep_mgf1_str(String.fromCharCode.apply(String, seed),
+                           d.length - SHA1_SIZE, rstr_sha1);
+
+    var DB = [];
+
+    for (i = 0; i < maskedDB.length; i += 1)
+    {
+        DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+    }
+
+    DB = String.fromCharCode.apply(String, DB);
+
+    if (DB.substr(0, SHA1_SIZE) !== rstr_sha1(''))
+    {
+        throw "Hash mismatch";
+    }
+
+    DB = DB.substr(SHA1_SIZE);
+
+    var first_one = DB.indexOf('\x01');
+    var last_zero = (first_one != -1) ? DB.substr(0, first_one).lastIndexOf('\x00') : -1;
+
+    if (last_zero + 1 != first_one)
+    {
+        throw "Malformed data";
+    }
+
+    return DB.substr(first_one + 1);
+}
+
 // Set the private key fields N, e, and d from hex strings
 function RSASetPrivate(N,E,D) {
-  if(N != null && E != null && N.length > 0 && E.length > 0) {
+  this.isPrivate = true;
+  if (typeof N !== "string")
+  {
+    this.n = N;
+    this.e = E;
+    this.d = D;
+  }
+  else if(N != null && E != null && N.length > 0 && E.length > 0) {
     this.n = parseBigInt(N,16);
     this.e = parseInt(E,16);
     this.d = parseBigInt(D,16);
@@ -5258,7 +2208,13 @@
 
 // Set the private key fields N, e, d and CRT params from hex strings
 function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
-  if(N != null && E != null && N.length > 0 && E.length > 0) {
+  this.isPrivate = true;
+  if (N == null) throw "RSASetPrivateEx N == null";
+  if (E == null) throw "RSASetPrivateEx E == null";
+  if (N.length == 0) throw "RSASetPrivateEx N.length == 0";
+  if (E.length == 0) throw "RSASetPrivateEx E.length == 0";
+
+  if (N != null && E != null && N.length > 0 && E.length > 0) {
     this.n = parseBigInt(N,16);
     this.e = parseInt(E,16);
     this.d = parseBigInt(D,16);
@@ -5267,14 +2223,12 @@
     this.dmp1 = parseBigInt(DP,16);
     this.dmq1 = parseBigInt(DQ,16);
     this.coeff = parseBigInt(C,16);
+  } else {
+    alert("Invalid RSA private key in RSASetPrivateEx");
   }
-  else
-    alert("Invalid RSA private key");
 }
 
-/**
- * Generate a new random private key B bits long, using public expt E
- */
+// Generate a new random private key B bits long, using public expt E
 function RSAGenerate(B,E) {
   var rng = new SecureRandom();
   var qs = B>>1;
@@ -5306,12 +2260,10 @@
       break;
     }
   }
+  this.isPrivate = true;
 }
 
-/**
- * Perform raw private operation on "x": return x^d (mod n)
- * @return x^d (mod n)
- */ 
+// Perform raw private operation on "x": return x^d (mod n)
 function RSADoPrivate(x) {
   if(this.p == null || this.q == null)
     return x.modPow(this.d, this.n);
@@ -5338,6 +2290,15 @@
   return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
 }
 
+// Return the PKCS#1 OAEP RSA decryption of "ctext".
+// "ctext" is an even-length hex string and the output is a plain string.
+function RSADecryptOAEP(ctext, hash) {
+  var c = parseBigInt(ctext, 16);
+  var m = this.doPrivate(c);
+  if(m == null) return null;
+  return oaep_unpad(m, (this.n.bitLength()+7)>>3, hash);
+}
+
 // Return the PKCS#1 RSA decryption of "ctext".
 // "ctext" is a Base64-encoded string and the output is a plain string.
 //function RSAB64Decrypt(ctext) {
@@ -5353,16 +2314,1256 @@
 RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
 RSAKey.prototype.generate = RSAGenerate;
 RSAKey.prototype.decrypt = RSADecrypt;
+RSAKey.prototype.decryptOAEP = RSADecryptOAEP;
 //RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
+
+exports.RSAKey = RSAKey;
+module.exports = exports;
+/*! crypto-1.1.7.js (c) 2013-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * crypto.js - Cryptographic Algorithm Provider class
+ *
+ * Copyright (c) 2013-2015 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license
+ *
+ * The above copyright and license notice shall be 
+ * included in all copies or substantial portions of the Software.
+ */
+
+/**
+ * @fileOverview
+ * @name crypto-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version 1.1.7 (2015-Oct-11)
+ * @since jsrsasign 2.2
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ */
+
+var CryptoJS = require('./sha256.js').CryptoJS
+  , intShim = require('jsbn');
+
+
+/** 
+ * kjur's class library name space
+ * @name KJUR
+ * @namespace kjur's class library name space
+ */
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+/**
+ * kjur's cryptographic algorithm provider library name space
+ * <p>
+ * This namespace privides following crytpgrahic classes.
+ * <ul>
+ * <li>{@link KJUR.crypto.MessageDigest} - Java JCE(cryptograhic extension) style MessageDigest class</li>
+ * <li>{@link KJUR.crypto.Signature} - Java JCE(cryptograhic extension) style Signature class</li>
+ * <li>{@link KJUR.crypto.Util} - cryptographic utility functions and properties</li>
+ * </ul>
+ * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
+ * </p>
+ * @name KJUR.crypto
+ * @namespace
+ */
+if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
+
+/**
+ * static object for cryptographic function utilities
+ * @name KJUR.crypto.Util
+ * @class static object for cryptographic function utilities
+ * @property {Array} DIGESTINFOHEAD PKCS#1 DigestInfo heading hexadecimal bytes for each hash algorithms
+ * @property {Array} DEFAULTPROVIDER associative array of default provider name for each hash and signature algorithms
+ * @description
+ */
+KJUR.crypto.Util = new function() {
+    this.DIGESTINFOHEAD = {
+	'sha1':      "3021300906052b0e03021a05000414",
+        'sha224':    "302d300d06096086480165030402040500041c",
+	'sha256':    "3031300d060960864801650304020105000420",
+	'sha384':    "3041300d060960864801650304020205000430",
+	'sha512':    "3051300d060960864801650304020305000440",
+	'md2':       "3020300c06082a864886f70d020205000410",
+	'md5':       "3020300c06082a864886f70d020505000410",
+	'ripemd160': "3021300906052b2403020105000414"
+    };
+
+    /*
+     * @since crypto 1.1.1
+     */
+    this.DEFAULTPROVIDER = {
+	'md5':			'cryptojs',
+	'sha1':			'cryptojs',
+	'sha224':		'cryptojs',
+	'sha256':		'cryptojs',
+	'sha384':		'cryptojs',
+	'sha512':		'cryptojs',
+	'ripemd160':		'cryptojs',
+	'hmacmd5':		'cryptojs',
+	'hmacsha1':		'cryptojs',
+	'hmacsha224':		'cryptojs',
+	'hmacsha256':		'cryptojs',
+	'hmacsha384':		'cryptojs',
+	'hmacsha512':		'cryptojs',
+	'hmacripemd160':	'cryptojs',
+
+	'MD5withRSA':		'cryptojs/jsrsa',
+	'SHA1withRSA':		'cryptojs/jsrsa',
+	'SHA224withRSA':	'cryptojs/jsrsa',
+	'SHA256withRSA':	'cryptojs/jsrsa',
+	'SHA384withRSA':	'cryptojs/jsrsa',
+	'SHA512withRSA':	'cryptojs/jsrsa',
+	'RIPEMD160withRSA':	'cryptojs/jsrsa',
+
+	'MD5withECDSA':		'cryptojs/jsrsa',
+	'SHA1withECDSA':	'cryptojs/jsrsa',
+	'SHA224withECDSA':	'cryptojs/jsrsa',
+	'SHA256withECDSA':	'cryptojs/jsrsa',
+	'SHA384withECDSA':	'cryptojs/jsrsa',
+	'SHA512withECDSA':	'cryptojs/jsrsa',
+	'RIPEMD160withECDSA':	'cryptojs/jsrsa',
+
+	'SHA1withDSA':		'cryptojs/jsrsa',
+	'SHA224withDSA':	'cryptojs/jsrsa',
+	'SHA256withDSA':	'cryptojs/jsrsa',
+
+	'MD5withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA1withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA224withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA256withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA384withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA512withRSAandMGF1':		'cryptojs/jsrsa',
+	'RIPEMD160withRSAandMGF1':	'cryptojs/jsrsa'
+    };
+
+    /*
+     * @since crypto 1.1.2
+     */
+    this.CRYPTOJSMESSAGEDIGESTNAME = {
+	'md5':		'CryptoJS.algo.MD5',
+	'sha1':		'CryptoJS.algo.SHA1',
+	'sha224':	'CryptoJS.algo.SHA224',
+	'sha256':	'CryptoJS.algo.SHA256',
+	'sha384':	'CryptoJS.algo.SHA384',
+	'sha512':	'CryptoJS.algo.SHA512',
+	'ripemd160':	'CryptoJS.algo.RIPEMD160'
+    };
+
+    /**
+     * get hexadecimal DigestInfo
+     * @name getDigestInfoHex
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} hHash hexadecimal hash value
+     * @param {String} alg hash algorithm name (ex. 'sha1')
+     * @return {String} hexadecimal string DigestInfo ASN.1 structure
+     */
+    this.getDigestInfoHex = function(hHash, alg) {
+	if (typeof this.DIGESTINFOHEAD[alg] == "undefined")
+	    throw "alg not supported in Util.DIGESTINFOHEAD: " + alg;
+	return this.DIGESTINFOHEAD[alg] + hHash;
+    };
+
+    /**
+     * get PKCS#1 padded hexadecimal DigestInfo
+     * @name getPaddedDigestInfoHex
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} hHash hexadecimal hash value of message to be signed
+     * @param {String} alg hash algorithm name (ex. 'sha1')
+     * @param {Integer} keySize key bit length (ex. 1024)
+     * @return {String} hexadecimal string of PKCS#1 padded DigestInfo
+     */
+    this.getPaddedDigestInfoHex = function(hHash, alg, keySize) {
+	var hDigestInfo = this.getDigestInfoHex(hHash, alg);
+	var pmStrLen = keySize / 4; // minimum PM length
+
+	if (hDigestInfo.length + 22 > pmStrLen) // len(0001+ff(*8)+00+hDigestInfo)=22
+	    throw "key is too short for SigAlg: keylen=" + keySize + "," + alg;
+
+	var hHead = "0001";
+	var hTail = "00" + hDigestInfo;
+	var hMid = "";
+	var fLen = pmStrLen - hHead.length - hTail.length;
+	for (var i = 0; i < fLen; i += 2) {
+	    hMid += "ff";
+	}
+	var hPaddedMessage = hHead + hMid + hTail;
+	return hPaddedMessage;
+    };
+
+    /**
+     * get hexadecimal hash of string with specified algorithm
+     * @name hashString
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @param {String} alg hash algorithm name
+     * @return {String} hexadecimal string of hash value
+     * @since 1.1.1
+     */
+    this.hashString = function(s, alg) {
+        var md = new KJUR.crypto.MessageDigest({'alg': alg});
+        return md.digestString(s);
+    };
+
+    /**
+     * get hexadecimal hash of hexadecimal string with specified algorithm
+     * @name hashHex
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} sHex input hexadecimal string to be hashed
+     * @param {String} alg hash algorithm name
+     * @return {String} hexadecimal string of hash value
+     * @since 1.1.1
+     */
+    this.hashHex = function(sHex, alg) {
+        var md = new KJUR.crypto.MessageDigest({'alg': alg});
+        return md.digestHex(sHex);
+    };
+
+    /**
+     * get hexadecimal SHA1 hash of string
+     * @name sha1
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.sha1 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha1', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    /**
+     * get hexadecimal SHA256 hash of string
+     * @name sha256
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.sha256 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    this.sha256Hex = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
+        return md.digestHex(s);
+    };
+
+    /**
+     * get hexadecimal SHA512 hash of string
+     * @name sha512
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.sha512 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    this.sha512Hex = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
+        return md.digestHex(s);
+    };
+
+    /**
+     * get hexadecimal MD5 hash of string
+     * @name md5
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.md5 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'md5', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    /**
+     * get hexadecimal RIPEMD160 hash of string
+     * @name ripemd160
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.ripemd160 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    /*
+     * @since 1.1.2
+     */
+    this.getCryptoJSMDByName = function(s) {
+	
+    };
+};
+
+/**
+ * MessageDigest class which is very similar to java.security.MessageDigest class
+ * @name KJUR.crypto.MessageDigest
+ * @class MessageDigest class which is very similar to java.security.MessageDigest class
+ * @param {Array} params parameters for constructor
+ * @description
+ * <br/>
+ * Currently this supports following algorithm and providers combination:
+ * <ul>
+ * <li>md5 - cryptojs</li>
+ * <li>sha1 - cryptojs</li>
+ * <li>sha224 - cryptojs</li>
+ * <li>sha256 - cryptojs</li>
+ * <li>sha384 - cryptojs</li>
+ * <li>sha512 - cryptojs</li>
+ * <li>ripemd160 - cryptojs</li>
+ * <li>sha256 - sjcl (NEW from crypto.js 1.0.4)</li>
+ * </ul>
+ * @example
+ * // CryptoJS provider sample
+ * var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"});
+ * md.updateString('aaa')
+ * var mdHex = md.digest()
+ *
+ * // SJCL(Stanford JavaScript Crypto Library) provider sample
+ * var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only
+ * md.updateString('aaa')
+ * var mdHex = md.digest()
+ */
+KJUR.crypto.MessageDigest = function(params) {
+    var md = null;
+    var algName = null;
+    var provName = null;
+
+    /**
+     * set hash algorithm and provider
+     * @name setAlgAndProvider
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} alg hash algorithm name
+     * @param {String} prov provider name
+     * @description
+     * @example
+     * // for SHA1
+     * md.setAlgAndProvider('sha1', 'cryptojs');
+     * // for RIPEMD160
+     * md.setAlgAndProvider('ripemd160', 'cryptojs');
+     */
+    this.setAlgAndProvider = function(alg, prov) {
+	if (alg != null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
+
+	// for cryptojs
+	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(alg) != -1 &&
+	    prov == 'cryptojs') {
+	    try {
+		this.md = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[alg]).create();
+	    } catch (ex) {
+		throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
+	    }
+	    this.updateString = function(str) {
+		this.md.update(str);
+	    };
+	    this.updateHex = function(hex) {
+		var wHex = CryptoJS.enc.Hex.parse(hex);
+		this.md.update(wHex);
+	    };
+	    this.digest = function() {
+		var hash = this.md.finalize();
+		return hash.toString(CryptoJS.enc.Hex);
+	    };
+	    this.digestString = function(str) {
+		this.updateString(str);
+		return this.digest();
+	    };
+	    this.digestHex = function(hex) {
+		this.updateHex(hex);
+		return this.digest();
+	    };
+	}
+	if (':sha256:'.indexOf(alg) != -1 &&
+	    prov == 'sjcl') {
+	    try {
+		this.md = new sjcl.hash.sha256();
+	    } catch (ex) {
+		throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
+	    }
+	    this.updateString = function(str) {
+		this.md.update(str);
+	    };
+	    this.updateHex = function(hex) {
+		var baHex = sjcl.codec.hex.toBits(hex);
+		this.md.update(baHex);
+	    };
+	    this.digest = function() {
+		var hash = this.md.finalize();
+		return sjcl.codec.hex.fromBits(hash);
+	    };
+	    this.digestString = function(str) {
+		this.updateString(str);
+		return this.digest();
+	    };
+	    this.digestHex = function(hex) {
+		this.updateHex(hex);
+		return this.digest();
+	    };
+	}
+    };
+
+    /**
+     * update digest by specified string
+     * @name updateString
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} str string to update
+     * @description
+     * @example
+     * md.updateString('New York');
+     */
+    this.updateString = function(str) {
+	throw "updateString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    /**
+     * update digest by specified hexadecimal string
+     * @name updateHex
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} hex hexadecimal string to update
+     * @description
+     * @example
+     * md.updateHex('0afe36');
+     */
+    this.updateHex = function(hex) {
+	throw "updateHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    /**
+     * completes hash calculation and returns hash result
+     * @name digest
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @description
+     * @example
+     * md.digest()
+     */
+    this.digest = function() {
+	throw "digest() not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    /**
+     * performs final update on the digest using string, then completes the digest computation
+     * @name digestString
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} str string to final update
+     * @description
+     * @example
+     * md.digestString('aaa')
+     */
+    this.digestString = function(str) {
+	throw "digestString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    /**
+     * performs final update on the digest using hexadecimal string, then completes the digest computation
+     * @name digestHex
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} hex hexadecimal string to final update
+     * @description
+     * @example
+     * md.digestHex('0f2abd')
+     */
+    this.digestHex = function(hex) {
+	throw "digestHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    if (params !== undefined) {
+	if (params['alg'] !== undefined) {
+	    this.algName = params['alg'];
+	    if (params['prov'] === undefined)
+		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+	    this.setAlgAndProvider(this.algName, this.provName);
+	}
+    }
+};
+
+/**
+ * Mac(Message Authentication Code) class which is very similar to java.security.Mac class 
+ * @name KJUR.crypto.Mac
+ * @class Mac class which is very similar to java.security.Mac class
+ * @param {Array} params parameters for constructor
+ * @description
+ * <br/>
+ * Currently this supports following algorithm and providers combination:
+ * <ul>
+ * <li>hmacmd5 - cryptojs</li>
+ * <li>hmacsha1 - cryptojs</li>
+ * <li>hmacsha224 - cryptojs</li>
+ * <li>hmacsha256 - cryptojs</li>
+ * <li>hmacsha384 - cryptojs</li>
+ * <li>hmacsha512 - cryptojs</li>
+ * </ul>
+ * NOTE: HmacSHA224 and HmacSHA384 issue was fixed since jsrsasign 4.1.4.
+ * Please use 'ext/cryptojs-312-core-fix*.js' instead of 'core.js' of original CryptoJS
+ * to avoid those issue.
+ * <br/>
+ * NOTE2: Hmac signature bug was fixed in jsrsasign 4.9.0 by providing CryptoJS
+ * bug workaround.
+ * <br/>
+ * Please see {@link KJUR.crypto.Mac.setPassword}, how to provide password
+ * in various ways in detail.
+ * @example
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", "pass": "pass"});
+ * mac.updateString('aaa')
+ * var macHex = md.doFinal()
+ *
+ * // other password representation 
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"hex":  "6161"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"utf8": "aa"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"rstr": "\x61\x61"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64":  "Mi02/+...a=="}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64u": "Mi02_-...a"}});
+ */
+KJUR.crypto.Mac = function(params) {
+    var mac = null;
+    var pass = null;
+    var algName = null;
+    var provName = null;
+    var algProv = null;
+
+    this.setAlgAndProvider = function(alg, prov) {
+	alg = alg.toLowerCase();
+
+	if (alg == null) alg = "hmacsha1";
+
+	alg = alg.toLowerCase();
+        if (alg.substr(0, 4) != "hmac") {
+	    throw "setAlgAndProvider unsupported HMAC alg: " + alg;
+	}
+
+	if (prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
+	this.algProv = alg + "/" + prov;
+
+	var hashAlg = alg.substr(4);
+
+	// for cryptojs
+	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(hashAlg) != -1 &&
+	    prov == 'cryptojs') {
+	    try {
+		var mdObj = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[hashAlg]);
+		this.mac = CryptoJS.algo.HMAC.create(mdObj, this.pass);
+	    } catch (ex) {
+		throw "setAlgAndProvider hash alg set fail hashAlg=" + hashAlg + "/" + ex;
+	    }
+	    this.updateString = function(str) {
+		this.mac.update(str);
+	    };
+	    this.updateHex = function(hex) {
+		var wHex = CryptoJS.enc.Hex.parse(hex);
+		this.mac.update(wHex);
+	    };
+	    this.doFinal = function() {
+		var hash = this.mac.finalize();
+		return hash.toString(CryptoJS.enc.Hex);
+	    };
+	    this.doFinalString = function(str) {
+		this.updateString(str);
+		return this.doFinal();
+	    };
+	    this.doFinalHex = function(hex) {
+		this.updateHex(hex);
+		return this.doFinal();
+	    };
+	}
+    };
+
+    /**
+     * update digest by specified string
+     * @name updateString
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {String} str string to update
+     * @description
+     * @example
+     * md.updateString('New York');
+     */
+    this.updateString = function(str) {
+	throw "updateString(str) not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * update digest by specified hexadecimal string
+     * @name updateHex
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {String} hex hexadecimal string to update
+     * @description
+     * @example
+     * md.updateHex('0afe36');
+     */
+    this.updateHex = function(hex) {
+	throw "updateHex(hex) not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * completes hash calculation and returns hash result
+     * @name doFinal
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @description
+     * @example
+     * md.digest()
+     */
+    this.doFinal = function() {
+	throw "digest() not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * performs final update on the digest using string, then completes the digest computation
+     * @name doFinalString
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {String} str string to final update
+     * @description
+     * @example
+     * md.digestString('aaa')
+     */
+    this.doFinalString = function(str) {
+	throw "digestString(str) not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * performs final update on the digest using hexadecimal string, 
+     * then completes the digest computation
+     * @name doFinalHex
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {String} hex hexadecimal string to final update
+     * @description
+     * @example
+     * md.digestHex('0f2abd')
+     */
+    this.doFinalHex = function(hex) {
+	throw "digestHex(hex) not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * set password for Mac
+     * @name setPassword
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {Object} pass password for Mac
+     * @since crypto 1.1.7 jsrsasign 4.9.0
+     * @description
+     * This method will set password for (H)Mac internally.
+     * Argument 'pass' can be specified as following:
+     * <ul>
+     * <li>even length string of 0..9, a..f or A-F: implicitly specified as hexadecimal string</li>
+     * <li>not above string: implicitly specified as raw string</li>
+     * <li>{rstr: "\x65\x70"}: explicitly specified as raw string</li>
+     * <li>{hex: "6570"}: explicitly specified as hexacedimal string</li>
+     * <li>{utf8: "秘密"}: explicitly specified as UTF8 string</li>
+     * <li>{b64: "Mi78..=="}: explicitly specified as Base64 string</li>
+     * <li>{b64u: "Mi7-_"}: explicitly specified as Base64URL string</li>
+     * </ul>
+     * It is *STRONGLY RECOMMENDED* that explicit representation of password argument
+     * to avoid ambiguity. For example string  "6161" can mean a string "6161" or 
+     * a hexadecimal string of "aa" (i.e. \x61\x61).
+     * @example
+     * mac = KJUR.crypto.Mac({'alg': 'hmacsha256'});
+     * // set password by implicit raw string
+     * mac.setPassword("\x65\x70\xb9\x0b");
+     * mac.setPassword("password");
+     * // set password by implicit hexadecimal string
+     * mac.setPassword("6570b90b");
+     * mac.setPassword("6570B90B");
+     * // set password by explicit raw string
+     * mac.setPassword({"rstr": "\x65\x70\xb9\x0b"});
+     * // set password by explicit hexadecimal string
+     * mac.setPassword({"hex": "6570b90b"});
+     * // set password by explicit utf8 string
+     * mac.setPassword({"utf8": "passwordパスワード");
+     * // set password by explicit Base64 string
+     * mac.setPassword({"b64": "Mb+c3f/=="});
+     * // set password by explicit Base64URL string
+     * mac.setPassword({"b64u": "Mb-c3f_"});
+     */
+    this.setPassword = function(pass) {
+	// internal this.pass shall be CryptoJS DWord Object for CryptoJS bug
+	// work around. CrytoJS HMac password can be passed by
+	// raw string as described in the manual however it doesn't
+	// work properly in some case. If password was passed
+	// by CryptoJS DWord which is not described in the manual
+	// it seems to work. (fixed since crypto 1.1.7)
+
+	if (typeof pass == 'string') {
+	    var hPass = pass;
+	    if (pass.length % 2 == 1 || ! pass.match(/^[0-9A-Fa-f]+$/)) { // raw str
+		hPass = rstrtohex(pass);
+	    }
+	    this.pass = CryptoJS.enc.Hex.parse(hPass);
+	    return;
+	}
+
+	if (typeof pass != 'object')
+	    throw "KJUR.crypto.Mac unsupported password type: " + pass;
+	
+	var hPass = null;
+	if (pass.hex  !== undefined) {
+	    if (pass.hex.length % 2 != 0 || ! pass.hex.match(/^[0-9A-Fa-f]+$/))
+		throw "Mac: wrong hex password: " + pass.hex;
+	    hPass = pass.hex;
+	}
+	if (pass.utf8 !== undefined) hPass = utf8tohex(pass.utf8);
+	if (pass.rstr !== undefined) hPass = rstrtohex(pass.rstr);
+	if (pass.b64  !== undefined) hPass = b64tohex(pass.b64);
+	if (pass.b64u !== undefined) hPass = b64utohex(pass.b64u);
+
+	if (hPass == null)
+	    throw "KJUR.crypto.Mac unsupported password type: " + pass;
+
+	this.pass = CryptoJS.enc.Hex.parse(hPass);
+    };
+
+    if (params !== undefined) {
+	if (params.pass !== undefined) {
+	    this.setPassword(params.pass);
+	}
+	if (params.alg !== undefined) {
+	    this.algName = params.alg;
+	    if (params['prov'] === undefined)
+		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+	    this.setAlgAndProvider(this.algName, this.provName);
+	}
+    }
+};
+
+/**
+ * Signature class which is very similar to java.security.Signature class
+ * @name KJUR.crypto.Signature
+ * @class Signature class which is very similar to java.security.Signature class
+ * @param {Array} params parameters for constructor
+ * @property {String} state Current state of this signature object whether 'SIGN', 'VERIFY' or null
+ * @description
+ * <br/>
+ * As for params of constructor's argument, it can be specify following attributes:
+ * <ul>
+ * <li>alg - signature algorithm name (ex. {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}with{RSA,ECDSA,DSA})</li>
+ * <li>provider - currently 'cryptojs/jsrsa' only</li>
+ * </ul>
+ * <h4>SUPPORTED ALGORITHMS AND PROVIDERS</h4>
+ * This Signature class supports following signature algorithm and provider names:
+ * <ul>
+ * <li>MD5withRSA - cryptojs/jsrsa</li>
+ * <li>SHA1withRSA - cryptojs/jsrsa</li>
+ * <li>SHA224withRSA - cryptojs/jsrsa</li>
+ * <li>SHA256withRSA - cryptojs/jsrsa</li>
+ * <li>SHA384withRSA - cryptojs/jsrsa</li>
+ * <li>SHA512withRSA - cryptojs/jsrsa</li>
+ * <li>RIPEMD160withRSA - cryptojs/jsrsa</li>
+ * <li>MD5withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA1withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA224withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA256withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA384withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA512withECDSA - cryptojs/jsrsa</li>
+ * <li>RIPEMD160withECDSA - cryptojs/jsrsa</li>
+ * <li>MD5withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA1withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA224withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA256withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA384withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA512withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>RIPEMD160withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA1withDSA - cryptojs/jsrsa</li>
+ * <li>SHA224withDSA - cryptojs/jsrsa</li>
+ * <li>SHA256withDSA - cryptojs/jsrsa</li>
+ * </ul>
+ * Here are supported elliptic cryptographic curve names and their aliases for ECDSA:
+ * <ul>
+ * <li>secp256k1</li>
+ * <li>secp256r1, NIST P-256, P-256, prime256v1</li>
+ * <li>secp384r1, NIST P-384, P-384</li>
+ * </ul>
+ * NOTE1: DSA signing algorithm is also supported since crypto 1.1.5.
+ * <h4>EXAMPLES</h4>
+ * @example
+ * // RSA signature generation
+ * var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
+ * sig.init(prvKeyPEM);
+ * sig.updateString('aaa');
+ * var hSigVal = sig.sign();
+ *
+ * // DSA signature validation
+ * var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withDSA"});
+ * sig2.init(certPEM);
+ * sig.updateString('aaa');
+ * var isValid = sig2.verify(hSigVal);
+ * 
+ * // ECDSA signing
+ * var sig = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
+ * sig.init(prvKeyPEM);
+ * sig.updateString('aaa');
+ * var sigValueHex = sig.sign();
+ *
+ * // ECDSA verifying
+ * var sig2 = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
+ * sig.init(certPEM);
+ * sig.updateString('aaa');
+ * var isValid = sig.verify(sigValueHex);
+ */
+KJUR.crypto.Signature = function(params) {
+    var prvKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for signing
+    var pubKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for verifying
+
+    var md = null; // KJUR.crypto.MessageDigest object
+    var sig = null;
+    var algName = null;
+    var provName = null;
+    var algProvName = null;
+    var mdAlgName = null;
+    var pubkeyAlgName = null;	// rsa,ecdsa,rsaandmgf1(=rsapss)
+    var state = null;
+    var pssSaltLen = -1;
+    var initParams = null;
+
+    var sHashHex = null; // hex hash value for hex
+    var hDigestInfo = null;
+    var hPaddedDigestInfo = null;
+    var hSign = null;
+
+    this._setAlgNames = function() {
+	if (this.algName.match(/^(.+)with(.+)$/)) {
+	    this.mdAlgName = RegExp.$1.toLowerCase();
+	    this.pubkeyAlgName = RegExp.$2.toLowerCase();
+	}
+    };
+
+    this._zeroPaddingOfSignature = function(hex, bitLength) {
+	var s = "";
+	var nZero = bitLength / 4 - hex.length;
+	for (var i = 0; i < nZero; i++) {
+	    s = s + "0";
+	}
+	return s + hex;
+    };
+
+    /**
+     * set signature algorithm and provider
+     * @name setAlgAndProvider
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} alg signature algorithm name
+     * @param {String} prov provider name
+     * @description
+     * @example
+     * md.setAlgAndProvider('SHA1withRSA', 'cryptojs/jsrsa');
+     */
+    this.setAlgAndProvider = function(alg, prov) {
+	this._setAlgNames();
+	if (prov != 'cryptojs/jsrsa')
+	    throw "provider not supported: " + prov;
+
+	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(this.mdAlgName) != -1) {
+	    try {
+		this.md = new KJUR.crypto.MessageDigest({'alg':this.mdAlgName});
+	    } catch (ex) {
+		throw "setAlgAndProvider hash alg set fail alg=" +
+                      this.mdAlgName + "/" + ex;
+	    }
+
+	    this.init = function(keyparam, pass) {
+		var keyObj = null;
+		try {
+		    if (pass === undefined) {
+			keyObj = KEYUTIL.getKey(keyparam);
+		    } else {
+			keyObj = KEYUTIL.getKey(keyparam, pass);
+		    }
+		} catch (ex) {
+		    throw "init failed:" + ex;
+		}
+
+		if (keyObj.isPrivate === true) {
+		    this.prvKey = keyObj;
+		    this.state = "SIGN";
+		} else if (keyObj.isPublic === true) {
+		    this.pubKey = keyObj;
+		    this.state = "VERIFY";
+		} else {
+		    throw "init failed.:" + keyObj;
+		}
+	    };
+
+	    this.initSign = function(params) {
+		if (typeof params['ecprvhex'] == 'string' &&
+                    typeof params['eccurvename'] == 'string') {
+		    this.ecprvhex = params['ecprvhex'];
+		    this.eccurvename = params['eccurvename'];
+		} else {
+		    this.prvKey = params;
+		}
+		this.state = "SIGN";
+	    };
+
+	    this.initVerifyByPublicKey = function(params) {
+		if (typeof params['ecpubhex'] == 'string' &&
+		    typeof params['eccurvename'] == 'string') {
+		    this.ecpubhex = params['ecpubhex'];
+		    this.eccurvename = params['eccurvename'];
+		} else if (params instanceof KJUR.crypto.ECDSA) {
+		    this.pubKey = params;
+		} else if (params instanceof RSAKey) {
+		    this.pubKey = params;
+		}
+		this.state = "VERIFY";
+	    };
+
+	    this.initVerifyByCertificatePEM = function(certPEM) {
+		var x509 = new X509();
+		x509.readCertPEM(certPEM);
+		this.pubKey = x509.subjectPublicKeyRSA;
+		this.state = "VERIFY";
+	    };
+
+	    this.updateString = function(str) {
+		this.md.updateString(str);
+	    };
+
+	    this.updateHex = function(hex) {
+		this.md.updateHex(hex);
+	    };
+
+	    this.sign = function() {
+		this.sHashHex = this.md.digest();
+		if (typeof this.ecprvhex != "undefined" &&
+		    typeof this.eccurvename != "undefined") {
+		    var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename});
+		    this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
+		} else if (this.prvKey instanceof RSAKey &&
+		           this.pubkeyAlgName == "rsaandmgf1") {
+		    this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex,
+								    this.mdAlgName,
+								    this.pssSaltLen);
+		} else if (this.prvKey instanceof RSAKey &&
+			   this.pubkeyAlgName == "rsa") {
+		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex,
+								 this.mdAlgName);
+		} else if (this.prvKey instanceof KJUR.crypto.ECDSA) {
+		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
+		} else if (this.prvKey instanceof KJUR.crypto.DSA) {
+		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
+		} else {
+		    throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
+		}
+		return this.hSign;
+	    };
+	    this.signString = function(str) {
+		this.updateString(str);
+		return this.sign();
+	    };
+	    this.signHex = function(hex) {
+		this.updateHex(hex);
+		return this.sign();
+	    };
+	    this.verify = function(hSigVal) {
+	        this.sHashHex = this.md.digest();
+		if (typeof this.ecpubhex != "undefined" &&
+		    typeof this.eccurvename != "undefined") {
+		    var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename});
+		    return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
+		} else if (this.pubKey instanceof RSAKey &&
+			   this.pubkeyAlgName == "rsaandmgf1") {
+		    return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal, 
+								this.mdAlgName,
+								this.pssSaltLen);
+		} else if (this.pubKey instanceof RSAKey &&
+			   this.pubkeyAlgName == "rsa") {
+		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+		} else if (this.pubKey instanceof KJUR.crypto.ECDSA) {
+		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+		} else if (this.pubKey instanceof KJUR.crypto.DSA) {
+		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+		} else {
+		    throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
+		}
+	    };
+	}
+    };
+
+    /**
+     * Initialize this object for signing or verifying depends on key
+     * @name init
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {Object} key specifying public or private key as plain/encrypted PKCS#5/8 PEM file, certificate PEM or {@link RSAKey}, {@link KJUR.crypto.DSA} or {@link KJUR.crypto.ECDSA} object
+     * @param {String} pass (OPTION) passcode for encrypted private key
+     * @since crypto 1.1.3
+     * @description
+     * This method is very useful initialize method for Signature class since
+     * you just specify key then this method will automatically initialize it
+     * using {@link KEYUTIL.getKey} method.
+     * As for 'key',  following argument type are supported:
+     * <h5>signing</h5>
+     * <ul>
+     * <li>PEM formatted PKCS#8 encrypted RSA/ECDSA private key concluding "BEGIN ENCRYPTED PRIVATE KEY"</li>
+     * <li>PEM formatted PKCS#5 encrypted RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" and ",ENCRYPTED"</li>
+     * <li>PEM formatted PKCS#8 plain RSA/ECDSA private key concluding "BEGIN PRIVATE KEY"</li>
+     * <li>PEM formatted PKCS#5 plain RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" without ",ENCRYPTED"</li>
+     * <li>RSAKey object of private key</li>
+     * <li>KJUR.crypto.ECDSA object of private key</li>
+     * <li>KJUR.crypto.DSA object of private key</li>
+     * </ul>
+     * <h5>verification</h5>
+     * <ul>
+     * <li>PEM formatted PKCS#8 RSA/EC/DSA public key concluding "BEGIN PUBLIC KEY"</li>
+     * <li>PEM formatted X.509 certificate with RSA/EC/DSA public key concluding
+     *     "BEGIN CERTIFICATE", "BEGIN X509 CERTIFICATE" or "BEGIN TRUSTED CERTIFICATE".</li>
+     * <li>RSAKey object of public key</li>
+     * <li>KJUR.crypto.ECDSA object of public key</li>
+     * <li>KJUR.crypto.DSA object of public key</li>
+     * </ul>
+     * @example
+     * sig.init(sCertPEM)
+     */
+    this.init = function(key, pass) {
+	throw "init(key, pass) not supported for this alg:prov=" +
+	      this.algProvName;
+    };
+
+    /**
+     * Initialize this object for verifying with a public key
+     * @name initVerifyByPublicKey
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {Object} param RSAKey object of public key or associative array for ECDSA
+     * @since 1.0.2
+     * @deprecated from crypto 1.1.5. please use init() method instead.
+     * @description
+     * Public key information will be provided as 'param' parameter and the value will be
+     * following:
+     * <ul>
+     * <li>{@link RSAKey} object for RSA verification</li>
+     * <li>associative array for ECDSA verification
+     *     (ex. <code>{'ecpubhex': '041f..', 'eccurvename': 'secp256r1'}</code>)
+     * </li>
+     * </ul>
+     * @example
+     * sig.initVerifyByPublicKey(rsaPrvKey)
+     */
+    this.initVerifyByPublicKey = function(rsaPubKey) {
+	throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" +
+	      this.algProvName;
+    };
+
+    /**
+     * Initialize this object for verifying with a certficate
+     * @name initVerifyByCertificatePEM
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} certPEM PEM formatted string of certificate
+     * @since 1.0.2
+     * @deprecated from crypto 1.1.5. please use init() method instead.
+     * @description
+     * @example
+     * sig.initVerifyByCertificatePEM(certPEM)
+     */
+    this.initVerifyByCertificatePEM = function(certPEM) {
+	throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" +
+	    this.algProvName;
+    };
+
+    /**
+     * Initialize this object for signing
+     * @name initSign
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {Object} param RSAKey object of public key or associative array for ECDSA
+     * @deprecated from crypto 1.1.5. please use init() method instead.
+     * @description
+     * Private key information will be provided as 'param' parameter and the value will be
+     * following:
+     * <ul>
+     * <li>{@link RSAKey} object for RSA signing</li>
+     * <li>associative array for ECDSA signing
+     *     (ex. <code>{'ecprvhex': '1d3f..', 'eccurvename': 'secp256r1'}</code>)</li>
+     * </ul>
+     * @example
+     * sig.initSign(prvKey)
+     */
+    this.initSign = function(prvKey) {
+	throw "initSign(prvKey) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * Updates the data to be signed or verified by a string
+     * @name updateString
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} str string to use for the update
+     * @description
+     * @example
+     * sig.updateString('aaa')
+     */
+    this.updateString = function(str) {
+	throw "updateString(str) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * Updates the data to be signed or verified by a hexadecimal string
+     * @name updateHex
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} hex hexadecimal string to use for the update
+     * @description
+     * @example
+     * sig.updateHex('1f2f3f')
+     */
+    this.updateHex = function(hex) {
+	throw "updateHex(hex) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * Returns the signature bytes of all data updates as a hexadecimal string
+     * @name sign
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @return the signature bytes as a hexadecimal string
+     * @description
+     * @example
+     * var hSigValue = sig.sign()
+     */
+    this.sign = function() {
+	throw "sign() not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * performs final update on the sign using string, then returns the signature bytes of all data updates as a hexadecimal string
+     * @name signString
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} str string to final update
+     * @return the signature bytes of a hexadecimal string
+     * @description
+     * @example
+     * var hSigValue = sig.signString('aaa')
+     */
+    this.signString = function(str) {
+	throw "digestString(str) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * performs final update on the sign using hexadecimal string, then returns the signature bytes of all data updates as a hexadecimal string
+     * @name signHex
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} hex hexadecimal string to final update
+     * @return the signature bytes of a hexadecimal string
+     * @description
+     * @example
+     * var hSigValue = sig.signHex('1fdc33')
+     */
+    this.signHex = function(hex) {
+	throw "digestHex(hex) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * verifies the passed-in signature.
+     * @name verify
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} str string to final update
+     * @return {Boolean} true if the signature was verified, otherwise false
+     * @description
+     * @example
+     * var isValid = sig.verify('1fbcefdca4823a7(snip)')
+     */
+    this.verify = function(hSigVal) {
+	throw "verify(hSigVal) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    this.initParams = params;
+
+    if (params !== undefined) {
+	if (params['alg'] !== undefined) {
+	    this.algName = params['alg'];
+	    if (params['prov'] === undefined) {
+		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+	    } else {
+		this.provName = params['prov'];
+	    }
+	    this.algProvName = this.algName + ":" + this.provName;
+	    this.setAlgAndProvider(this.algName, this.provName);
+	    this._setAlgNames();
+	}
+
+	if (params['psssaltlen'] !== undefined) this.pssSaltLen = params['psssaltlen'];
+
+	if (params['prvkeypem'] !== undefined) {
+	    if (params['prvkeypas'] !== undefined) {
+		throw "both prvkeypem and prvkeypas parameters not supported";
+	    } else {
+		try {
+		    var prvKey = new RSAKey();
+		    prvKey.readPrivateKeyFromPEMString(params['prvkeypem']);
+		    this.initSign(prvKey);
+		} catch (ex) {
+		    throw "fatal error to load pem private key: " + ex;
+		}
+	    }
+	}
+    }
+};
+
+/**
+ * static object for cryptographic function utilities
+ * @name KJUR.crypto.OID
+ * @class static object for cryptography related OIDs
+ * @property {Array} oidhex2name key value of hexadecimal OID and its name
+ *           (ex. '2a8648ce3d030107' and 'secp256r1')
+ * @since crypto 1.1.3
+ * @description
+ */
+
+
+KJUR.crypto.OID = new function() {
+    this.oidhex2name = {
+	'2a864886f70d010101': 'rsaEncryption',
+	'2a8648ce3d0201': 'ecPublicKey',
+	'2a8648ce380401': 'dsa',
+	'2a8648ce3d030107': 'secp256r1',
+	'2b8104001f': 'secp192k1',
+	'2b81040021': 'secp224r1',
+	'2b8104000a': 'secp256k1',
+	'2b81040023': 'secp521r1',
+	'2b81040022': 'secp384r1',
+	'2a8648ce380403': 'SHA1withDSA', // 1.2.840.10040.4.3
+	'608648016503040301': 'SHA224withDSA', // 2.16.840.1.101.3.4.3.1
+	'608648016503040302': 'SHA256withDSA'  // 2.16.840.1.101.3.4.3.2
+    };
+};
+
+exports.KJUR = KJUR;
+module.exports = exports;
 /*! rsapem-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
  */
 //
 // rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
 //              to RSAKey class.
 //
-// version: 1.1 (2012-May-10)
+// version: 1.1.1 (2013-Apr-12)
 //
-// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
+// Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
 //
 // This software is licensed under the terms of the MIT License.
 // http://kjur.github.com/jsrsasign/license/
@@ -5381,6 +3582,18 @@
 //   new lines from PEM formatted RSA private key string.
 //
 
+/**
+ * @fileOverview
+ * @name rsapem-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version 1.1
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ */
+
+var ASN1HEX = require('./asn1hex-1.1.js').ASN1HEX;
+var b64tohex = require('./base64.js').b64tohex;
+var RSAKey = require('./rsa2.js').RSAKey;
+
 function _rsapem_pemToBase64(sPEMPrivateKey) {
   var s = sPEMPrivateKey;
   s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
@@ -5421,6 +3634,19 @@
 }
 
 /**
+ * read RSA private key from a ASN.1 hexadecimal string
+ * @name readPrivateKeyFromASN1HexString
+ * @memberOf RSAKey#
+ * @function
+ * @param {String} keyHex ASN.1 hexadecimal string of PKCS#1 private key.
+ * @since 1.1.1
+ */
+function _rsapem_readPrivateKeyFromASN1HexString(keyHex) {
+  var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
+  this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
+}
+
+/**
  * read PKCS#1 private key from a string
  * @name readPrivateKeyFromPEMString
  * @memberOf RSAKey#
@@ -5435,70 +3661,37 @@
 }
 
 RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
-/*! rsasign-1.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
+RSAKey.prototype.readPrivateKeyFromASN1HexString = _rsapem_readPrivateKeyFromASN1HexString;
+
+exports.RSAKey = RSAKey;
+module.exports = exports;
+/*! rsasign-1.2.7.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
  */
-//
-// rsa-sign.js - adding signing functions to RSAKey class.
-//
-//
-// version: 1.2.1 (08 May 2012)
-//
-// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
-//
-// This software is licensed under the terms of the MIT License.
-// http://kjur.github.com/jsrsasign/license/
-//
-// The above copyright and license notice shall be 
-// included in all copies or substantial portions of the Software.
-
-//
-// Depends on:
-//   function sha1.hex(s) of sha1.js
-//   jsbn.js
-//   jsbn2.js
-//   rsa.js
-//   rsa2.js
-//
-
-// keysize / pmstrlen
-//  512 /  128
-// 1024 /  256
-// 2048 /  512
-// 4096 / 1024
+/*
+ * rsa-sign.js - adding signing functions to RSAKey class.
+ *
+ * version: 1.2.7 (2013 Aug 25)
+ *
+ * Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license/
+ *
+ * The above copyright and license notice shall be 
+ * included in all copies or substantial portions of the Software.
+ */
 
 /**
- * @property {Dictionary} _RSASIGN_DIHEAD
- * @description Array of head part of hexadecimal DigestInfo value for hash algorithms.
- * You can add any DigestInfo hash algorith for signing.
- * See PKCS#1 v2.1 spec (p38).
+ * @fileOverview
+ * @name rsasign-1.2.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version rsasign 1.2.7
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
  */
-var _RSASIGN_DIHEAD = [];
-_RSASIGN_DIHEAD['sha1'] =      "3021300906052b0e03021a05000414";
-_RSASIGN_DIHEAD['sha256'] =    "3031300d060960864801650304020105000420";
-_RSASIGN_DIHEAD['sha384'] =    "3041300d060960864801650304020205000430";
-_RSASIGN_DIHEAD['sha512'] =    "3051300d060960864801650304020305000440";
-_RSASIGN_DIHEAD['md2'] =       "3020300c06082a864886f70d020205000410";
-_RSASIGN_DIHEAD['md5'] =       "3020300c06082a864886f70d020505000410";
-_RSASIGN_DIHEAD['ripemd160'] = "3021300906052b2403020105000414";
 
-/**
- * @property {Dictionary} _RSASIGN_HASHHEXFUNC
- * @description Array of functions which calculate hash and returns it as hexadecimal.
- * You can add any hash algorithm implementations.
- */
-var _RSASIGN_HASHHEXFUNC = [];
-_RSASIGN_HASHHEXFUNC['sha1'] =      function(s){return hex_sha1(s);};  // http://pajhome.org.uk/crypt/md5/md5.html
-_RSASIGN_HASHHEXFUNC['sha256'] =    function(s){return hex_sha256(s);} // http://pajhome.org.uk/crypt/md5/md5.html
-_RSASIGN_HASHHEXFUNC['sha512'] =    function(s){return hex_sha512(s);} // http://pajhome.org.uk/crypt/md5/md5.html
-_RSASIGN_HASHHEXFUNC['md5'] =       function(s){return hex_md5(s);};   // http://pajhome.org.uk/crypt/md5/md5.html
-_RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return hex_rmd160(s);};   // http://pajhome.org.uk/crypt/md5/md5.html
-
-//@author axelcdv
-var _RSASIGN_HASHBYTEFUNC = [];
-_RSASIGN_HASHBYTEFUNC['sha256'] = 	function(byteArray){return hex_sha256_from_bytes(byteArray);};
-
-//_RSASIGN_HASHHEXFUNC['sha1'] =   function(s){return sha1.hex(s);}   // http://user1.matsumoto.ne.jp/~goma/js/hash.html
-//_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;}    // http://user1.matsumoto.ne.jp/~goma/js/hash.html
+var intShim = require('jsbn');
+var BigInteger = intShim.BigInteger ? intShim.BigInteger : intShim;
+var RSAKey = require('./rsapem-1.1.js').RSAKey
 
 var _RE_HEXDECONLY = new RegExp("");
 _RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
@@ -5508,134 +3701,176 @@
 // ========================================================================
 
 function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
-  var pmStrLen = keySize / 4;
-  var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
-  var sHashHex = hashFunc(s);
+    var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
+    var sHashHex = hashFunc(s);
 
-  var sHead = "0001";
-  var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
-  var sMid = "";
-  var fLen = pmStrLen - sHead.length - sTail.length;
-  for (var i = 0; i < fLen; i += 2) {
-    sMid += "ff";
-  }
-  sPaddedMessageHex = sHead + sMid + sTail;
-  return sPaddedMessageHex;
-}
-
-
-//@author: Meki Cheraoui
-function _rsasign_getHexPaddedDigestInfoForStringHEX(s, keySize, hashAlg) {
-  var pmStrLen = keySize / 4;
-  var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
-  var sHashHex = hashFunc(s);
-
-  var sHead = "0001";
-  var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
-  var sMid = "";
-  var fLen = pmStrLen - sHead.length - sTail.length;
-  for (var i = 0; i < fLen; i += 2) {
-    sMid += "ff";
-  }
-  sPaddedMessageHex = sHead + sMid + sTail;
-  return sPaddedMessageHex;
-}
-
-/**
- * Apply padding, then computes the hash of the given byte array, according to the key size and with the hash algorithm
- * @param byteArray (byte[])
- * @param keySize (int)
- * @param hashAlg the hash algorithm to apply (string)
- * @return the hash of byteArray
- */
-function _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, keySize, hashAlg){
-	var pmStrLen = keySize / 4;
-	var hashFunc = _RSASIGN_HASHBYTEFUNC[hashAlg];
-	var sHashHex = hashFunc(byteArray); //returns hex hash
-	
-	var sHead = "0001";
-	  var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
-	  var sMid = "";
-	  var fLen = pmStrLen - sHead.length - sTail.length;
-	  for (var i = 0; i < fLen; i += 2) {
-	    sMid += "ff";
-	  }
-	  sPaddedMessageHex = sHead + sMid + sTail;
-	  return sPaddedMessageHex;
+    return KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, keySize);
 }
 
 function _zeroPaddingOfSignature(hex, bitLength) {
-  var s = "";
-  var nZero = bitLength / 4 - hex.length;
-  for (var i = 0; i < nZero; i++) {
-    s = s + "0";
-  }
-  return s + hex;
+    var s = "";
+    var nZero = bitLength / 4 - hex.length;
+    for (var i = 0; i < nZero; i++) {
+	s = s + "0";
+    }
+    return s + hex;
 }
 
 /**
  * sign for a message string with RSA private key.<br/>
  * @name signString
- * @memberOf RSAKey#
+ * @memberOf RSAKey
  * @function
  * @param {String} s message string to be signed.
  * @param {String} hashAlg hash algorithm name for signing.<br/>
  * @return returns hexadecimal string of signature value.
  */
 function _rsasign_signString(s, hashAlg) {
-  //alert("this.n.bitLength() = " + this.n.bitLength());
-  var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
-  var biPaddedMessage = parseBigInt(hPM, 16);
-  var biSign = this.doPrivate(biPaddedMessage);
-  var hexSign = biSign.toString(16);
-  return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
-}
+    var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
+    var sHashHex = hashFunc(s);
 
-//@author: ucla-cs
-function _rsasign_signStringHEX(s, hashAlg) {
-  //alert("this.n.bitLength() = " + this.n.bitLength());
-  var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
-  var biPaddedMessage = parseBigInt(hPM, 16);
-  var biSign = this.doPrivate(biPaddedMessage);
-  var hexSign = biSign.toString(16);
-  return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
+    return this.signWithMessageHash(sHashHex, hashAlg);
 }
 
-
 /**
- * Sign a message byteArray with an RSA private key
- * @name signByteArray
- * @memberOf RSAKey#
+ * sign hash value of message to be signed with RSA private key.<br/>
+ * @name signWithMessageHash
+ * @memberOf RSAKey
  * @function
- * @param {byte[]} byteArray
- * @param {Sring} hashAlg the hash algorithm to apply
- * @param {RSAKey} rsa key to sign with: hack because the context is lost here
- * @return hexadecimal string of signature value
+ * @param {String} sHashHex hexadecimal string of hash value of message to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.<br/>
+ * @return returns hexadecimal string of signature value.
+ * @since rsasign 1.2.6
  */
-function _rsasign_signByteArray(byteArray, hashAlg, rsaKey) {
-	var hPM = _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, rsaKey.n.bitLength(), hashAlg); ///hack because the context is lost here
-	var biPaddedMessage = parseBigInt(hPM, 16);
-	var biSign = rsaKey.doPrivate(biPaddedMessage); //hack because the context is lost here
-	var hexSign = biSign.toString(16);
-	return _zeroPaddingOfSignature(hexSign, rsaKey.n.bitLength()); //hack because the context is lost here
+function _rsasign_signWithMessageHash(sHashHex, hashAlg) {
+    var hPM = KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, this.n.bitLength());
+    var biPaddedMessage = parseBigInt(hPM, 16);
+    var biSign = this.doPrivate(biPaddedMessage);
+    var hexSign = biSign.toString(16);
+    return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
 }
 
-/**
- * Sign a byte array with the Sha-256 algorithm
- * @param {byte[]} byteArray
- * @return hexadecimal string of signature value
- */
-function _rsasign_signByteArrayWithSHA256(byteArray){
-	return _rsasign_signByteArray(byteArray, 'sha256', this); //Hack because the context is lost in the next function
-}
-
-
 function _rsasign_signStringWithSHA1(s) {
-  return _rsasign_signString(s, 'sha1');
+    return _rsasign_signString.call(this, s, 'sha1');
 }
 
 function _rsasign_signStringWithSHA256(s) {
-  return _rsasign_signString(s, 'sha256');
+    return _rsasign_signString.call(this, s, 'sha256');
+}
+
+// PKCS#1 (PSS) mask generation function
+function pss_mgf1_str(seed, len, hash) {
+    var mask = '', i = 0;
+
+    while (mask.length < len) {
+        mask += hextorstr(hash(rstrtohex(seed + String.fromCharCode.apply(String, [
+                (i & 0xff000000) >> 24,
+                (i & 0x00ff0000) >> 16,
+                (i & 0x0000ff00) >> 8,
+                i & 0x000000ff]))));
+        i += 1;
+    }
+
+    return mask;
+}
+
+/**
+ * sign for a message string with RSA private key by PKCS#1 PSS signing.<br/>
+ * @name signStringPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} s message string to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ *        There are two special values:
+ *        <ul>
+ *        <li>-1: sets the salt length to the digest length</li>
+ *        <li>-2: sets the salt length to maximum permissible value
+ *           (i.e. keybytelen - hashbytelen - 2)</li>
+ *        </ul>
+ *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns hexadecimal string of signature value.
+ */
+function _rsasign_signStringPSS(s, hashAlg, sLen) {
+    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); } 
+    var hHash = hashFunc(rstrtohex(s));
+
+    if (sLen === undefined) sLen = -1;
+    return this.signWithMessageHashPSS(hHash, hashAlg, sLen);
+}
+
+/**
+ * sign hash value of message with RSA private key by PKCS#1 PSS signing.<br/>
+ * @name signWithMessageHashPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} hHash hexadecimal hash value of message to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ *        There are two special values:
+ *        <ul>
+ *        <li>-1: sets the salt length to the digest length</li>
+ *        <li>-2: sets the salt length to maximum permissible value
+ *           (i.e. keybytelen - hashbytelen - 2)</li>
+ *        </ul>
+ *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns hexadecimal string of signature value.
+ * @since rsasign 1.2.6
+ */
+function _rsasign_signWithMessageHashPSS(hHash, hashAlg, sLen) {
+    var mHash = hextorstr(hHash);
+    var hLen = mHash.length;
+    var emBits = this.n.bitLength() - 1;
+    var emLen = Math.ceil(emBits / 8);
+    var i;
+    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); } 
+
+    if (sLen === -1 || sLen === undefined) {
+        sLen = hLen; // same as hash length
+    } else if (sLen === -2) {
+        sLen = emLen - hLen - 2; // maximum
+    } else if (sLen < -2) {
+        throw "invalid salt length";
+    }
+
+    if (emLen < (hLen + sLen + 2)) {
+        throw "data too long";
+    }
+
+    var salt = '';
+
+    if (sLen > 0) {
+        salt = new Array(sLen);
+        new SecureRandom().nextBytes(salt);
+        salt = String.fromCharCode.apply(String, salt);
+    }
+
+    var H = hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt)));
+    var PS = [];
+
+    for (i = 0; i < emLen - sLen - hLen - 2; i += 1) {
+        PS[i] = 0x00;
+    }
+
+    var DB = String.fromCharCode.apply(String, PS) + '\x01' + salt;
+    var dbMask = pss_mgf1_str(H, DB.length, hashFunc);
+    var maskedDB = [];
+
+    for (i = 0; i < DB.length; i += 1) {
+        maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+    }
+
+    var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
+    maskedDB[0] &= ~mask;
+
+    for (i = 0; i < hLen; i++) {
+        maskedDB.push(H.charCodeAt(i));
+    }
+
+    maskedDB.push(0xbc);
+
+    return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(maskedDB)).toString(16),
+				   this.n.bitLength());
 }
 
 // ========================================================================
@@ -5643,47 +3878,47 @@
 // ========================================================================
 
 function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
-  var rsa = new RSAKey();
-  rsa.setPublic(hN, hE);
-  var biDecryptedSig = rsa.doPublic(biSig);
-  return biDecryptedSig;
+    var rsa = new RSAKey();
+    rsa.setPublic(hN, hE);
+    var biDecryptedSig = rsa.doPublic(biSig);
+    return biDecryptedSig;
 }
 
 function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
-  var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
-  var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
-  return hDigestInfo;
+    var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
+    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+    return hDigestInfo;
 }
 
 function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
-  for (var algName in _RSASIGN_DIHEAD) {
-    var head = _RSASIGN_DIHEAD[algName];
-    var len = head.length;
-    if (hDigestInfo.substring(0, len) == head) {
-      var a = [algName, hDigestInfo.substring(len)];
-      return a;
+    for (var algName in KJUR.crypto.Util.DIGESTINFOHEAD) {
+	var head = KJUR.crypto.Util.DIGESTINFOHEAD[algName];
+	var len = head.length;
+	if (hDigestInfo.substring(0, len) == head) {
+	    var a = [algName, hDigestInfo.substring(len)];
+	    return a;
+	}
     }
-  }
-  return [];
+    return [];
 }
 
 function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
-  var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
-  var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
-  if (digestInfoAry.length == 0) return false;
-  var algName = digestInfoAry[0];
-  var diHashValue = digestInfoAry[1];
-  var ff = _RSASIGN_HASHHEXFUNC[algName];
-  var msgHashValue = ff(sMsg);
-  return (diHashValue == msgHashValue);
+    var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
+    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
+    if (digestInfoAry.length == 0) return false;
+    var algName = digestInfoAry[0];
+    var diHashValue = digestInfoAry[1];
+    var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
+    var msgHashValue = ff(sMsg);
+    return (diHashValue == msgHashValue);
 }
 
 function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
-  var biSig = parseBigInt(hSig, 16);
-  var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
-						this.n.toString(16),
-						this.e.toString(16));
-  return result;
+    var biSig = parseBigInt(hSig, 16);
+    var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
+						  this.n.toString(16),
+						  this.e.toString(16));
+    return result;
 }
 
 /**
@@ -5697,661 +3932,1410 @@
  * @return returns 1 if valid, otherwise 0
  */
 function _rsasign_verifyString(sMsg, hSig) {
-  hSig = hSig.replace(_RE_HEXDECONLY, '');
+    hSig = hSig.replace(_RE_HEXDECONLY, '');
+    hSig = hSig.replace(/[ \n]+/g, "");
+    var biSig = parseBigInt(hSig, 16);
+    if (biSig.bitLength() > this.n.bitLength()) return 0;
+    var biDecryptedSig = this.doPublic(biSig);
+    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
   
-  if(LOG>3)console.log('n is '+this.n);
-  if(LOG>3)console.log('e is '+this.e);
-  
-  if (hSig.length != this.n.bitLength() / 4) return 0;
-  hSig = hSig.replace(/[ \n]+/g, "");
-  var biSig = parseBigInt(hSig, 16);
-  var biDecryptedSig = this.doPublic(biSig);
-  var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
-  var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
-  
-  if (digestInfoAry.length == 0) return false;
-  var algName = digestInfoAry[0];
-  var diHashValue = digestInfoAry[1];
-  var ff = _RSASIGN_HASHHEXFUNC[algName];
-  var msgHashValue = ff(sMsg);
-  return (diHashValue == msgHashValue);
+    if (digestInfoAry.length == 0) return false;
+    var algName = digestInfoAry[0];
+    var diHashValue = digestInfoAry[1];
+    var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
+    var msgHashValue = ff(sMsg);
+    return (diHashValue == msgHashValue);
 }
 
 /**
- * verifies a sigature for a message byte array with RSA public key.<br/>
- * @name verifyByteArray
- * @memberOf RSAKey#
+ * verifies a sigature for a message string with RSA public key.<br/>
+ * @name verifyWithMessageHash
+ * @memberOf RSAKey
  * @function
- * @param {byte[]} byteArray message byte array to be verified.
- * @param {String} hSig hexadecimal string of signature.<br/>
+ * @param {String} sHashHex hexadecimal hash value of message to be verified.
+ * @param {String} hSig hexadecimal string of siganture.<br/>
  *                 non-hexadecimal charactors including new lines will be ignored.
- * @return returns 1 if valid, otherwise 0 
+ * @return returns 1 if valid, otherwise 0
+ * @since rsasign 1.2.6
  */
-function _rsasign_verifyByteArray(byteArray, witness, hSig) {
-	hSig = hSig.replace(_RE_HEXDECONLY, '');
-	  
-	  if(LOG>3)console.log('n is '+this.n);
-	  if(LOG>3)console.log('e is '+this.e);
-	  
-	  if (hSig.length != this.n.bitLength() / 4) return 0;
-	  hSig = hSig.replace(/[ \n]+/g, "");
-	  var biSig = parseBigInt(hSig, 16);
-	  var biDecryptedSig = this.doPublic(biSig);
-	  var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
-	  var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
-	  
-	  if (digestInfoAry.length == 0) return false;
-	  var algName = digestInfoAry[0];
-	  var diHashValue = digestInfoAry[1];
-	  var msgHashValue = null;
-	  
-	  if (witness == null) {
-	  	var ff = _RSASIGN_HASHBYTEFUNC[algName];
-	  	msgHashValue = ff(byteArray);
-	  } else {
-	  	// Compute merkle hash
-		  var h = hex_sha256_from_bytes(byteArray);
-		  var index = witness.path.index;
-		  for (var i = witness.path.digestList.length - 1; i >= 0; i--) {
-		  	var str = "";
-		  	if (index % 2 == 0) {
-		  		str = h + witness.path.digestList[i];
-		  	} else {
-		  		str = witness.path.digestList[i] + h;
-		  	}
-		  	h = hex_sha256_from_bytes(DataUtils.toNumbers(str));
-		  	index = Math.floor(index / 2);
-		  }
-		  msgHashValue = hex_sha256_from_bytes(DataUtils.toNumbers(h));
-	  }
-	  //console.log(diHashValue);
-	  //console.log(msgHashValue);
-	  return (diHashValue == msgHashValue);
+function _rsasign_verifyWithMessageHash(sHashHex, hSig) {
+    hSig = hSig.replace(_RE_HEXDECONLY, '');
+    hSig = hSig.replace(/[ \n]+/g, "");
+    var biSig = parseBigInt(hSig, 16);
+    if (biSig.bitLength() > this.n.bitLength()) return 0;
+    var biDecryptedSig = this.doPublic(biSig);
+    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
+  
+    if (digestInfoAry.length == 0) return false;
+    var algName = digestInfoAry[0];
+    var diHashValue = digestInfoAry[1];
+    return (diHashValue == sHashHex);
 }
 
+/**
+ * verifies a sigature for a message string with RSA public key by PKCS#1 PSS sign.<br/>
+ * @name verifyStringPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} sMsg message string to be verified.
+ * @param {String} hSig hexadecimal string of signature value
+ * @param {String} hashAlg hash algorithm name
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ *        There are two special values:
+ *        <ul>
+ *        <li>-1: sets the salt length to the digest length</li>
+ *        <li>-2: sets the salt length to maximum permissible value
+ *           (i.e. keybytelen - hashbytelen - 2)</li>
+ *        </ul>
+ *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns true if valid, otherwise false
+ */
+function _rsasign_verifyStringPSS(sMsg, hSig, hashAlg, sLen) {
+    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
+    var hHash = hashFunc(rstrtohex(sMsg));
 
+    if (sLen === undefined) sLen = -1;
+    return this.verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen);
+}
+
+/**
+ * verifies a sigature for a hash value of message string with RSA public key by PKCS#1 PSS sign.<br/>
+ * @name verifyWithMessageHashPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} hHash hexadecimal hash value of message string to be verified.
+ * @param {String} hSig hexadecimal string of signature value
+ * @param {String} hashAlg hash algorithm name
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ *        There are two special values:
+ *        <ul>
+ *        <li>-1: sets the salt length to the digest length</li>
+ *        <li>-2: sets the salt length to maximum permissible value
+ *           (i.e. keybytelen - hashbytelen - 2)</li>
+ *        </ul>
+ *        DEFAULT is -1 (NOTE: OpenSSL's default is -2.)
+ * @return returns true if valid, otherwise false
+ * @since rsasign 1.2.6
+ */
+function _rsasign_verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen) {
+    var biSig = new BigInteger(hSig, 16);
+
+    if (biSig.bitLength() > this.n.bitLength()) {
+        return false;
+    }
+
+    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
+    var mHash = hextorstr(hHash);
+    var hLen = mHash.length;
+    var emBits = this.n.bitLength() - 1;
+    var emLen = Math.ceil(emBits / 8);
+    var i;
+
+    if (sLen === -1 || sLen === undefined) {
+        sLen = hLen; // same as hash length
+    } else if (sLen === -2) {
+        sLen = emLen - hLen - 2; // recover
+    } else if (sLen < -2) {
+        throw "invalid salt length";
+    }
+
+    if (emLen < (hLen + sLen + 2)) {
+        throw "data too long";
+    }
+
+    var em = this.doPublic(biSig).toByteArray();
+
+    for (i = 0; i < em.length; i += 1) {
+        em[i] &= 0xff;
+    }
+
+    while (em.length < emLen) {
+        em.unshift(0);
+    }
+
+    if (em[emLen -1] !== 0xbc) {
+        throw "encoded message does not end in 0xbc";
+    }
+
+    em = String.fromCharCode.apply(String, em);
+
+    var maskedDB = em.substr(0, emLen - hLen - 1);
+    var H = em.substr(maskedDB.length, hLen);
+
+    var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
+
+    if ((maskedDB.charCodeAt(0) & mask) !== 0) {
+        throw "bits beyond keysize not zero";
+    }
+
+    var dbMask = pss_mgf1_str(H, maskedDB.length, hashFunc);
+    var DB = [];
+
+    for (i = 0; i < maskedDB.length; i += 1) {
+        DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+    }
+
+    DB[0] &= ~mask;
+
+    var checkLen = emLen - hLen - sLen - 2;
+
+    for (i = 0; i < checkLen; i += 1) {
+        if (DB[i] !== 0x00) {
+            throw "leftmost octets not zero";
+        }
+    }
+
+    if (DB[checkLen] !== 0x01) {
+        throw "0x01 marker not found";
+    }
+
+    return H === hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
+				     String.fromCharCode.apply(String, DB.slice(-sLen)))));
+}
+
+RSAKey.prototype.signWithMessageHash = _rsasign_signWithMessageHash;
 RSAKey.prototype.signString = _rsasign_signString;
-
-RSAKey.prototype.signByteArray = _rsasign_signByteArray; //@author axelcdv
-RSAKey.prototype.signByteArrayWithSHA256 = _rsasign_signByteArrayWithSHA256; //@author axelcdv
-
 RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
 RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
 RSAKey.prototype.sign = _rsasign_signString;
 RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
 RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
 
+RSAKey.prototype.signWithMessageHashPSS = _rsasign_signWithMessageHashPSS;
+RSAKey.prototype.signStringPSS = _rsasign_signStringPSS;
+RSAKey.prototype.signPSS = _rsasign_signStringPSS;
+RSAKey.SALT_LEN_HLEN = -1;
+RSAKey.SALT_LEN_MAX = -2;
 
-/*RSAKey.prototype.signStringHEX = _rsasign_signStringHEX;
-RSAKey.prototype.signStringWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
-RSAKey.prototype.signStringWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
-RSAKey.prototype.signHEX = _rsasign_signStringHEX;
-RSAKey.prototype.signWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
-RSAKey.prototype.signWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
-*/
-
-RSAKey.prototype.verifyByteArray = _rsasign_verifyByteArray;
+RSAKey.prototype.verifyWithMessageHash = _rsasign_verifyWithMessageHash;
 RSAKey.prototype.verifyString = _rsasign_verifyString;
 RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
 RSAKey.prototype.verify = _rsasign_verifyString;
 RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
 
-/*
-RSAKey.prototype.verifyStringHEX = _rsasign_verifyStringHEX;
-RSAKey.prototype.verifyHexSignatureForMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
-RSAKey.prototype.verifyHEX = _rsasign_verifyStringHEX;
-RSAKey.prototype.verifyHexSignatureForByteArrayMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
-*/
-	
-	
+RSAKey.prototype.verifyWithMessageHashPSS = _rsasign_verifyWithMessageHashPSS;
+RSAKey.prototype.verifyStringPSS = _rsasign_verifyStringPSS;
+RSAKey.prototype.verifyPSS = _rsasign_verifyStringPSS;
+RSAKey.SALT_LEN_RECOVER = -2;
+
 /**
  * @name RSAKey
- * @class
+ * @class key of RSA public key algorithm
  * @description Tom Wu's RSA Key class and extension
  */
-/*! asn1hex-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
- */
-//
-// asn1hex.js - Hexadecimal represented ASN.1 string library
-//
-// version: 1.1 (09-May-2012)
-//
-// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
-//
-// This software is licensed under the terms of the MIT License.
-// http://kjur.github.com/jsrsasign/license/
-//
-// The above copyright and license notice shall be 
-// included in all copies or substantial portions of the Software.
-//
-// Depends on:
-//
 
-// MEMO:
-//   f('3082025b02...', 2) ... 82025b ... 3bytes
-//   f('020100', 2) ... 01 ... 1byte
-//   f('0203001...', 2) ... 03 ... 1byte
-//   f('02818003...', 2) ... 8180 ... 2bytes
-//   f('3080....0000', 2) ... 80 ... -1
-//
-//   Requirements:
-//   - ASN.1 type octet length MUST be 1. 
-//     (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
-//   - 
-/**
- * get byte length for ASN.1 L(length) bytes
- * @name getByteLengthOfL_AtObj
- * @memberOf ASN1HEX
- * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return byte length for ASN.1 L(length) bytes
+exports.RSAKey = RSAKey;
+module.exports = exports;
+/*! ecdsa-modified-1.0.4.js (c) Stephan Thomas, Kenji Urushima | github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
  */
-function _asnhex_getByteLengthOfL_AtObj(s, pos) {
-  if (s.substring(pos + 2, pos + 3) != '8') return 1;
-  var i = parseInt(s.substring(pos + 3, pos + 4));
-  if (i == 0) return -1; 		// length octet '80' indefinite length
-  if (0 < i && i < 10) return i + 1;	// including '8?' octet;
-  return -2;				// malformed format
-}
-
+/*
+ * ecdsa-modified.js - modified Bitcoin.ECDSA class
+ * 
+ * Copyright (c) 2013 Stefan Thomas (github.com/justmoon)
+ *                    Kenji Urushima (kenji.urushima@gmail.com)
+ * LICENSE
+ *   https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
+ */
 
 /**
- * get hexadecimal string for ASN.1 L(length) bytes
- * @name getHexOfL_AtObj
- * @memberOf ASN1HEX
- * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return {String} hexadecimal string for ASN.1 L(length) bytes
+ * @fileOverview
+ * @name ecdsa-modified-1.0.js
+ * @author Stefan Thomas (github.com/justmoon) and Kenji Urushima (kenji.urushima@gmail.com)
+ * @version 1.0.4 (2013-Oct-06)
+ * @since jsrsasign 4.0
+ * @license <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE">MIT License</a>
  */
-function _asnhex_getHexOfL_AtObj(s, pos) {
-  var len = _asnhex_getByteLengthOfL_AtObj(s, pos);
-  if (len < 1) return '';
-  return s.substring(pos + 2, pos + 2 + len * 2);
-}
 
-//
-//   getting ASN.1 length value at the position 'idx' of
-//   hexa decimal string 's'.
-//
-//   f('3082025b02...', 0) ... 82025b ... ???
-//   f('020100', 0) ... 01 ... 1
-//   f('0203001...', 0) ... 03 ... 3
-//   f('02818003...', 0) ... 8180 ... 128
-/**
- * get integer value of ASN.1 length for ASN.1 data
- * @name getIntOfL_AtObj
- * @memberOf ASN1HEX
- * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return ASN.1 L(length) integer value
- */
-function _asnhex_getIntOfL_AtObj(s, pos) {
-  var hLength = _asnhex_getHexOfL_AtObj(s, pos);
-  if (hLength == '') return -1;
-  var bi;
-  if (parseInt(hLength.substring(0, 1)) < 8) {
-     bi = parseBigInt(hLength, 16);
-  } else {
-     bi = parseBigInt(hLength.substring(2), 16);
-  }
-  return bi.intValue();
-}
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
 
 /**
- * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
- * @name getStartPosOfV_AtObj
- * @memberOf ASN1HEX
- * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
+ * class for EC key generation,  ECDSA signing and verifcation
+ * @name KJUR.crypto.ECDSA
+ * @class class for EC key generation,  ECDSA signing and verifcation
+ * @description
+ * <p>
+ * CAUTION: Most of the case, you don't need to use this class except
+ * for generating an EC key pair. Please use {@link KJUR.crypto.Signature} class instead.
+ * </p>
+ * <p>
+ * This class was originally developped by Stefan Thomas for Bitcoin JavaScript library.
+ * (See {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/src/ecdsa.js})
+ * Currently this class supports following named curves and their aliases.
+ * <ul>
+ * <li>secp256r1, NIST P-256, P-256, prime256v1 (*)</li>
+ * <li>secp256k1 (*)</li>
+ * <li>secp384r1, NIST P-384, P-384 (*)</li>
+ * </ul>
+ * </p>
  */
-function _asnhex_getStartPosOfV_AtObj(s, pos) {
-  var l_len = _asnhex_getByteLengthOfL_AtObj(s, pos);
-  if (l_len < 0) return l_len;
-  return pos + (l_len + 1) * 2;
-}
+KJUR.crypto.ECDSA = function(params) {
+    var curveName = "secp256r1";	// curve name default
+    var ecparams = null;
+    var prvKeyHex = null;
+    var pubKeyHex = null;
+
+    var rng = new SecureRandom();
+
+    var P_OVER_FOUR = null;
+
+    this.type = "EC";
+
+    function implShamirsTrick(P, k, Q, l) {
+	var m = Math.max(k.bitLength(), l.bitLength());
+	var Z = P.add2D(Q);
+	var R = P.curve.getInfinity();
+
+	for (var i = m - 1; i >= 0; --i) {
+	    R = R.twice2D();
+
+	    R.z = BigInteger.ONE;
+
+	    if (k.testBit(i)) {
+		if (l.testBit(i)) {
+		    R = R.add2D(Z);
+		} else {
+		    R = R.add2D(P);
+		}
+	    } else {
+		if (l.testBit(i)) {
+		    R = R.add2D(Q);
+		}
+	    }
+	}
+	
+	return R;
+    };
+
+    //===========================
+    // PUBLIC METHODS
+    //===========================
+    this.getBigRandom = function (limit) {
+	return new BigInteger(limit.bitLength(), rng)
+	.mod(limit.subtract(BigInteger.ONE))
+	.add(BigInteger.ONE)
+	;
+    };
+
+    this.setNamedCurve = function(curveName) {
+	this.ecparams = KJUR.crypto.ECParameterDB.getByName(curveName);
+	this.prvKeyHex = null;
+	this.pubKeyHex = null;
+	this.curveName = curveName;
+    }
+
+    this.setPrivateKeyHex = function(prvKeyHex) {
+        this.isPrivate = true;
+	this.prvKeyHex = prvKeyHex;
+    }
+
+    this.setPublicKeyHex = function(pubKeyHex) {
+        this.isPublic = true;
+	this.pubKeyHex = pubKeyHex;
+    }
+
+    /**
+     * generate a EC key pair
+     * @name generateKeyPairHex
+     * @memberOf KJUR.crypto.ECDSA
+     * @function
+     * @return {Array} associative array of hexadecimal string of private and public key
+     * @since ecdsa-modified 1.0.1
+     * @example
+     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+     * var keypair = ec.generateKeyPairHex();
+     * var pubhex = keypair.ecpubhex; // hexadecimal string of EC private key (=d)
+     * var prvhex = keypair.ecprvhex; // hexadecimal string of EC public key
+     */
+    this.generateKeyPairHex = function() {
+	var biN = this.ecparams['n'];
+	var biPrv = this.getBigRandom(biN);
+	var epPub = this.ecparams['G'].multiply(biPrv);
+	var biX = epPub.getX().toBigInteger();
+	var biY = epPub.getY().toBigInteger();
+
+	var charlen = this.ecparams['keylen'] / 4;
+	var hPrv = ("0000000000" + biPrv.toString(16)).slice(- charlen);
+	var hX   = ("0000000000" + biX.toString(16)).slice(- charlen);
+	var hY   = ("0000000000" + biY.toString(16)).slice(- charlen);
+	var hPub = "04" + hX + hY;
+
+	this.setPrivateKeyHex(hPrv);
+	this.setPublicKeyHex(hPub);
+	return {'ecprvhex': hPrv, 'ecpubhex': hPub};
+    };
+
+    this.signWithMessageHash = function(hashHex) {
+	return this.signHex(hashHex, this.prvKeyHex);
+    };
+
+    /**
+     * signing to message hash
+     * @name signHex
+     * @memberOf KJUR.crypto.ECDSA
+     * @function
+     * @param {String} hashHex hexadecimal string of hash value of signing message
+     * @param {String} privHex hexadecimal string of EC private key
+     * @return {String} hexadecimal string of ECDSA signature
+     * @since ecdsa-modified 1.0.1
+     * @example
+     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+     * var sigValue = ec.signHex(hash, prvKey);
+     */
+    this.signHex = function (hashHex, privHex) {
+	var d = new BigInteger(privHex, 16);
+	var n = this.ecparams['n'];
+	var e = new BigInteger(hashHex, 16);
+
+	do {
+	    var k = this.getBigRandom(n);
+	    var G = this.ecparams['G'];
+	    var Q = G.multiply(k);
+	    var r = Q.getX().toBigInteger().mod(n);
+	} while (r.compareTo(BigInteger.ZERO) <= 0);
+
+	var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+
+	return KJUR.crypto.ECDSA.biRSSigToASN1Sig(r, s);
+    };
+
+    this.sign = function (hash, priv) {
+	var d = priv;
+	var n = this.ecparams['n'];
+	var e = BigInteger.fromByteArrayUnsigned(hash);
+
+	do {
+	    var k = this.getBigRandom(n);
+	    var G = this.ecparams['G'];
+	    var Q = G.multiply(k);
+	    var r = Q.getX().toBigInteger().mod(n);
+	} while (r.compareTo(BigInteger.ZERO) <= 0);
+
+	var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+	return this.serializeSig(r, s);
+    };
+
+    this.verifyWithMessageHash = function(hashHex, sigHex) {
+	return this.verifyHex(hashHex, sigHex, this.pubKeyHex);
+    };
+
+    /**
+     * verifying signature with message hash and public key
+     * @name verifyHex
+     * @memberOf KJUR.crypto.ECDSA
+     * @function
+     * @param {String} hashHex hexadecimal string of hash value of signing message
+     * @param {String} sigHex hexadecimal string of signature value
+     * @param {String} pubkeyHex hexadecimal string of public key
+     * @return {Boolean} true if the signature is valid, otherwise false
+     * @since ecdsa-modified 1.0.1
+     * @example
+     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+     * var result = ec.verifyHex(msgHashHex, sigHex, pubkeyHex);
+     */
+    this.verifyHex = function(hashHex, sigHex, pubkeyHex) {
+	var r,s;
+
+	var obj = KJUR.crypto.ECDSA.parseSigHex(sigHex);
+	r = obj.r;
+	s = obj.s;
+
+	var Q;
+	Q = ECPointFp.decodeFromHex(this.ecparams['curve'], pubkeyHex);
+	var e = new BigInteger(hashHex, 16);
+
+	return this.verifyRaw(e, r, s, Q);
+    };
+
+    this.verify = function (hash, sig, pubkey) {
+	var r,s;
+	if (Bitcoin.Util.isArray(sig)) {
+	    var obj = this.parseSig(sig);
+	    r = obj.r;
+	    s = obj.s;
+	} else if ("object" === typeof sig && sig.r && sig.s) {
+	    r = sig.r;
+	    s = sig.s;
+	} else {
+	    throw "Invalid value for signature";
+	}
+
+	var Q;
+	if (pubkey instanceof ECPointFp) {
+	    Q = pubkey;
+	} else if (Bitcoin.Util.isArray(pubkey)) {
+	    Q = ECPointFp.decodeFrom(this.ecparams['curve'], pubkey);
+	} else {
+	    throw "Invalid format for pubkey value, must be byte array or ECPointFp";
+	}
+	var e = BigInteger.fromByteArrayUnsigned(hash);
+
+	return this.verifyRaw(e, r, s, Q);
+    };
+
+    this.verifyRaw = function (e, r, s, Q) {
+	var n = this.ecparams['n'];
+	var G = this.ecparams['G'];
+
+	if (r.compareTo(BigInteger.ONE) < 0 ||
+	    r.compareTo(n) >= 0)
+	    return false;
+
+	if (s.compareTo(BigInteger.ONE) < 0 ||
+	    s.compareTo(n) >= 0)
+	    return false;
+
+	var c = s.modInverse(n);
+
+	var u1 = e.multiply(c).mod(n);
+	var u2 = r.multiply(c).mod(n);
+
+	// TODO(!!!): For some reason Shamir's trick isn't working with
+	// signed message verification!? Probably an implementation
+	// error!
+	//var point = implShamirsTrick(G, u1, Q, u2);
+	var point = G.multiply(u1).add(Q.multiply(u2));
+
+	var v = point.getX().toBigInteger().mod(n);
+
+	return v.equals(r);
+    };
+
+    /**
+     * Serialize a signature into DER format.
+     *
+     * Takes two BigIntegers representing r and s and returns a byte array.
+     */
+    this.serializeSig = function (r, s) {
+	var rBa = r.toByteArraySigned();
+	var sBa = s.toByteArraySigned();
+
+	var sequence = [];
+	sequence.push(0x02); // INTEGER
+	sequence.push(rBa.length);
+	sequence = sequence.concat(rBa);
+
+	sequence.push(0x02); // INTEGER
+	sequence.push(sBa.length);
+	sequence = sequence.concat(sBa);
+
+	sequence.unshift(sequence.length);
+	sequence.unshift(0x30); // SEQUENCE
+	return sequence;
+    };
+
+    /**
+     * Parses a byte array containing a DER-encoded signature.
+     *
+     * This function will return an object of the form:
+     *
+     * {
+     *   r: BigInteger,
+     *   s: BigInteger
+     * }
+     */
+    this.parseSig = function (sig) {
+	var cursor;
+	if (sig[0] != 0x30)
+	    throw new Error("Signature not a valid DERSequence");
+
+	cursor = 2;
+	if (sig[cursor] != 0x02)
+	    throw new Error("First element in signature must be a DERInteger");;
+	var rBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
+
+	cursor += 2+sig[cursor+1];
+	if (sig[cursor] != 0x02)
+	    throw new Error("Second element in signature must be a DERInteger");
+	var sBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
+
+	cursor += 2+sig[cursor+1];
+
+	//if (cursor != sig.length)
+	//  throw new Error("Extra bytes in signature");
+
+	var r = BigInteger.fromByteArrayUnsigned(rBa);
+	var s = BigInteger.fromByteArrayUnsigned(sBa);
+
+	return {r: r, s: s};
+    };
+
+    this.parseSigCompact = function (sig) {
+	if (sig.length !== 65) {
+	    throw "Signature has the wrong length";
+	}
+
+	// Signature is prefixed with a type byte storing three bits of
+	// information.
+	var i = sig[0] - 27;
+	if (i < 0 || i > 7) {
+	    throw "Invalid signature type";
+	}
+
+	var n = this.ecparams['n'];
+	var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n);
+	var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n);
+
+	return {r: r, s: s, i: i};
+    };
+
+    /*
+     * Recover a public key from a signature.
+     *
+     * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
+     * Key Recovery Operation".
+     *
+     * http://www.secg.org/download/aid-780/sec1-v2.pdf
+     */
+    /*
+    recoverPubKey: function (r, s, hash, i) {
+	// The recovery parameter i has two bits.
+	i = i & 3;
+
+	// The less significant bit specifies whether the y coordinate
+	// of the compressed point is even or not.
+	var isYEven = i & 1;
+
+	// The more significant bit specifies whether we should use the
+	// first or second candidate key.
+	var isSecondKey = i >> 1;
+
+	var n = this.ecparams['n'];
+	var G = this.ecparams['G'];
+	var curve = this.ecparams['curve'];
+	var p = curve.getQ();
+	var a = curve.getA().toBigInteger();
+	var b = curve.getB().toBigInteger();
+
+	// We precalculate (p + 1) / 4 where p is if the field order
+	if (!P_OVER_FOUR) {
+	    P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4));
+	}
+
+	// 1.1 Compute x
+	var x = isSecondKey ? r.add(n) : r;
+
+	// 1.3 Convert x to point
+	var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p);
+	var beta = alpha.modPow(P_OVER_FOUR, p);
+
+	var xorOdd = beta.isEven() ? (i % 2) : ((i+1) % 2);
+	// If beta is even, but y isn't or vice versa, then convert it,
+	// otherwise we're done and y == beta.
+	var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta);
+
+	// 1.4 Check that nR is at infinity
+	var R = new ECPointFp(curve,
+			      curve.fromBigInteger(x),
+			      curve.fromBigInteger(y));
+	R.validate();
+
+	// 1.5 Compute e from M
+	var e = BigInteger.fromByteArrayUnsigned(hash);
+	var eNeg = BigInteger.ZERO.subtract(e).mod(n);
+
+	// 1.6 Compute Q = r^-1 (sR - eG)
+	var rInv = r.modInverse(n);
+	var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv);
+
+	Q.validate();
+	if (!this.verifyRaw(e, r, s, Q)) {
+	    throw "Pubkey recovery unsuccessful";
+	}
+
+	var pubKey = new Bitcoin.ECKey();
+	pubKey.pub = Q;
+	return pubKey;
+    },
+    */
+
+    /*
+     * Calculate pubkey extraction parameter.
+     *
+     * When extracting a pubkey from a signature, we have to
+     * distinguish four different cases. Rather than putting this
+     * burden on the verifier, Bitcoin includes a 2-bit value with the
+     * signature.
+     *
+     * This function simply tries all four cases and returns the value
+     * that resulted in a successful pubkey recovery.
+     */
+    /*
+    calcPubkeyRecoveryParam: function (address, r, s, hash) {
+	for (var i = 0; i < 4; i++) {
+	    try {
+		var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i);
+		if (pubkey.getBitcoinAddress().toString() == address) {
+		    return i;
+		}
+	    } catch (e) {}
+	}
+	throw "Unable to find valid recovery factor";
+    }
+    */
+
+    if (params !== undefined) {
+	if (params['curve'] !== undefined) {
+	    this.curveName = params['curve'];
+	}
+    }
+    if (this.curveName === undefined) this.curveName = curveName;
+    this.setNamedCurve(this.curveName);
+    if (params !== undefined) {
+	if (params['prv'] !== undefined) this.setPrivateKeyHex(params['prv']);
+	if (params['pub'] !== undefined) this.setPublicKeyHex(params['pub']);
+    }
+};
 
 /**
- * get hexadecimal string of ASN.1 V(value)
- * @name getHexOfV_AtObj
- * @memberOf ASN1HEX
+ * parse ASN.1 DER encoded ECDSA signature
+ * @name parseSigHex
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return {String} hexadecimal string of ASN.1 value.
+ * @static
+ * @param {String} sigHex hexadecimal string of ECDSA signature value
+ * @return {Array} associative array of signature field r and s of BigInteger
+ * @since ecdsa-modified 1.0.1
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var sig = ec.parseSigHex('30...');
+ * var biR = sig.r; // BigInteger object for 'r' field of signature.
+ * var biS = sig.s; // BigInteger object for 's' field of signature.
  */
-function _asnhex_getHexOfV_AtObj(s, pos) {
-  var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
-  var len = _asnhex_getIntOfL_AtObj(s, pos);
-  return s.substring(pos1, pos1 + len * 2);
-}
+KJUR.crypto.ECDSA.parseSigHex = function(sigHex) {
+    var p = KJUR.crypto.ECDSA.parseSigHexInHexRS(sigHex);
+    var biR = new BigInteger(p.r, 16);
+    var biS = new BigInteger(p.s, 16);
+    
+    return {'r': biR, 's': biS};
+};
 
 /**
- * get hexadecimal string of ASN.1 TLV at
- * @name getHexOfTLV_AtObj
- * @memberOf ASN1HEX
+ * parse ASN.1 DER encoded ECDSA signature
+ * @name parseSigHexInHexRS
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return {String} hexadecimal string of ASN.1 TLV.
- * @since 1.1
+ * @static
+ * @param {String} sigHex hexadecimal string of ECDSA signature value
+ * @return {Array} associative array of signature field r and s in hexadecimal
+ * @since ecdsa-modified 1.0.3
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var sig = ec.parseSigHexInHexRS('30...');
+ * var hR = sig.r; // hexadecimal string for 'r' field of signature.
+ * var hS = sig.s; // hexadecimal string for 's' field of signature.
  */
-function _asnhex_getHexOfTLV_AtObj(s, pos) {
-  var hT = s.substr(pos, 2);
-  var hL = _asnhex_getHexOfL_AtObj(s, pos);
-  var hV = _asnhex_getHexOfV_AtObj(s, pos);
-  return hT + hL + hV;
-}
+KJUR.crypto.ECDSA.parseSigHexInHexRS = function(sigHex) {
+    // 1. ASN.1 Sequence Check
+    if (sigHex.substr(0, 2) != "30")
+	throw "signature is not a ASN.1 sequence";
+
+    // 2. Items of ASN.1 Sequence Check
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(sigHex, 0);
+    if (a.length != 2)
+	throw "number of signature ASN.1 sequence elements seem wrong";
+    
+    // 3. Integer check
+    var iTLV1 = a[0];
+    var iTLV2 = a[1];
+    if (sigHex.substr(iTLV1, 2) != "02")
+	throw "1st item of sequene of signature is not ASN.1 integer";
+    if (sigHex.substr(iTLV2, 2) != "02")
+	throw "2nd item of sequene of signature is not ASN.1 integer";
+
+    // 4. getting value
+    var hR = ASN1HEX.getHexOfV_AtObj(sigHex, iTLV1);
+    var hS = ASN1HEX.getHexOfV_AtObj(sigHex, iTLV2);
+    
+    return {'r': hR, 's': hS};
+};
 
 /**
- * get next sibling starting index for ASN.1 object string
- * @name getPosOfNextSibling_AtObj
- * @memberOf ASN1HEX
+ * convert hexadecimal ASN.1 encoded signature to concatinated signature
+ * @name asn1SigToConcatSig
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return next sibling starting index for ASN.1 object string
+ * @static
+ * @param {String} asn1Hex hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @return {String} r-s concatinated format of ECDSA signature value
+ * @since ecdsa-modified 1.0.3
  */
-function _asnhex_getPosOfNextSibling_AtObj(s, pos) {
-  var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
-  var len = _asnhex_getIntOfL_AtObj(s, pos);
-  return pos1 + len * 2;
-}
+KJUR.crypto.ECDSA.asn1SigToConcatSig = function(asn1Sig) {
+    var pSig = KJUR.crypto.ECDSA.parseSigHexInHexRS(asn1Sig);
+    var hR = pSig.r;
+    var hS = pSig.s;
+
+    if (hR.substr(0, 2) == "00" && (((hR.length / 2) * 8) % (16 * 8)) == 8) 
+	hR = hR.substr(2);
+
+    if (hS.substr(0, 2) == "00" && (((hS.length / 2) * 8) % (16 * 8)) == 8) 
+	hS = hS.substr(2);
+
+    if ((((hR.length / 2) * 8) % (16 * 8)) != 0)
+	throw "unknown ECDSA sig r length error";
+
+    if ((((hS.length / 2) * 8) % (16 * 8)) != 0)
+	throw "unknown ECDSA sig s length error";
+
+    return hR + hS;
+};
 
 /**
- * get array of indexes of child ASN.1 objects
- * @name getPosArrayOfChildren_AtObj
- * @memberOf ASN1HEX
+ * convert hexadecimal concatinated signature to ASN.1 encoded signature
+ * @name concatSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} start string index of ASN.1 object
- * @return {Array of Number} array of indexes for childen of ASN.1 objects
+ * @static
+ * @param {String} concatSig r-s concatinated format of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
  */
-function _asnhex_getPosArrayOfChildren_AtObj(h, pos) {
-  var a = new Array();
-  var p0 = _asnhex_getStartPosOfV_AtObj(h, pos);
-  a.push(p0);
+KJUR.crypto.ECDSA.concatSigToASN1Sig = function(concatSig) {
+    if ((((concatSig.length / 2) * 8) % (16 * 8)) != 0)
+	throw "unknown ECDSA concatinated r-s sig  length error";
 
-  var len = _asnhex_getIntOfL_AtObj(h, pos);
-  var p = p0;
-  var k = 0;
-  while (1) {
-    var pNext = _asnhex_getPosOfNextSibling_AtObj(h, p);
-    if (pNext == null || (pNext - p0  >= (len * 2))) break;
-    if (k >= 200) break;
-
-    a.push(pNext);
-    p = pNext;
-
-    k++;
-  }
-
-  return a;
-}
+    var hR = concatSig.substr(0, concatSig.length / 2);
+    var hS = concatSig.substr(concatSig.length / 2);
+    return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(hR, hS);
+};
 
 /**
- * get string index of nth child object of ASN.1 object refered by h, idx
- * @name getNthChildIndex_AtObj
- * @memberOf ASN1HEX
+ * convert hexadecimal R and S value of signature to ASN.1 encoded signature
+ * @name hexRSSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} h hexadecimal string of ASN.1 DER encoded data
- * @param {Number} idx start string index of ASN.1 object
- * @param {Number} nth for child
- * @return {Number} string index of nth child.
- * @since 1.1
+ * @static
+ * @param {String} hR hexadecimal string of R field of ECDSA signature value
+ * @param {String} hS hexadecimal string of S field of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
  */
-function _asnhex_getNthChildIndex_AtObj(h, idx, nth) {
-  var a = _asnhex_getPosArrayOfChildren_AtObj(h, idx);
-  return a[nth];
-}
-
-// ========== decendant methods ==============================
+KJUR.crypto.ECDSA.hexRSSigToASN1Sig = function(hR, hS) {
+    var biR = new BigInteger(hR, 16);
+    var biS = new BigInteger(hS, 16);
+    return KJUR.crypto.ECDSA.biRSSigToASN1Sig(biR, biS);
+};
 
 /**
- * get string index of nth child object of ASN.1 object refered by h, idx
- * @name getDecendantIndexByNthList
- * @memberOf ASN1HEX
+ * convert R and S BigInteger object of signature to ASN.1 encoded signature
+ * @name biRSSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} h hexadecimal string of ASN.1 DER encoded data
- * @param {Number} currentIndex start string index of ASN.1 object
- * @param {Array of Number} nthList array list of nth
- * @return {Number} string index refered by nthList
- * @since 1.1
+ * @static
+ * @param {BigInteger} biR BigInteger object of R field of ECDSA signature value
+ * @param {BigInteger} biS BIgInteger object of S field of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
  */
-function _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList) {
-  if (nthList.length == 0) {
-    return currentIndex;
-  }
-  var firstNth = nthList.shift();
-  var a = _asnhex_getPosArrayOfChildren_AtObj(h, currentIndex);
-  return _asnhex_getDecendantIndexByNthList(h, a[firstNth], nthList);
-}
+KJUR.crypto.ECDSA.biRSSigToASN1Sig = function(biR, biS) {
+    var derR = new KJUR.asn1.DERInteger({'bigint': biR});
+    var derS = new KJUR.asn1.DERInteger({'bigint': biS});
+    var derSeq = new KJUR.asn1.DERSequence({'array': [derR, derS]});
+    return derSeq.getEncodedHex();
+};
+
+/*! asn1hex-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * asn1hex.js - Hexadecimal represented ASN.1 string library
+ *
+ * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license/
+ *
+ * The above copyright and license notice shall be 
+ * included in all copies or substantial portions of the Software.
+ */
 
 /**
- * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
- * @name getDecendantHexTLVByNthList
- * @memberOf ASN1HEX
- * @function
- * @param {String} h hexadecimal string of ASN.1 DER encoded data
- * @param {Number} currentIndex start string index of ASN.1 object
- * @param {Array of Number} nthList array list of nth
- * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
- * @since 1.1
+ * @fileOverview
+ * @name asn1hex-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version asn1hex 1.1.6 (2015-Jun-11)
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
  */
-function _asnhex_getDecendantHexTLVByNthList(h, currentIndex, nthList) {
-  var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
-  return _asnhex_getHexOfTLV_AtObj(h, idx);
-}
 
-/**
- * get hexadecimal string of ASN.1 V refered by current index and nth index list.
- * @name getDecendantHexVByNthList
- * @memberOf ASN1HEX
- * @function
- * @param {String} h hexadecimal string of ASN.1 DER encoded data
- * @param {Number} currentIndex start string index of ASN.1 object
- * @param {Array of Number} nthList array list of nth
- * @return {Number} hexadecimal string of ASN.1 V refered by nthList
- * @since 1.1
+/*
+ * MEMO:
+ *   f('3082025b02...', 2) ... 82025b ... 3bytes
+ *   f('020100', 2) ... 01 ... 1byte
+ *   f('0203001...', 2) ... 03 ... 1byte
+ *   f('02818003...', 2) ... 8180 ... 2bytes
+ *   f('3080....0000', 2) ... 80 ... -1
+ *
+ *   Requirements:
+ *   - ASN.1 type octet length MUST be 1. 
+ *     (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
  */
-function _asnhex_getDecendantHexVByNthList(h, currentIndex, nthList) {
-  var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
-  return _asnhex_getHexOfV_AtObj(h, idx);
-}
-
-// ========== class definition ==============================
 
 /**
  * ASN.1 DER encoded hexadecimal string utility class
+ * @name ASN1HEX
  * @class ASN.1 DER encoded hexadecimal string utility class
- * @author Kenji Urushima
- * @version 1.1 (09 May 2012)
- * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
- * @since 1.1
+ * @since jsrsasign 1.1
  */
-function ASN1HEX() {
-  return ASN1HEX;
-}
+var intShim = require('jsbn');
 
-ASN1HEX.getByteLengthOfL_AtObj = _asnhex_getByteLengthOfL_AtObj;
-ASN1HEX.getHexOfL_AtObj = _asnhex_getHexOfL_AtObj;
-ASN1HEX.getIntOfL_AtObj = _asnhex_getIntOfL_AtObj;
-ASN1HEX.getStartPosOfV_AtObj = _asnhex_getStartPosOfV_AtObj;
-ASN1HEX.getHexOfV_AtObj = _asnhex_getHexOfV_AtObj;
-ASN1HEX.getHexOfTLV_AtObj = _asnhex_getHexOfTLV_AtObj;
-ASN1HEX.getPosOfNextSibling_AtObj = _asnhex_getPosOfNextSibling_AtObj;
-ASN1HEX.getPosArrayOfChildren_AtObj = _asnhex_getPosArrayOfChildren_AtObj;
-ASN1HEX.getNthChildIndex_AtObj = _asnhex_getNthChildIndex_AtObj;
-ASN1HEX.getDecendantIndexByNthList = _asnhex_getDecendantIndexByNthList;
-ASN1HEX.getDecendantHexVByNthList = _asnhex_getDecendantHexVByNthList;
-ASN1HEX.getDecendantHexTLVByNthList = _asnhex_getDecendantHexTLVByNthList;
-/*! x509-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
+var ASN1HEX = new function() {
+    /**
+     * get byte length for ASN.1 L(length) bytes
+     * @name getByteLengthOfL_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return byte length for ASN.1 L(length) bytes
+     */
+    this.getByteLengthOfL_AtObj = function(s, pos) {
+        if (s.substring(pos + 2, pos + 3) != '8') return 1;
+        var i = parseInt(s.substring(pos + 3, pos + 4));
+        if (i == 0) return -1;          // length octet '80' indefinite length
+        if (0 < i && i < 10) return i + 1;      // including '8?' octet;
+        return -2;                              // malformed format
+    };
+
+    /**
+     * get hexadecimal string for ASN.1 L(length) bytes
+     * @name getHexOfL_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return {String} hexadecimal string for ASN.1 L(length) bytes
+     */
+    this.getHexOfL_AtObj = function(s, pos) {
+        var len = this.getByteLengthOfL_AtObj(s, pos);
+        if (len < 1) return '';
+        return s.substring(pos + 2, pos + 2 + len * 2);
+    };
+
+    //   getting ASN.1 length value at the position 'idx' of
+    //   hexa decimal string 's'.
+    //
+    //   f('3082025b02...', 0) ... 82025b ... ???
+    //   f('020100', 0) ... 01 ... 1
+    //   f('0203001...', 0) ... 03 ... 3
+    //   f('02818003...', 0) ... 8180 ... 128
+    /**
+     * get integer value of ASN.1 length for ASN.1 data
+     * @name getIntOfL_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return ASN.1 L(length) integer value
+     */
+    this.getIntOfL_AtObj = function(s, pos) {
+        var hLength = this.getHexOfL_AtObj(s, pos);
+        if (hLength == '') return -1;
+        var bi;
+        if (parseInt(hLength.substring(0, 1)) < 8) {
+            bi = new BigInteger(hLength, 16);
+        } else {
+            bi = new BigInteger(hLength.substring(2), 16);
+        }
+        return bi.intValue();
+    };
+
+    /**
+     * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
+     * @name getStartPosOfV_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     */
+    this.getStartPosOfV_AtObj = function(s, pos) {
+        var l_len = this.getByteLengthOfL_AtObj(s, pos);
+        if (l_len < 0) return l_len;
+        return pos + (l_len + 1) * 2;
+    };
+
+    /**
+     * get hexadecimal string of ASN.1 V(value)
+     * @name getHexOfV_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return {String} hexadecimal string of ASN.1 value.
+     */
+    this.getHexOfV_AtObj = function(s, pos) {
+        var pos1 = this.getStartPosOfV_AtObj(s, pos);
+        var len = this.getIntOfL_AtObj(s, pos);
+        return s.substring(pos1, pos1 + len * 2);
+    };
+
+    /**
+     * get hexadecimal string of ASN.1 TLV at
+     * @name getHexOfTLV_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return {String} hexadecimal string of ASN.1 TLV.
+     * @since 1.1
+     */
+    this.getHexOfTLV_AtObj = function(s, pos) {
+        var hT = s.substr(pos, 2);
+        var hL = this.getHexOfL_AtObj(s, pos);
+        var hV = this.getHexOfV_AtObj(s, pos);
+        return hT + hL + hV;
+    };
+
+    /**
+     * get next sibling starting index for ASN.1 object string
+     * @name getPosOfNextSibling_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return next sibling starting index for ASN.1 object string
+     */
+    this.getPosOfNextSibling_AtObj = function(s, pos) {
+        var pos1 = this.getStartPosOfV_AtObj(s, pos);
+        var len = this.getIntOfL_AtObj(s, pos);
+        return pos1 + len * 2;
+    };
+
+    /**
+     * get array of indexes of child ASN.1 objects
+     * @name getPosArrayOfChildren_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} start string index of ASN.1 object
+     * @return {Array of Number} array of indexes for childen of ASN.1 objects
+     */
+    this.getPosArrayOfChildren_AtObj = function(h, pos) {
+        var a = new Array();
+        var p0 = this.getStartPosOfV_AtObj(h, pos);
+        a.push(p0);
+
+        var len = this.getIntOfL_AtObj(h, pos);
+        var p = p0;
+        var k = 0;
+        while (1) {
+            var pNext = this.getPosOfNextSibling_AtObj(h, p);
+            if (pNext == null || (pNext - p0  >= (len * 2))) break;
+            if (k >= 200) break;
+            
+            a.push(pNext);
+            p = pNext;
+            
+            k++;
+        }
+        
+        return a;
+    };
+
+    /**
+     * get string index of nth child object of ASN.1 object refered by h, idx
+     * @name getNthChildIndex_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} h hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} idx start string index of ASN.1 object
+     * @param {Number} nth for child
+     * @return {Number} string index of nth child.
+     * @since 1.1
+     */
+    this.getNthChildIndex_AtObj = function(h, idx, nth) {
+        var a = this.getPosArrayOfChildren_AtObj(h, idx);
+        return a[nth];
+    };
+
+    // ========== decendant methods ==============================
+    /**
+     * get string index of nth child object of ASN.1 object refered by h, idx
+     * @name getDecendantIndexByNthList
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} h hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} currentIndex start string index of ASN.1 object
+     * @param {Array of Number} nthList array list of nth
+     * @return {Number} string index refered by nthList
+     * @since 1.1
+     * @example
+     * The "nthList" is a index list of structured ASN.1 object
+     * reference. Here is a sample structure and "nthList"s which
+     * refers each objects.
+     *
+     * SQUENCE               - 
+     *   SEQUENCE            - [0]
+     *     IA5STRING 000     - [0, 0]
+     *     UTF8STRING 001    - [0, 1]
+     *   SET                 - [1]
+     *     IA5STRING 010     - [1, 0]
+     *     UTF8STRING 011    - [1, 1]
+     */
+    this.getDecendantIndexByNthList = function(h, currentIndex, nthList) {
+        if (nthList.length == 0) {
+            return currentIndex;
+        }
+        var firstNth = nthList.shift();
+        var a = this.getPosArrayOfChildren_AtObj(h, currentIndex);
+        return this.getDecendantIndexByNthList(h, a[firstNth], nthList);
+    };
+
+    /**
+     * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
+     * @name getDecendantHexTLVByNthList
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} h hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} currentIndex start string index of ASN.1 object
+     * @param {Array of Number} nthList array list of nth
+     * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
+     * @since 1.1
+     */
+    this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) {
+        var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
+        return this.getHexOfTLV_AtObj(h, idx);
+    };
+
+    /**
+     * get hexadecimal string of ASN.1 V refered by current index and nth index list.
+     * @name getDecendantHexVByNthList
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} h hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} currentIndex start string index of ASN.1 object
+     * @param {Array of Number} nthList array list of nth
+     * @return {Number} hexadecimal string of ASN.1 V refered by nthList
+     * @since 1.1
+     */
+    this.getDecendantHexVByNthList = function(h, currentIndex, nthList) {
+        var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
+        return this.getHexOfV_AtObj(h, idx);
+    };
+};
+
+/*
+ * @since asn1hex 1.1.4
  */
-// 
-// x509.js - X509 class to read subject public key from certificate.
-//
-// version: 1.1 (10-May-2012)
-//
-// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
-//
-// This software is licensed under the terms of the MIT License.
-// http://kjur.github.com/jsrsasign/license
-//
-// The above copyright and license notice shall be 
-// included in all copies or substantial portions of the Software.
-// 
-
-// Depends:
-//   base64.js
-//   rsa.js
-//   asn1hex.js
-
-function _x509_pemToBase64(sCertPEM) {
-  var s = sCertPEM;
-  s = s.replace("-----BEGIN CERTIFICATE-----", "");
-  s = s.replace("-----END CERTIFICATE-----", "");
-  s = s.replace(/[ \n]+/g, "");
-  return s;
-}
-
-function _x509_pemToHex(sCertPEM) {
-  var b64Cert = _x509_pemToBase64(sCertPEM);
-  var hCert = b64tohex(b64Cert);
-  return hCert;
-}
-
-function _x509_getHexTbsCertificateFromCert(hCert) {
-  var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
-  return pTbsCert;
-}
-
-// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
-// NOTE: v1 and v3 supported
-function _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert) {
-  var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
-  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert); 
-  if (a.length < 1) return -1;
-  if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
-    if (a.length < 6) return -1;
-    return a[6];
-  } else {
-    if (a.length < 5) return -1;
-    return a[5];
-  }
-}
-
-// NOTE: Without BITSTRING encapsulation.
-// If pInfo is supplied, it is the position in hCert of the SubjectPublicKeyInfo.
-function _x509_getSubjectPublicKeyPosFromCertHex(hCert, pInfo) {
-  if (pInfo == null)
-      pInfo = _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert);
-  if (pInfo == -1) return -1;    
-  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo); 
-  
-  if (a.length != 2) return -1;
-  var pBitString = a[1];
-  if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
-  var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
-
-  if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
-  return pBitStringV + 2;
-}
-
-// If p is supplied, it is the public key position in hCert.
-function _x509_getPublicKeyHexArrayFromCertHex(hCert, p) {
-  if (p == null)
-      p = _x509_getSubjectPublicKeyPosFromCertHex(hCert);
-  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 
-  //var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a[3]); 
-  if(LOG>4){
-	  console.log('a is now');
-	  console.log(a);
-  }
-  
-  //if (a.length != 2) return [];
-  if (a.length < 2) return [];
-
-  var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
-  var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
-  if (hN != null && hE != null) {
-    return [hN, hE];
-  } else {
-    return [];
-  }
-}
-
-function _x509_getPublicKeyHexArrayFromCertPEM(sCertPEM) {
-  var hCert = _x509_pemToHex(sCertPEM);
-  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
-  return a;
-}
-
-// ===== get basic fields from hex =====================================
-/**
- * get hexadecimal string of serialNumber field of certificate.<br/>
- * @name getSerialNumberHex
- * @memberOf X509#
- * @function
- */
-function _x509_getSerialNumberHex() {
-  return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
-}
+ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) {
+    var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
+    if (idx === undefined) {
+        throw "can't find nthList object";
+    }
+    if (checkingTag !== undefined) {
+        if (h.substr(idx, 2) != checkingTag) {
+            throw "checking tag doesn't match: " + 
+                h.substr(idx,2) + "!=" + checkingTag;
+        }
+    }
+    return this.getHexOfV_AtObj(h, idx);
+};
 
 /**
- * get hexadecimal string of issuer field of certificate.<br/>
- * @name getIssuerHex
- * @memberOf X509#
+ * get OID string from hexadecimal encoded value
+ * @name hextooidstr
+ * @memberOf ASN1HEX
  * @function
+ * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value
+ * @return {String} OID string (ex. '1.2.3.4.567')
+ * @since asn1hex 1.1.5
  */
-function _x509_getIssuerHex() {
-  return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
-}
+ASN1HEX.hextooidstr = function(hex) {
+    var zeroPadding = function(s, len) {
+        if (s.length >= len) return s;
+        return new Array(len - s.length + 1).join('0') + s;
+    };
+
+    var a = [];
+
+    // a[0], a[1]
+    var hex0 = hex.substr(0, 2);
+    var i0 = parseInt(hex0, 16);
+    a[0] = new String(Math.floor(i0 / 40));
+    a[1] = new String(i0 % 40);
+
+    // a[2]..a[n]
+   var hex1 = hex.substr(2);
+    var b = [];
+    for (var i = 0; i < hex1.length / 2; i++) {
+    b.push(parseInt(hex1.substr(i * 2, 2), 16));
+    }
+    var c = [];
+    var cbin = "";
+    for (var i = 0; i < b.length; i++) {
+        if (b[i] & 0x80) {
+            cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
+        } else {
+            cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
+            c.push(new String(parseInt(cbin, 2)));
+            cbin = "";
+        }
+    }
+
+    var s = a.join(".");
+    if (c.length > 0) s = s + "." + c.join(".");
+    return s;
+};
 
 /**
- * get string of issuer field of certificate.<br/>
- * @name getIssuerString
- * @memberOf X509#
+ * get string of simple ASN.1 dump from hexadecimal ASN.1 data
+ * @name dump
+ * @memberOf ASN1HEX
  * @function
+ * @param {String} hex hexadecmal string of ASN.1 data
+ * @param {Array} associative array of flags for dump (OPTION)
+ * @param {Number} idx string index for starting dump (OPTION)
+ * @param {String} indent string (OPTION)
+ * @return {String} string of simple ASN.1 dump
+ * @since jsrsasign 4.8.3 asn1hex 1.1.6
+ * @description
+ * This method will get an ASN.1 dump from
+ * hexadecmal string of ASN.1 DER encoded data.
+ * Here are features:
+ * <ul>
+ * <li>ommit long hexadecimal string</li>
+ * <li>dump encapsulated OCTET STRING (good for X.509v3 extensions)</li>
+ * <li>structured/primitive context specific tag support (i.e. [0], [3] ...)</li>
+ * <li>automatic decode for implicit primitive context specific tag 
+ * (good for X.509v3 extension value)
+ *   <ul>
+ *   <li>if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.</li>
+ *   <li>if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag
+ *   value will be encoded as utf8 string</li>
+ *   <li>otherwise it shows as hexadecimal string</li>
+ *   </ul>
+ * </li>
+ * </ul>
+ * @example
+ * // ASN.1 INTEGER
+ * ASN1HEX.dump('0203012345')
+ * &darr;
+ * INTEGER 012345
+ * // ASN.1 Object Identifier
+ * ASN1HEX.dump('06052b0e03021a')
+ * &darr;
+ * ObjectIdentifier sha1 (1 3 14 3 2 26)
+ * // ASN.1 SEQUENCE
+ * ASN1HEX.dump('3006020101020102')
+ * &darr;
+ * SEQUENCE
+ *   INTEGER 01
+ *   INTEGER 02
+ * // ASN.1 DUMP FOR X.509 CERTIFICATE
+ * ASN1HEX.dump(X509.pemToHex(certPEM))
+ * &darr;
+ * SEQUENCE
+ *   SEQUENCE
+ *     [0]
+ *       INTEGER 02
+ *     INTEGER 0c009310d206dbe337553580118ddc87
+ *     SEQUENCE
+ *       ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11)
+ *       NULL
+ *     SEQUENCE
+ *       SET
+ *         SEQUENCE
+ *           ObjectIdentifier countryName (2 5 4 6)
+ *           PrintableString 'US'
+ *             :
  */
-function _x509_getIssuerString() {
-  return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
-}
+ASN1HEX.dump = function(hex, flags, idx, indent) {
+    var _skipLongHex = function(hex, limitNumOctet) {
+	if (hex.length <= limitNumOctet * 2) {
+	    return hex;
+	} else {
+	    var s = hex.substr(0, limitNumOctet) + 
+		    "..(total " + hex.length / 2 + "bytes).." +
+		    hex.substr(hex.length - limitNumOctet, limitNumOctet);
+	    return s;
+	};
+    };
+
+    if (flags === undefined) flags = { "ommit_long_octet": 32 };
+    if (idx === undefined) idx = 0;
+    if (indent === undefined) indent = "";
+    var skipLongHex = flags.ommit_long_octet;
+
+    if (hex.substr(idx, 2) == "01") {
+	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	if (v == "00") {
+	    return indent + "BOOLEAN FALSE\n";
+	} else {
+	    return indent + "BOOLEAN TRUE\n";
+	}
+    }
+    if (hex.substr(idx, 2) == "02") {
+	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n";
+    }
+    if (hex.substr(idx, 2) == "03") {
+	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n";
+    }
+    if (hex.substr(idx, 2) == "04") {
+	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	if (ASN1HEX.isASN1HEX(v)) {
+	    var s = indent + "OCTETSTRING, encapsulates\n";
+	    s = s + ASN1HEX.dump(v, flags, 0, indent + "  ");
+	    return s;
+	} else {
+	    return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n";
+	}
+    }
+    if (hex.substr(idx, 2) == "05") {
+	return indent + "NULL\n";
+    }
+    if (hex.substr(idx, 2) == "06") {
+	var hV = ASN1HEX.getHexOfV_AtObj(hex, idx);
+        var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV);
+        var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
+	var oidSpc = oidDot.replace(/\./g, ' ');
+        if (oidName != '') {
+  	    return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n";
+	} else {
+  	    return indent + "ObjectIdentifier (" + oidSpc + ")\n";
+	}
+    }
+    if (hex.substr(idx, 2) == "0c") {
+	return indent + "UTF8String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
+    }
+    if (hex.substr(idx, 2) == "13") {
+	return indent + "PrintableString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
+    }
+    if (hex.substr(idx, 2) == "14") {
+	return indent + "TeletexString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
+    }
+    if (hex.substr(idx, 2) == "16") {
+	return indent + "IA5String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
+    }
+    if (hex.substr(idx, 2) == "17") {
+	return indent + "UTCTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n";
+    }
+    if (hex.substr(idx, 2) == "18") {
+	return indent + "GeneralizedTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n";
+    }
+    if (hex.substr(idx, 2) == "30") {
+	if (hex.substr(idx, 4) == "3000") {
+	    return indent + "SEQUENCE {}\n";
+	}
+
+	var s = indent + "SEQUENCE\n";
+	var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
+
+	var flagsTemp = flags;
+	
+	if ((aIdx.length == 2 || aIdx.length == 3) &&
+	    hex.substr(aIdx[0], 2) == "06" &&
+	    hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension
+	    var oidHex = ASN1HEX.getHexOfV_AtObj(hex, aIdx[0]);
+	    var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(oidHex);
+	    var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
+
+	    var flagsClone = JSON.parse(JSON.stringify(flags));
+	    flagsClone.x509ExtName = oidName;
+	    flagsTemp = flagsClone;
+	}
+	
+	for (var i = 0; i < aIdx.length; i++) {
+	    s = s + ASN1HEX.dump(hex, flagsTemp, aIdx[i], indent + "  ");
+	}
+	return s;
+    }
+    if (hex.substr(idx, 2) == "31") {
+	var s = indent + "SET\n";
+	var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
+	for (var i = 0; i < aIdx.length; i++) {
+	    s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + "  ");
+	}
+	return s;
+    }
+    var tag = parseInt(hex.substr(idx, 2), 16);
+    if ((tag & 128) != 0) { // context specific 
+	var tagNumber = tag & 31;
+	if ((tag & 32) != 0) { // structured tag
+	    var s = indent + "[" + tagNumber + "]\n";
+	    var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
+	    for (var i = 0; i < aIdx.length; i++) {
+		s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + "  ");
+	    }
+	    return s;
+	} else { // primitive tag
+	    var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	    if (v.substr(0, 8) == "68747470") { // http
+		v = hextoutf8(v);
+	    }
+	    if (flags.x509ExtName === "subjectAltName" &&
+		tagNumber == 2) {
+		v = hextoutf8(v);
+	    }
+	    
+	    var s = indent + "[" + tagNumber + "] " + v + "\n";
+	    return s;
+	}
+    }
+    return indent + "UNKNOWN(" + hex.substr(idx, 2) + ") " + ASN1HEX.getHexOfV_AtObj(hex, idx) + "\n";
+};
 
 /**
- * get hexadecimal string of subject field of certificate.<br/>
- * @name getSubjectHex
- * @memberOf X509#
+ * check wheather the string is ASN.1 hexadecimal string or not
+ * @name isASN1HEX
+ * @memberOf ASN1HEX
  * @function
+ * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not
+ * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false
+ * @since jsrsasign 4.8.3 asn1hex 1.1.6
+ * @description
+ * This method checks wheather the argument 'hex' is a hexadecimal string of
+ * ASN.1 data or not.
+ * @example
+ * ASN1HEX.isASN1HEX('0203012345') &rarr; true // PROPER ASN.1 INTEGER
+ * ASN1HEX.isASN1HEX('0203012345ff') &rarr; false // TOO LONG VALUE
+ * ASN1HEX.isASN1HEX('02030123') &rarr; false // TOO SHORT VALUE
+ * ASN1HEX.isASN1HEX('fa3bcd') &rarr; false // WRONG FOR ASN.1
  */
-function _x509_getSubjectHex() {
-  return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
-}
+ASN1HEX.isASN1HEX = function(hex) {
+    if (hex.length % 2 == 1) return false;
+
+    var intL = ASN1HEX.getIntOfL_AtObj(hex, 0);
+    var tV = hex.substr(0, 2);
+    var lV = ASN1HEX.getHexOfL_AtObj(hex, 0);
+    var hVLength = hex.length - tV.length - lV.length;
+    if (hVLength == intL * 2) return true;
+
+    return false;
+};
+
+exports.ASN1HEX = ASN1HEX;
+module.exports = exports;
+/*! x509-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/* 
+ * x509.js - X509 class to read subject public key from certificate.
+ *
+ * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license
+ *
+ * The above copyright and license notice shall be 
+ * included in all copies or substantial portions of the Software.
+ */
 
 /**
- * get string of subject field of certificate.<br/>
- * @name getSubjectString
- * @memberOf X509#
- * @function
+ * @fileOverview
+ * @name x509-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version x509 1.1.6 (2015-May-20)
+ * @since jsrsasign 1.x.x
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
  */
-function _x509_getSubjectString() {
-  return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
-}
 
-/**
- * get notBefore field string of certificate.<br/>
- * @name getNotBefore
- * @memberOf X509#
- * @function
+/*
+ * Depends:
+ *   base64.js
+ *   rsa.js
+ *   asn1hex.js
  */
-function _x509_getNotBefore() {
-  var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
-  s = s.replace(/(..)/g, "%$1");
-  s = decodeURIComponent(s);
-  return s;
-}
-
-/**
- * get notAfter field string of certificate.<br/>
- * @name getNotAfter
- * @memberOf X509#
- * @function
- */
-function _x509_getNotAfter() {
-  var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
-  s = s.replace(/(..)/g, "%$1");
-  s = decodeURIComponent(s);
-  return s;
-}
-
-// ===== read certificate =====================================
-
-_x509_DN_ATTRHEX = {
-    "0603550406": "C",
-    "060355040a": "O",
-    "060355040b": "OU",
-    "0603550403": "CN",
-    "0603550405": "SN",
-    "0603550408": "ST",
-    "0603550407": "L" };
-
-function _x509_hex2dn(hDN) {
-  var s = "";
-  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
-  for (var i = 0; i < a.length; i++) {
-    var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
-    s = s + "/" + _x509_hex2rdn(hRDN);
-  }
-  return s;
-}
-
-function _x509_hex2rdn(hRDN) {
-    var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
-    var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
-    var type = "";
-    try { type = _x509_DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
-    hValue = hValue.replace(/(..)/g, "%$1");
-    var value = decodeURIComponent(hValue);
-    return type + "=" + value;
-}
-
-// ===== read certificate =====================================
-
-
-/**
- * read PEM formatted X.509 certificate from string.<br/>
- * @name readCertPEM
- * @memberOf X509#
- * @function
- * @param {String} sCertPEM string for PEM formatted X.509 certificate
- */
-function _x509_readCertPEM(sCertPEM) {
-  var hCert = _x509_pemToHex(sCertPEM);
-  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
-  if(LOG>4){
-	  console.log('HEX VALUE IS ' + hCert);
-	  console.log('type of a' + typeof a);
-	  console.log('a VALUE IS ');
-	  console.log(a);
-	  console.log('a[0] VALUE IS ' + a[0]);
-	  console.log('a[1] VALUE IS ' + a[1]);
-  }
-  var rsa = new RSAKey();
-  rsa.setPublic(a[0], a[1]);
-  this.subjectPublicKeyRSA = rsa;
-  this.subjectPublicKeyRSA_hN = a[0];
-  this.subjectPublicKeyRSA_hE = a[1];
-  this.hex = hCert;
-}
-
-/**
- * read hex formatted X.509 certificate from string.
- * @name readCertHex
- * @memberOf X509#
- * @function
- * @param {String} hCert string for hex formatted X.509 certificate
- */
-function _x509_readCertHex(hCert) {
-  hCert = hCert.toLowerCase();
-  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
-  var rsa = new RSAKey();
-  rsa.setPublic(a[0], a[1]);
-  this.subjectPublicKeyRSA = rsa;
-  this.subjectPublicKeyRSA_hN = a[0];
-  this.subjectPublicKeyRSA_hE = a[1];
-  this.hex = hCert;
-}
-
-function _x509_readCertPEMWithoutRSAInit(sCertPEM) {
-  var hCert = _x509_pemToHex(sCertPEM);
-  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
-  this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
-  this.subjectPublicKeyRSA_hN = a[0];
-  this.subjectPublicKeyRSA_hE = a[1];
-  this.hex = hCert;
-}
 
 /**
  * X.509 certificate class.<br/>
@@ -6364,24 +5348,698 @@
  * @version 1.0.1 (08 May 2012)
  * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
  */
+
+var b64tohex = require('./base64.js').b64tohex;
+var RSAKey = require('./rsa.js').RSAKey;
+var ASN1HEX = require('./asn1hex-1.1.js').ASN1HEX;
+
 function X509() {
-  this.subjectPublicKeyRSA = null;
-  this.subjectPublicKeyRSA_hN = null;
-  this.subjectPublicKeyRSA_hE = null;
-  this.hex = null;
-}
+    this.subjectPublicKeyRSA = null;
+    this.subjectPublicKeyRSA_hN = null;
+    this.subjectPublicKeyRSA_hE = null;
+    this.hex = null;
 
-X509.prototype.readCertPEM = _x509_readCertPEM;
-X509.prototype.readCertHex = _x509_readCertHex;
-X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
-X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
-X509.prototype.getIssuerHex = _x509_getIssuerHex;
-X509.prototype.getSubjectHex = _x509_getSubjectHex;
-X509.prototype.getIssuerString = _x509_getIssuerString;
-X509.prototype.getSubjectString = _x509_getSubjectString;
-X509.prototype.getNotBefore = _x509_getNotBefore;
-X509.prototype.getNotAfter = _x509_getNotAfter;
+    // ===== get basic fields from hex =====================================
 
+    /**
+     * get hexadecimal string of serialNumber field of certificate.<br/>
+     * @name getSerialNumberHex
+     * @memberOf X509#
+     * @function
+     */
+    this.getSerialNumberHex = function() {
+        return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
+    };
+
+    /**
+     * get hexadecimal string of issuer field TLV of certificate.<br/>
+     * @name getIssuerHex
+     * @memberOf X509#
+     * @function
+     */
+    this.getIssuerHex = function() {
+        return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
+    };
+
+    /**
+     * get string of issuer field of certificate.<br/>
+     * @name getIssuerString
+     * @memberOf X509#
+     * @function
+     */
+    this.getIssuerString = function() {
+        return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
+    };
+
+    /**
+     * get hexadecimal string of subject field of certificate.<br/>
+     * @name getSubjectHex
+     * @memberOf X509#
+     * @function
+     */
+    this.getSubjectHex = function() {
+        return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
+    };
+
+    /**
+     * get string of subject field of certificate.<br/>
+     * @name getSubjectString
+     * @memberOf X509#
+     * @function
+     */
+    this.getSubjectString = function() {
+        return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
+    };
+
+    /**
+     * get notBefore field string of certificate.<br/>
+     * @name getNotBefore
+     * @memberOf X509#
+     * @function
+     */
+    this.getNotBefore = function() {
+        var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
+        s = s.replace(/(..)/g, "%$1");
+        s = decodeURIComponent(s);
+        return s;
+    };
+
+    /**
+     * get notAfter field string of certificate.<br/>
+     * @name getNotAfter
+     * @memberOf X509#
+     * @function
+     */
+    this.getNotAfter = function() {
+        var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
+        s = s.replace(/(..)/g, "%$1");
+        s = decodeURIComponent(s);
+        return s;
+    };
+
+    // ===== read certificate public key ==========================
+
+    // ===== read certificate =====================================
+    /**
+     * read PEM formatted X.509 certificate from string.<br/>
+     * @name readCertPEM
+     * @memberOf X509#
+     * @function
+     * @param {String} sCertPEM string for PEM formatted X.509 certificate
+     */
+    this.readCertPEM = function(sCertPEM) {
+        var hCert = X509.pemToHex(sCertPEM);
+        var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
+        var rsa = new RSAKey();
+        rsa.setPublic(a[0], a[1]);
+        this.subjectPublicKeyRSA = rsa;
+        this.subjectPublicKeyRSA_hN = a[0];
+        this.subjectPublicKeyRSA_hE = a[1];
+        this.hex = hCert;
+    };
+
+    this.readCertPEMWithoutRSAInit = function(sCertPEM) {
+        var hCert = X509.pemToHex(sCertPEM);
+        var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
+        this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
+        this.subjectPublicKeyRSA_hN = a[0];
+        this.subjectPublicKeyRSA_hE = a[1];
+        this.hex = hCert;
+    };
+};
+
+X509.pemToBase64 = function(sCertPEM) {
+    var s = sCertPEM;
+    s = s.replace("-----BEGIN CERTIFICATE-----", "");
+    s = s.replace("-----END CERTIFICATE-----", "");
+    s = s.replace(/[ \n]+/g, "");
+    return s;
+};
+
+X509.pemToHex = function(sCertPEM) {
+    var b64Cert = X509.pemToBase64(sCertPEM);
+    var hCert = b64tohex(b64Cert);
+    return hCert;
+};
+
+// NOTE: Without BITSTRING encapsulation.
+X509.getSubjectPublicKeyPosFromCertHex = function(hCert) {
+    var pInfo = X509.getSubjectPublicKeyInfoPosFromCertHex(hCert);
+    if (pInfo == -1) return -1;    
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo); 
+    if (a.length != 2) return -1;
+    var pBitString = a[1];
+    if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
+    var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
+    
+    if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
+    return pBitStringV + 2;
+};
+
+// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
+// NOTE: v1 and v3 supported
+X509.getSubjectPublicKeyInfoPosFromCertHex = function(hCert) {
+    var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert); 
+    if (a.length < 1) return -1;
+    if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
+        if (a.length < 6) return -1;
+        return a[6];
+    } else {
+        if (a.length < 5) return -1;
+        return a[5];
+    }
+};
+
+X509.getPublicKeyHexArrayFromCertHex = function(hCert) {
+    var p = X509.getSubjectPublicKeyPosFromCertHex(hCert);
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 
+    if (a.length != 2) return [];
+    var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
+    var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
+    if (hN != null && hE != null) {
+        return [hN, hE];
+    } else {
+        return [];
+    }
+};
+
+X509.getHexTbsCertificateFromCert = function(hCert) {
+    var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
+    return pTbsCert;
+};
+
+X509.getPublicKeyHexArrayFromCertPEM = function(sCertPEM) {
+    var hCert = X509.pemToHex(sCertPEM);
+    var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
+    return a;
+};
+
+X509.hex2dn = function(hDN) {
+    var s = "";
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
+    for (var i = 0; i < a.length; i++) {
+        var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
+        s = s + "/" + X509.hex2rdn(hRDN);
+    }
+    return s;
+};
+
+X509.hex2rdn = function(hRDN) {
+    var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
+    var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
+    var type = "";
+    try { type = X509.DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
+    hValue = hValue.replace(/(..)/g, "%$1");
+    var value = decodeURIComponent(hValue);
+    return type + "=" + value;
+};
+
+X509.DN_ATTRHEX = {
+    "0603550406": "C",
+    "060355040a": "O",
+    "060355040b": "OU",
+    "0603550403": "CN",
+    "0603550405": "SN",
+    "0603550408": "ST",
+    "0603550407": "L"
+};
+
+/**
+ * get RSAKey/ECDSA public key object from PEM certificate string
+ * @name getPublicKeyFromCertPEM
+ * @memberOf X509
+ * @function
+ * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
+ * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
+ * @since x509 1.1.1
+ * @description
+ * NOTE: DSA is also supported since x509 1.1.2.
+ */
+X509.getPublicKeyFromCertPEM = function(sCertPEM) {
+    var info = X509.getPublicKeyInfoPropOfCertPEM(sCertPEM);
+
+    if (info.algoid == "2a864886f70d010101") { // RSA
+        var aRSA = KEYUTIL.parsePublicRawRSAKeyHex(info.keyhex);
+        var key = new RSAKey();
+        key.setPublic(aRSA.n, aRSA.e);
+        return key;
+    } else if (info.algoid == "2a8648ce3d0201") { // ECC
+        var curveName = KJUR.crypto.OID.oidhex2name[info.algparam];
+        var key = new KJUR.crypto.ECDSA({'curve': curveName, 'info': info.keyhex});
+        key.setPublicKeyHex(info.keyhex);
+        return key;
+    } else if (info.algoid == "2a8648ce380401") { // DSA 1.2.840.10040.4.1
+        var p = ASN1HEX.getVbyList(info.algparam, 0, [0], "02");
+        var q = ASN1HEX.getVbyList(info.algparam, 0, [1], "02");
+        var g = ASN1HEX.getVbyList(info.algparam, 0, [2], "02");
+        var y = ASN1HEX.getHexOfV_AtObj(info.keyhex, 0);
+        y = y.substr(2);
+        var key = new KJUR.crypto.DSA();
+        key.setPublic(new BigInteger(p, 16),
+                      new BigInteger(q, 16),
+                      new BigInteger(g, 16),
+                      new BigInteger(y, 16));
+        return key;
+    } else {
+        throw "unsupported key";
+    }
+};
+
+/**
+ * get public key information from PEM certificate
+ * @name getPublicKeyInfoPropOfCertPEM
+ * @memberOf X509
+ * @function
+ * @param {String} sCertPEM string of PEM formatted certificate
+ * @return {Hash} hash of information for public key
+ * @since x509 1.1.1
+ * @description
+ * Resulted associative array has following properties:
+ * <ul>
+ * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li>
+ * <li>algparam - hexadecimal string of OID of ECC curve name or null</li>
+ * <li>keyhex - hexadecimal string of key in the certificate</li>
+ * </ul>
+ * @since x509 1.1.1
+ */
+X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
+    var result = {};
+    result.algparam = null;
+    var hCert = X509.pemToHex(sCertPEM);
+
+    // 1. Certificate ASN.1
+    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
+    if (a1.length != 3)
+        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
+
+    // 2. tbsCertificate
+    if (hCert.substr(a1[0], 2) != "30")
+        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
+
+    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
+
+    // 3. subjectPublicKeyInfo
+    if (a2.length < 7)
+        throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
+
+    var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[6]); 
+
+    if (a3.length != 2)
+        throw "malformed X.509 certificate PEM (code:004)"; // not AlgId and PubKey
+
+    // 4. AlgId
+    var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]); 
+
+    if (a4.length != 2)
+        throw "malformed X.509 certificate PEM (code:005)"; // not 2 item in AlgId
+
+    result.algoid = ASN1HEX.getHexOfV_AtObj(hCert, a4[0]);
+
+    if (hCert.substr(a4[1], 2) == "06") { // EC
+        result.algparam = ASN1HEX.getHexOfV_AtObj(hCert, a4[1]);
+    } else if (hCert.substr(a4[1], 2) == "30") { // DSA
+        result.algparam = ASN1HEX.getHexOfTLV_AtObj(hCert, a4[1]);
+    }
+
+    // 5. Public Key Hex
+    if (hCert.substr(a3[1], 2) != "03")
+        throw "malformed X.509 certificate PEM (code:006)"; // not bitstring
+
+    var unusedBitAndKeyHex = ASN1HEX.getHexOfV_AtObj(hCert, a3[1]);
+    result.keyhex = unusedBitAndKeyHex.substr(2);
+
+    return result;
+};
+
+/**
+ * get position of subjectPublicKeyInfo field from HEX certificate
+ * @name getPublicKeyInfoPosOfCertHEX
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of certificate
+ * @return {Integer} position in hexadecimal string
+ * @since x509 1.1.4
+ * @description
+ * get position for SubjectPublicKeyInfo field in the hexadecimal string of
+ * certificate.
+ */
+X509.getPublicKeyInfoPosOfCertHEX = function(hCert) {
+    // 1. Certificate ASN.1
+    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
+    if (a1.length != 3)
+        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
+
+    // 2. tbsCertificate
+    if (hCert.substr(a1[0], 2) != "30")
+        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
+
+    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
+
+    // 3. subjectPublicKeyInfo
+    if (a2.length < 7)
+        throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
+    
+    return a2[6];
+};
+
+/**
+ * get array of X.509 V3 extension value information in hex string of certificate
+ * @name getV3ExtInfoListOfCertHex
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @return {Array} array of result object by {@link X509.getV3ExtInfoListOfCertHex}
+ * @since x509 1.1.5
+ * @description
+ * This method will get all extension information of a X.509 certificate.
+ * Items of resulting array has following properties:
+ * <ul>
+ * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li>
+ * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li>
+ * <li>critical - critical flag value for this extension</li>
+ * <li>posV - index of ASN.1 TLV for the extension value.
+ * This is a position of a content of ENCAPSULATED OCTET STRING.</li>
+ * </ul>
+ * @example
+ * hCert = X509.pemToHex(certGithubPEM);
+ * a = X509.getV3ExtInfoListOfCertHex(hCert);
+ * // Then a will be an array of like following:
+ * [{posTLV: 1952, oid: "2.5.29.35", critical: false, posV: 1968},
+ *  {posTLV: 1974, oid: "2.5.29.19", critical: true, posV: 1986}, ...]
+ */
+X509.getV3ExtInfoListOfCertHex = function(hCert) {
+    // 1. Certificate ASN.1
+    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
+    if (a1.length != 3)
+        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
+
+    // 2. tbsCertificate
+    if (hCert.substr(a1[0], 2) != "30")
+        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
+
+    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
+
+    // 3. v3Extension EXPLICIT Tag [3]
+    // ver, seri, alg, iss, validity, subj, spki, (iui,) (sui,) ext
+    if (a2.length < 8)
+        throw "malformed X.509 certificate PEM (code:003)"; // tbsCert num field too short
+
+    if (hCert.substr(a2[7], 2) != "a3")
+        throw "malformed X.509 certificate PEM (code:004)"; // not [3] tag
+
+    var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[7]);
+    if (a3.length != 1)
+        throw "malformed X.509 certificate PEM (code:005)"; // [3]tag numChild!=1
+
+    // 4. v3Extension SEQUENCE
+    if (hCert.substr(a3[0], 2) != "30")
+        throw "malformed X.509 certificate PEM (code:006)"; // not SEQ
+
+    var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]);
+
+    // 5. v3Extension item position
+    var numExt = a4.length;
+    var aInfo = new Array(numExt);
+    for (var i = 0; i < numExt; i++) {
+	aInfo[i] = X509.getV3ExtItemInfo_AtObj(hCert, a4[i]);
+    }
+    return aInfo;
+};
+
+/**
+ * get X.509 V3 extension value information at the specified position
+ * @name getV3ExtItemInfo_AtObj
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @param {Integer} pos index of hexadecimal string for the extension
+ * @return {Object} properties for the extension
+ * @since x509 1.1.5
+ * @description
+ * This method will get some information of a X.509 V extension 
+ * which is referred by an index of hexadecimal string of X.509 
+ * certificate. 
+ * Resulting object has following properties:
+ * <ul>
+ * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li>
+ * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li>
+ * <li>critical - critical flag value for this extension</li>
+ * <li>posV - index of ASN.1 TLV for the extension value.
+ * This is a position of a content of ENCAPSULATED OCTET STRING.</li>
+ * </ul>
+ * This method is used by {@link X509.getV3ExtInfoListOfCertHex} internally.
+ */
+X509.getV3ExtItemInfo_AtObj = function(hCert, pos) {
+    var info = {};
+
+    // posTLV - extension TLV
+    info.posTLV = pos;
+
+    var a  = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos);
+    if (a.length != 2 && a.length != 3)
+        throw "malformed X.509v3 Ext (code:001)"; // oid,(critical,)val
+
+    // oid - extension OID
+    if (hCert.substr(a[0], 2) != "06")
+        throw "malformed X.509v3 Ext (code:002)"; // not OID "06"
+    var valueHex = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
+    info.oid = ASN1HEX.hextooidstr(valueHex); 
+
+    // critical - extension critical flag
+    info.critical = false; // critical false by default
+    if (a.length == 3) info.critical = true;
+
+    // posV - content TLV position of encapsulated
+    //        octet string of V3 extension value.
+    var posExtV = a[a.length - 1];
+    if (hCert.substr(posExtV, 2) != "04")
+        throw "malformed X.509v3 Ext (code:003)"; // not EncapOctet "04"
+    info.posV = ASN1HEX.getStartPosOfV_AtObj(hCert, posExtV);
+    
+    return info;
+};
+
+/**
+ * get X.509 V3 extension value ASN.1 TLV for specified oid or name
+ * @name getHexOfTLV_V3ExtValue
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
+ * @return {String} hexadecimal string of extension ASN.1 TLV
+ * @since x509 1.1.6
+ * @description
+ * This method will get X.509v3 extension value of ASN.1 TLV
+ * which is specifyed by extension name or oid. 
+ * @example
+ * hExtValue = X509.getHexOfTLV_V3ExtValue(hCert, "keyUsage");
+ * // hExtValue will be such like '030205a0'.
+ */
+X509.getHexOfTLV_V3ExtValue = function(hCert, oidOrName) {
+    var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName);
+    if (pos == -1) return '';
+    return ASN1HEX.getHexOfTLV_AtObj(hCert, pos);
+};
+
+/**
+ * get X.509 V3 extension value ASN.1 V for specified oid or name
+ * @name getHexOfV_V3ExtValue
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
+ * @return {String} hexadecimal string of extension ASN.1 TLV
+ * @since x509 1.1.6
+ * @description
+ * This method will get X.509v3 extension value of ASN.1 value
+ * which is specifyed by extension name or oid. 
+ * If there is no such extension in the certificate,
+ * it returns empty string (i.e. '').
+ * Available extension names and oids are defined
+ * in the {@link KJUR.asn1.x509.OID} class.
+ * @example
+ * hExtValue = X509.getHexOfV_V3ExtValue(hCert, "keyUsage");
+ * // hExtValue will be such like '05a0'.
+ */
+X509.getHexOfV_V3ExtValue = function(hCert, oidOrName) {
+    var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName);
+    if (pos == -1) return '';
+    return ASN1HEX.getHexOfV_AtObj(hCert, pos);
+};
+
+/**
+ * get index in the certificate hexa string for specified oid or name specified extension
+ * @name getPosOfTLV_V3ExtValue
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
+ * @return {Integer} index in the hexadecimal string of certficate for specified extension
+ * @since x509 1.1.6
+ * @description
+ * This method will get X.509v3 extension value of ASN.1 V(value)
+ * which is specifyed by extension name or oid. 
+ * If there is no such extension in the certificate,
+ * it returns empty string (i.e. '').
+ * Available extension names and oids are defined
+ * in the {@link KJUR.asn1.x509.OID} class.
+ * @example
+ * idx = X509.getPosOfV_V3ExtValue(hCert, "keyUsage");
+ * // The 'idx' will be index in the string for keyUsage value ASN.1 TLV.
+ */
+X509.getPosOfTLV_V3ExtValue = function(hCert, oidOrName) {
+    var oid = oidOrName;
+    if (! oidOrName.match(/^[0-9.]+$/)) oid = KJUR.asn1.x509.OID.name2oid(oidOrName);
+    if (oid == '') return -1;
+
+    var infoList = X509.getV3ExtInfoListOfCertHex(hCert);
+    for (var i = 0; i < infoList.length; i++) {
+	var info = infoList[i];
+	if (info.oid == oid) return info.posV;
+    }
+    return -1;
+};
+
+X509.KEYUSAGE_NAME = [
+    "digitalSignature",
+    "nonRepudiation",
+    "keyEncipherment",
+    "dataEncipherment",
+    "keyAgreement",
+    "keyCertSign",
+    "cRLSign",
+    "encipherOnly",
+    "decipherOnly"
+];
+
+/**
+ * get KeyUsage extension value as binary string in the certificate
+ * @name getExtKeyUsageBin
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @return {String} binary string of key usage bits (ex. '101')
+ * @since x509 1.1.6
+ * @description
+ * This method will get key usage extension value
+ * as binary string such like '101'.
+ * Key usage bits definition is in the RFC 5280.
+ * If there is no key usage extension in the certificate,
+ * it returns empty string (i.e. '').
+ * @example
+ * bKeyUsage = X509.getExtKeyUsageBin(hCert);
+ * // bKeyUsage will be such like '101'.
+ * // 1 - digitalSignature 
+ * // 0 - nonRepudiation
+ * // 1 - keyEncipherment
+ */
+X509.getExtKeyUsageBin = function(hCert) {
+    var hKeyUsage = X509.getHexOfV_V3ExtValue(hCert, "keyUsage");
+    if (hKeyUsage == '') return '';
+    if (hKeyUsage.length % 2 != 0 || hKeyUsage.length <= 2)
+	throw "malformed key usage value";
+    var unusedBits = parseInt(hKeyUsage.substr(0, 2));
+    var bKeyUsage = parseInt(hKeyUsage.substr(2), 16).toString(2);
+    return bKeyUsage.substr(0, bKeyUsage.length - unusedBits);
+};
+
+/**
+ * get KeyUsage extension value as names in the certificate
+ * @name getExtKeyUsageString
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @return {String} comma separated string of key usage
+ * @since x509 1.1.6
+ * @description
+ * This method will get key usage extension value
+ * as comma separated string of usage names.
+ * If there is no key usage extension in the certificate,
+ * it returns empty string (i.e. '').
+ * @example
+ * sKeyUsage = X509.getExtKeyUsageString(hCert);
+ * // sKeyUsage will be such like 'digitalSignature,keyEncipherment'.
+ */
+X509.getExtKeyUsageString = function(hCert) {
+    var bKeyUsage = X509.getExtKeyUsageBin(hCert);
+    var a = new Array();
+    for (var i = 0; i < bKeyUsage.length; i++) {
+	if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]);
+    }
+    return a.join(",");
+};
+
+/**
+ * get AuthorityInfoAccess extension value in the certificate as associative array
+ * @name getExtAIAInfo
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @return {Object} associative array of AIA extension properties
+ * @since x509 1.1.6
+ * @description
+ * This method will get authority info access value
+ * as associate array which has following properties:
+ * <ul>
+ * <li>ocsp - array of string for OCSP responder URL</li>
+ * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li>
+ * </ul>
+ * If there is no key usage extension in the certificate,
+ * it returns null;
+ * @example
+ * oAIA = X509.getExtAIAInfo(hCert);
+ * // result will be such like:
+ * // oAIA.ocsp = ["http://ocsp.foo.com"];
+ * // oAIA.caissuer = ["http://rep.foo.com/aaa.p8m"];
+ */
+X509.getExtAIAInfo = function(hCert) {
+    var result = {};
+    result.ocsp = [];
+    result.caissuer = [];
+    var pos1 = X509.getPosOfTLV_V3ExtValue(hCert, "authorityInfoAccess");
+    if (pos1 == -1) return null;
+    if (hCert.substr(pos1, 2) != "30") // extnValue SEQUENCE
+	throw "malformed AIA Extn Value";
+    
+    var posAccDescList = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos1);
+    for (var i = 0; i < posAccDescList.length; i++) {
+	var p = posAccDescList[i];
+	var posAccDescChild = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
+	if (posAccDescChild.length != 2)
+	    throw "malformed AccessDescription of AIA Extn";
+	var pOID = posAccDescChild[0];
+	var pName = posAccDescChild[1];
+	if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073001") {
+	    if (hCert.substr(pName, 2) == "86") {
+		result.ocsp.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName)));
+	    }
+	}
+	if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073002") {
+	    if (hCert.substr(pName, 2) == "86") {
+		result.caissuer.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName)));
+	    }
+	}
+    }
+    return result;
+};
+
+/*
+  X509.prototype.readCertPEM = _x509_readCertPEM;
+  X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
+  X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
+  X509.prototype.getIssuerHex = _x509_getIssuerHex;
+  X509.prototype.getSubjectHex = _x509_getSubjectHex;
+  X509.prototype.getIssuerString = _x509_getIssuerString;
+  X509.prototype.getSubjectString = _x509_getSubjectString;
+  X509.prototype.getNotBefore = _x509_getNotBefore;
+  X509.prototype.getNotAfter = _x509_getNotAfter;
+*/
+
+exports.X509 = X509;
+module.exports = exports;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
 // Copyright (c) 2005  Tom Wu
 // All Rights Reserved.
 // See "LICENSE" for details.
@@ -6396,7 +6054,7 @@
 var j_lm = ((canary&0xffffff)==0xefcafe);
 
 // (public) Constructor
-function BigInteger(a,b,c) {
+var BigInteger = function BigInteger(a,b,c) {
   if(a != null)
     if("number" == typeof a) this.fromNumber(a,b,c);
     else if(b == null && "string" != typeof a) this.fromString(a,256);
@@ -6502,7 +6160,7 @@
   this.t = 1;
   this.s = (x<0)?-1:0;
   if(x > 0) this[0] = x;
-  else if(x < -1) this[0] = x+DV;
+  else if(x < -1) this[0] = x+this.DV;
   else this.t = 0;
 }
 
@@ -6596,7 +6254,7 @@
   if(r != 0) return r;
   var i = this.t;
   r = i-a.t;
-  if(r != 0) return r;
+  if(r != 0) return (this.s<0)?-r:r;
   while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
   return 0;
 }
@@ -6941,6 +6599,8 @@
 // "constants"
 BigInteger.ZERO = nbv(0);
 BigInteger.ONE = nbv(1);
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
 // Copyright (c) 2005-2009  Tom Wu
 // All Rights Reserved.
 // See "LICENSE" for details.
@@ -6948,6 +6608,7 @@
 // Extended JavaScript BN functions, required for RSA private ops.
 
 // Version 1.1: new BigInteger("0", 10) returns "proper" zero
+// Version 1.2: square() API, isProbablePrime fix
 
 // (public)
 function bnClone() { var r = nbi(); this.copyTo(r); return r; }
@@ -7233,6 +6894,9 @@
 // (public) this * a
 function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
 
+// (public) this^2
+function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
+
 // (public) this / a
 function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
 
@@ -7485,7 +7149,7 @@
   if(d.signum() < 0) return d.add(m); else return d;
 }
 
-var 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];
+var 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,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
 var lplim = (1<<26)/lowprimes[lowprimes.length-1];
 
 // (public) test primality with certainty >= 1-.5^t
@@ -7517,7 +7181,8 @@
   if(t > lowprimes.length) t = lowprimes.length;
   var a = nbi();
   for(var i = 0; i < t; ++i) {
-    a.fromInt(lowprimes[i]);
+    //Pick bases at random, instead of starting at 2
+    a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
     var y = a.modPow(r,this);
     if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
       var j = 1;
@@ -7581,6 +7246,9 @@
 BigInteger.prototype.gcd = bnGCD;
 BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
 
+// JSBN-specific extension
+BigInteger.prototype.square = bnSquare;
+
 // BigInteger interfaces not implemented in jsbn:
 
 // BigInteger(int signum, byte[] magnitude)
@@ -7589,623 +7257,30318 @@
 // int hashCode()
 // long longValue()
 // static BigInteger valueOf(long val)
+
+exports.BigInteger = BigInteger;
+module.exports = exports;
 /**
- * @author: Meki Cherkaoui, Jeff Thompson, Wentao Shang
- * See COPYING for copyright and distribution information.
- * This class represents the top-level object for communicating with an NDN host.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
  */
 
-var LOG = 0;
+/** @ignore */
+var ASN1HEX = require('../contrib/securityLib/asn1hex-1.1.js').ASN1HEX /** @ignore */
+var KJUR = require('../contrib/securityLib/crypto-1.0.js').KJUR /** @ignore */
+var RSAKey = require('../contrib/securityLib/rsasign-1.2.js').RSAKey /** @ignore */
+var b64tohex = require('../contrib/securityLib/base64.js').b64tohex
 
-/**
- * settings is an associative array with the following defaults:
- * {
- *   getTransport: function() { return new WebSocketTransport(); },
- *   getHostAndPort: transport.defaultGetHostAndPort,
- *   host: null, // If null, use getHostAndPort when connecting.
- *   port: 9696,
- *   onopen: function() { if (LOG > 3) console.log("NDN connection established."); },
- *   onclose: function() { if (LOG > 3) console.log("NDN connection closed."); },
- *   verify: true // If false, don't verify and call upcall with Closure.UPCALL_CONTENT_UNVERIFIED.
- * }
- *
- * getHostAndPort is a function, on each call it returns a new { host: host, port: port } or
- *   null if there are no more hosts.
- *
- * This throws an exception if NDN.supported is false.
- */
-var NDN = function NDN(settings) {
-    if (!NDN.supported)
-        throw new Error("The necessary JavaScript support is not available on this platform.");
+// Library namespace
+/** @ignore */
+var ndn = ndn || {};
 
-    settings = (settings || {});
-    var getTransport = (settings.getTransport || function() { return new WebSocketTransport(); });
-    this.transport = getTransport();
-    this.getHostAndPort = (settings.getHostAndPort || this.transport.defaultGetHostAndPort);
-	this.host = (settings.host !== undefined ? settings.host : null);
-	this.port = (settings.port || 9696);
-    this.readyStatus = NDN.UNOPEN;
-    this.verify = (settings.verify !== undefined ? settings.verify : true);
-    // Event handler
-    this.onopen = (settings.onopen || function() { if (LOG > 3) console.log("NDN connection established."); });
-    this.onclose = (settings.onclose || function() { if (LOG > 3) console.log("NDN connection closed."); });
-	this.ndndid = null;
+/** @ignore */
+var exports = ndn;
+
+// Factory method to create hasher objects
+exports.createHash = function(alg)
+{
+  if (alg != 'sha256')
+    throw new Error('createHash: unsupported algorithm.');
+
+  var obj = {};
+
+  obj.md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "cryptojs"});
+
+  obj.update = function(buf) {
+    this.md.updateHex(buf.toString('hex'));
+  };
+
+  obj.digest = function(encoding) {
+    var hexDigest = this.md.digest();
+    if (encoding == 'hex')
+      return hexDigest;
+    else if (encoding == 'base64')
+      return new Buffer(hexDigest, 'hex').toString('base64');
+    else
+      return new Buffer(hexDigest, 'hex');
+  };
+
+  return obj;
 };
 
-NDN.UNOPEN = 0;  // created but not opened yet
-NDN.OPENED = 1;  // connection to ndnd opened
-NDN.CLOSED = 2;  // connection to ndnd closed
+// Factory method to create HMAC objects.
+exports.createHmac = function(algorithm, key)
+{
+  if (algorithm !== 'sha256')
+    throw new Error('createHmac: unsupported algorithm.');
+
+  var obj = {};
+
+  obj.md = new KJUR.crypto.Mac({alg: "HmacSHA256", pass: {hex: key.toString('hex')}});
+
+  obj.update = function(buf) {
+    this.md.updateHex(buf.toString('hex'));
+  };
+
+  obj.digest = function(encoding) {
+    var hexDigest = this.md.doFinal();
+    if (encoding == 'hex')
+      return hexDigest;
+    else if (encoding == 'base64')
+      return new Buffer(hexDigest, 'hex').toString('base64');
+    else
+      return new Buffer(hexDigest, 'hex');
+  };
+
+  return obj;
+};
+
+// Factory method to create RSA signer objects
+exports.createSign = function(alg)
+{
+  if (alg != 'RSA-SHA256')
+    throw new Error('createSign: unsupported algorithm.');
+
+  var obj = {};
+
+  obj.arr = [];
+
+  obj.update = function(buf) {
+    this.arr.push(buf);
+  };
+
+  obj.sign = function(keypem) {
+    var rsa = new RSAKey();
+    rsa.readPrivateKeyFromPEMString(keypem);
+    var signer = new KJUR.crypto.Signature({alg: "SHA256withRSA", prov: "cryptojs/jsrsa"});
+    signer.initSign(rsa);
+    for (var i = 0; i < this.arr.length; ++i)
+      signer.updateHex(this.arr[i].toString('hex'));
+
+    return new Buffer(signer.sign(), 'hex');
+  };
+
+  return obj;
+};
+
+// Factory method to create RSA verifier objects
+exports.createVerify = function(alg)
+{
+  if (alg != 'RSA-SHA256')
+    throw new Error('createSign: unsupported algorithm.');
+
+  var obj = {};
+
+  obj.arr = [];
+
+  obj.update = function(buf) {
+    this.arr.push(buf);
+  };
+
+  var getSubjectPublicKeyPosFromHex = function(hPub) {
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hPub, 0);
+    if (a.length != 2)
+      return -1;
+    var pBitString = a[1];
+    if (hPub.substring(pBitString, pBitString + 2) != '03')
+      return -1;
+    var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hPub, pBitString);
+    if (hPub.substring(pBitStringV, pBitStringV + 2) != '00')
+      return -1;
+    return pBitStringV + 2;
+  };
+
+  var publicKeyPemToDer = function(publicKeyPem) {
+    // Remove the '-----XXX-----' from the beginning and the end of the public
+    // key and also remove any \n in the public key string.
+    var lines = publicKeyPem.split('\n');
+    var pub = "";
+    for (var i = 1; i < lines.length - 1; i++)
+      pub += lines[i];
+    return new Buffer(pub, 'base64');
+  }
+
+  var readPublicDER = function(pub_der) {
+    var hex = pub_der.toString('hex');
+    var p = getSubjectPublicKeyPosFromHex(hex);
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hex, p);
+    if (a.length != 2)
+      return null;
+    var hN = ASN1HEX.getHexOfV_AtObj(hex, a[0]);
+    var hE = ASN1HEX.getHexOfV_AtObj(hex, a[1]);
+    var rsaKey = new RSAKey();
+    rsaKey.setPublic(hN, hE);
+    return rsaKey;
+  };
+
+  obj.verify = function(keypem, sig) {
+    var rsa = readPublicDER(publicKeyPemToDer(keypem));
+    var signer = new KJUR.crypto.Signature({alg: "SHA256withRSA", prov: "cryptojs/jsrsa"});
+    signer.initVerifyByPublicKey(rsa);
+    for (var i = 0; i < this.arr.length; i++)
+      signer.updateHex(this.arr[i].toString('hex'));
+    var hSig = sig.toString('hex');
+    return signer.verify(hSig);
+  };
+
+  return obj;
+};
+
+exports.randomBytes = function(size)
+{
+  // TODO: Use a cryptographic random number generator.
+  var result = new Buffer(size);
+  for (var i = 0; i < size; ++i)
+    result[i] = Math.floor(Math.random() * 256);
+  return result;
+};
+
+// contrib/feross/buffer.js needs base64.toByteArray. Define it here so that
+// we don't have to include the entire base64 module.
+exports.toByteArray = function(str) {
+  var hex = b64tohex(str);
+  var result = [];
+  hex.replace(/(..)/g, function(ss) {
+    result.push(parseInt(ss, 16));
+  });
+  return result;
+};
+
+module.exports = exports
+// After this we include contrib/feross/buffer.js to define the Buffer class.
+var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var base64js = {};
+
+;(function (exports) {
+	'use strict';
+
+  var Arr = (typeof Uint8Array !== 'undefined')
+    ? Uint8Array
+    : Array
+
+	var PLUS   = '+'.charCodeAt(0)
+	var SLASH  = '/'.charCodeAt(0)
+	var NUMBER = '0'.charCodeAt(0)
+	var LOWER  = 'a'.charCodeAt(0)
+	var UPPER  = 'A'.charCodeAt(0)
+
+	function decode (elt) {
+		var code = elt.charCodeAt(0)
+		if (code === PLUS)
+			return 62 // '+'
+		if (code === SLASH)
+			return 63 // '/'
+		if (code < NUMBER)
+			return -1 //no match
+		if (code < NUMBER + 10)
+			return code - NUMBER + 26 + 26
+		if (code < UPPER + 26)
+			return code - UPPER
+		if (code < LOWER + 26)
+			return code - LOWER + 26
+	}
+
+	function b64ToByteArray (b64) {
+		var i, j, l, tmp, placeHolders, arr
+
+		if (b64.length % 4 > 0) {
+			throw new Error('Invalid string. Length must be a multiple of 4')
+		}
+
+		// the number of equal signs (place holders)
+		// if there are two placeholders, than the two characters before it
+		// represent one byte
+		// if there is only one, then the three characters before it represent 2 bytes
+		// this is just a cheap hack to not do indexOf twice
+		var len = b64.length
+		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
+
+		// base64 is 4/3 + up to two characters of the original data
+		arr = new Arr(b64.length * 3 / 4 - placeHolders)
+
+		// if there are placeholders, only get up to the last complete 4 chars
+		l = placeHolders > 0 ? b64.length - 4 : b64.length
+
+		var L = 0
+
+		function push (v) {
+			arr[L++] = v
+		}
+
+		for (i = 0, j = 0; i < l; i += 4, j += 3) {
+			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
+			push((tmp & 0xFF0000) >> 16)
+			push((tmp & 0xFF00) >> 8)
+			push(tmp & 0xFF)
+		}
+
+		if (placeHolders === 2) {
+			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
+			push(tmp & 0xFF)
+		} else if (placeHolders === 1) {
+			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
+			push((tmp >> 8) & 0xFF)
+			push(tmp & 0xFF)
+		}
+
+		return arr
+	}
+
+	function uint8ToBase64 (uint8) {
+		var i,
+			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
+			output = "",
+			temp, length
+
+		function encode (num) {
+			return lookup.charAt(num)
+		}
+
+		function tripletToBase64 (num) {
+			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
+		}
+
+		// go through the array every three bytes, we'll deal with trailing stuff later
+		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
+			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
+			output += tripletToBase64(temp)
+		}
+
+		// pad the end with zeros, but make sure to not forget the extra bytes
+		switch (extraBytes) {
+			case 1:
+				temp = uint8[uint8.length - 1]
+				output += encode(temp >> 2)
+				output += encode((temp << 4) & 0x3F)
+				output += '=='
+				break
+			case 2:
+				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
+				output += encode(temp >> 10)
+				output += encode((temp >> 4) & 0x3F)
+				output += encode((temp << 2) & 0x3F)
+				output += '='
+				break
+		}
+
+		return output
+	}
+
+	exports.toByteArray = b64ToByteArray
+	exports.fromByteArray = uint8ToBase64
+})(base64js);
+var ieee = {};
+
+ieee.read = function(buffer, offset, isLE, mLen, nBytes) {
+  var e, m,
+      eLen = nBytes * 8 - mLen - 1,
+      eMax = (1 << eLen) - 1,
+      eBias = eMax >> 1,
+      nBits = -7,
+      i = isLE ? (nBytes - 1) : 0,
+      d = isLE ? -1 : 1,
+      s = buffer[offset + i];
+
+  i += d;
+
+  e = s & ((1 << (-nBits)) - 1);
+  s >>= (-nBits);
+  nBits += eLen;
+  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
+
+  m = e & ((1 << (-nBits)) - 1);
+  e >>= (-nBits);
+  nBits += mLen;
+  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
+
+  if (e === 0) {
+    e = 1 - eBias;
+  } else if (e === eMax) {
+    return m ? NaN : ((s ? -1 : 1) * Infinity);
+  } else {
+    m = m + Math.pow(2, mLen);
+    e = e - eBias;
+  }
+  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
+};
+
+ieee.write = function(buffer, value, offset, isLE, mLen, nBytes) {
+  var e, m, c,
+      eLen = nBytes * 8 - mLen - 1,
+      eMax = (1 << eLen) - 1,
+      eBias = eMax >> 1,
+      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
+      i = isLE ? 0 : (nBytes - 1),
+      d = isLE ? 1 : -1,
+      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
+
+  value = Math.abs(value);
+
+  if (isNaN(value) || value === Infinity) {
+    m = isNaN(value) ? 1 : 0;
+    e = eMax;
+  } else {
+    e = Math.floor(Math.log(value) / Math.LN2);
+    if (value * (c = Math.pow(2, -e)) < 1) {
+      e--;
+      c *= 2;
+    }
+    if (e + eBias >= 1) {
+      value += rt / c;
+    } else {
+      value += rt * Math.pow(2, 1 - eBias);
+    }
+    if (value * c >= 2) {
+      e++;
+      c /= 2;
+    }
+
+    if (e + eBias >= eMax) {
+      m = 0;
+      e = eMax;
+    } else if (e + eBias >= 1) {
+      m = (value * c - 1) * Math.pow(2, mLen);
+      e = e + eBias;
+    } else {
+      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
+      e = 0;
+    }
+  }
+
+  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
+
+  e = (e << mLen) | m;
+  eLen += mLen;
+  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
+
+  buffer[offset + i - d] |= s * 128;
+};
+
+exports.ieee = ieee;
+/**
+ * The buffer module from node.js, for the browser.
+ * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+ *
+ * Copyright (C) 2013 Feross Aboukhadijeh, and other contributors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * @license  MIT
+ */
+
+var base64 = base64js;
+var ieee754 = require('./ieee754.js').ieee
+
+exports.Buffer = Buffer
+exports.SlowBuffer = Buffer
+exports.INSPECT_MAX_BYTES = 50
+Buffer.poolSize = 8192
+
+/**
+ * If `Buffer._useTypedArrays`:
+ *   === true    Use Uint8Array implementation (fastest)
+ *   === false   Use Object implementation (compatible down to IE6)
+ */
+Buffer._useTypedArrays = (function () {
+  // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+,
+  // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding
+  // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support
+  // because we need to be able to add all the node Buffer API methods. This is an issue
+  // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438
+  try {
+    var buf = new ArrayBuffer(0)
+    var arr = new Uint8Array(buf)
+    arr.foo = function () { return 42 }
+    return 42 === arr.foo() &&
+        typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray`
+  } catch (e) {
+    return false
+  }
+})()
+
+/**
+ * Class: Buffer
+ * =============
+ *
+ * The Buffer constructor returns instances of `Uint8Array` that are augmented
+ * with function properties for all the node `Buffer` API functions. We use
+ * `Uint8Array` so that square bracket notation works as expected -- it returns
+ * a single octet.
+ *
+ * By augmenting the instances, we can avoid modifying the `Uint8Array`
+ * prototype.
+ */
+function Buffer (subject, encoding, noZero) {
+  if (!(this instanceof Buffer))
+    return new Buffer(subject, encoding, noZero)
+
+  var type = typeof subject
+
+  // Workaround: node's base64 implementation allows for non-padded strings
+  // while base64-js does not.
+  if (encoding === 'base64' && type === 'string') {
+    subject = Buffer.stringtrim(subject)
+    while (subject.length % 4 !== 0) {
+      subject = subject + '='
+    }
+  }
+
+  // Find the length
+  var length
+  if (type === 'number')
+    length = Buffer.coerce(subject)
+  else if (type === 'string')
+    length = Buffer.byteLength(subject, encoding)
+  else if (type === 'object')
+    length = Buffer.coerce(subject.length) // assume that object is array-like
+  else
+    throw new Error('First argument needs to be a number, array or string.')
+
+  var buf
+  if (Buffer._useTypedArrays) {
+    // Preferred: Return an augmented `Uint8Array` instance for best performance
+    buf = Buffer._augment(new Uint8Array(length))
+  } else {
+    // Fallback: Return THIS instance of Buffer (created by `new`)
+    buf = this
+    buf.length = length
+    buf._isBuffer = true
+  }
+
+  var i
+  if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') {
+    // Speed optimization -- use set if we're copying from a typed array
+    buf._set(subject)
+  } else if (Buffer.isArrayish(subject)) {
+    // Treat array-ish objects as a byte array
+    if (Buffer.isBuffer(subject)) {
+      for (i = 0; i < length; i++)
+        buf[i] = subject.readUInt8(i)
+    } else {
+      for (i = 0; i < length; i++)
+        buf[i] = ((subject[i] % 256) + 256) % 256
+    }
+  } else if (type === 'string') {
+    buf.write(subject, 0, encoding)
+  } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) {
+    for (i = 0; i < length; i++) {
+      buf[i] = 0
+    }
+  }
+
+  return buf
+}
+
+// STATIC METHODS
+// ==============
+
+Buffer.isEncoding = function (encoding) {
+  switch (String(encoding).toLowerCase()) {
+    case 'hex':
+    case 'utf8':
+    case 'utf-8':
+    case 'ascii':
+    case 'binary':
+    case 'base64':
+    case 'raw':
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      return true
+    default:
+      return false
+  }
+}
+
+Buffer.isBuffer = function (b) {
+  return !!(b !== null && b !== undefined && b._isBuffer)
+}
+
+Buffer.byteLength = function (str, encoding) {
+  var ret
+  str = str.toString()
+  switch (encoding || 'utf8') {
+    case 'hex':
+      ret = str.length / 2
+      break
+    case 'utf8':
+    case 'utf-8':
+      ret = Buffer.utf8ToBytes(str).length
+      break
+    case 'ascii':
+    case 'binary':
+    case 'raw':
+      ret = str.length
+      break
+    case 'base64':
+      ret = Buffer.base64ToBytes(str).length
+      break
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      ret = str.length * 2
+      break
+    default:
+      throw new Error('Unknown encoding')
+  }
+  return ret
+}
+
+Buffer.concat = function (list, totalLength) {
+  Buffer.assert(Buffer.isArray(list), 'Usage: Buffer.concat(list[, length])')
+
+  if (list.length === 0) {
+    return new Buffer(0)
+  } else if (list.length === 1) {
+    return list[0]
+  }
+
+  var i
+  if (totalLength === undefined) {
+    totalLength = 0
+    for (i = 0; i < list.length; i++) {
+      totalLength += list[i].length
+    }
+  }
+
+  var buf = new Buffer(totalLength)
+  var pos = 0
+  for (i = 0; i < list.length; i++) {
+    var item = list[i]
+    item.copy(buf, pos)
+    pos += item.length
+  }
+  return buf
+}
+
+Buffer.compare = function (a, b) {
+  Buffer.assert(Buffer.isBuffer(a) && Buffer.isBuffer(b), 'Arguments must be Buffers')
+  var x = a.length
+  var y = b.length
+  for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}
+  if (i !== len) {
+    x = a[i]
+    y = b[i]
+  }
+  if (x < y) {
+    return -1
+  }
+  if (y < x) {
+    return 1
+  }
+  return 0
+}
+
+// BUFFER INSTANCE METHODS
+// =======================
+
+Buffer.hexWrite = function(buf, string, offset, length) {
+  offset = Number(offset) || 0
+  var remaining = buf.length - offset
+  if (!length) {
+    length = remaining
+  } else {
+    length = Number(length)
+    if (length > remaining) {
+      length = remaining
+    }
+  }
+
+  // must be an even number of digits
+  var strLen = string.length
+  Buffer.assert(strLen % 2 === 0, 'Invalid hex string')
+
+  if (length > strLen / 2) {
+    length = strLen / 2
+  }
+  for (var i = 0; i < length; i++) {
+    var b = parseInt(string.substr(i * 2, 2), 16)
+    Buffer.assert(!isNaN(b), 'Invalid hex string')
+    buf[offset + i] = b
+  }
+  return i
+}
+
+Buffer.utf8Write = function(buf, string, offset, length) {
+  var charsWritten = Buffer.blitBuffer(Buffer.utf8ToBytes(string), buf, offset, length)
+  return charsWritten
+}
+
+Buffer.asciiWrite = function(buf, string, offset, length) {
+  var charsWritten = Buffer.blitBuffer(Buffer.asciiToBytes(string), buf, offset, length)
+  return charsWritten
+}
+
+Buffer.binaryWrite = function(buf, string, offset, length) {
+  return Buffer.asciiWrite(buf, string, offset, length)
+}
+
+Buffer.base64Write = function(buf, string, offset, length) {
+  var charsWritten = Buffer.blitBuffer(Buffer.base64ToBytes(string), buf, offset, length)
+  return charsWritten
+}
+
+Buffer.utf16leWrite = function(buf, string, offset, length) {
+  var charsWritten = Buffer.blitBuffer(Buffer.utf16leToBytes(string), buf, offset, length)
+  return charsWritten
+}
+
+Buffer.prototype.write = function (string, offset, length, encoding) {
+  // Support both (string, offset, length, encoding)
+  // and the legacy (string, encoding, offset, length)
+  if (isFinite(offset)) {
+    if (!isFinite(length)) {
+      encoding = length
+      length = undefined
+    }
+  } else {  // legacy
+    var swap = encoding
+    encoding = offset
+    offset = length
+    length = swap
+  }
+
+  offset = Number(offset) || 0
+  var remaining = this.length - offset
+  if (!length) {
+    length = remaining
+  } else {
+    length = Number(length)
+    if (length > remaining) {
+      length = remaining
+    }
+  }
+  encoding = String(encoding || 'utf8').toLowerCase()
+
+  var ret
+  switch (encoding) {
+    case 'hex':
+      ret = Buffer.hexWrite(this, string, offset, length)
+      break
+    case 'utf8':
+    case 'utf-8':
+      ret = Buffer.utf8Write(this, string, offset, length)
+      break
+    case 'ascii':
+      ret = Buffer.asciiWrite(this, string, offset, length)
+      break
+    case 'binary':
+      ret = Buffer.binaryWrite(this, string, offset, length)
+      break
+    case 'base64':
+      ret = Buffer.base64Write(this, string, offset, length)
+      break
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      ret = Buffer.utf16leWrite(this, string, offset, length)
+      break
+    default:
+      throw new Error('Unknown encoding')
+  }
+  return ret
+}
+
+Buffer.prototype.toString = function (encoding, start, end) {
+  var self = this
+
+  encoding = String(encoding || 'utf8').toLowerCase()
+  start = Number(start) || 0
+  end = (end === undefined) ? self.length : Number(end)
+
+  // Fastpath empty strings
+  if (end === start)
+    return ''
+
+  var ret
+  switch (encoding) {
+    case 'hex':
+      ret = Buffer.hexSlice(self, start, end)
+      break
+    case 'utf8':
+    case 'utf-8':
+      ret = Buffer.utf8Slice(self, start, end)
+      break
+    case 'ascii':
+      ret = Buffer.asciiSlice(self, start, end)
+      break
+    case 'binary':
+      ret = Buffer.binarySlice(self, start, end)
+      break
+    case 'base64':
+      ret = Buffer.base64Slice(self, start, end)
+      break
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      ret = utf16leSlice(self, start, end)
+      break
+    default:
+      throw new Error('Unknown encoding')
+  }
+  return ret
+}
+
+Buffer.prototype.toJSON = function () {
+  return {
+    type: 'Buffer',
+    data: Array.prototype.slice.call(this._arr || this, 0)
+  }
+}
+
+Buffer.prototype.equals = function (b) {
+  Buffer.assert(Buffer.isBuffer(b), 'Argument must be a Buffer')
+  return Buffer.compare(this, b) === 0
+}
+
+Buffer.prototype.compare = function (b) {
+  Buffer.assert(Buffer.isBuffer(b), 'Argument must be a Buffer')
+  return Buffer.compare(this, b)
+}
+
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+Buffer.prototype.copy = function (target, target_start, start, end) {
+  var source = this
+
+  if (!start) start = 0
+  if (!end && end !== 0) end = this.length
+  if (!target_start) target_start = 0
+
+  // Copy 0 bytes; we're done
+  if (end === start) return
+  if (target.length === 0 || source.length === 0) return
+
+  // Fatal error conditions
+  Buffer.assert(end >= start, 'sourceEnd < sourceStart')
+  Buffer.assert(target_start >= 0 && target_start < target.length,
+      'targetStart out of bounds')
+  Buffer.assert(start >= 0 && start < source.length, 'sourceStart out of bounds')
+  Buffer.assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds')
+
+  // Are we oob?
+  if (end > this.length)
+    end = this.length
+  if (target.length - target_start < end - start)
+    end = target.length - target_start + start
+
+  var len = end - start
+
+  if (len < 100 || !Buffer._useTypedArrays) {
+    for (var i = 0; i < len; i++) {
+      target[i + target_start] = this[i + start]
+    }
+  } else {
+    target._set(this.subarray(start, start + len), target_start)
+  }
+}
+
+Buffer.base64Slice = function(buf, start, end) {
+  if (start === 0 && end === buf.length) {
+    return base64.fromByteArray(buf)
+  } else {
+    return base64.fromByteArray(buf.slice(start, end))
+  }
+}
+
+Buffer.utf8Slice = function(buf, start, end) {
+  var res = ''
+  var tmp = ''
+  end = Math.min(buf.length, end)
+
+  for (var i = start; i < end; i++) {
+    if (buf[i] <= 0x7F) {
+      res += Buffer.decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
+      tmp = ''
+    } else {
+      tmp += '%' + buf[i].toString(16)
+    }
+  }
+
+  return res + Buffer.decodeUtf8Char(tmp)
+}
+
+Buffer.asciiSlice = function(buf, start, end) {
+  var ret = ''
+  end = Math.min(buf.length, end)
+
+  for (var i = start; i < end; i++) {
+    ret += String.fromCharCode(buf[i])
+  }
+  return ret
+}
+
+Buffer.binarySlice = function(buf, start, end) {
+  return Buffer.asciiSlice(buf, start, end)
+}
+
+Buffer.hexSlice = function(buf, start, end) {
+  var len = buf.length
+
+  if (!start || start < 0) start = 0
+  if (!end || end < 0 || end > len) end = len
+
+  var out = ''
+  for (var i = start; i < end; i++) {
+    out += Buffer.toHex(buf[i])
+  }
+  return out
+}
+
+function utf16leSlice (buf, start, end) {
+  var bytes = buf.slice(start, end)
+  var res = ''
+  for (var i = 0; i < bytes.length; i += 2) {
+    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
+  }
+  return res
+}
+
+Buffer.prototype.slice = function (start, end) {
+  var len = this.length
+  start = Buffer.clamp(start, len, 0)
+  end = Buffer.clamp(end, len, len)
+
+  if (Buffer._useTypedArrays) {
+    return Buffer._augment(this.subarray(start, end))
+  } else {
+    var sliceLen = end - start
+    var newBuf = new Buffer(sliceLen, undefined, true)
+    for (var i = 0; i < sliceLen; i++) {
+      newBuf[i] = this[i + start]
+    }
+    return newBuf
+  }
+}
+
+// `get` will be removed in Node 0.13+
+Buffer.prototype.get = function (offset) {
+  console.log('.get() is deprecated. Access using array indexes instead.')
+  return this.readUInt8(offset)
+}
+
+// `set` will be removed in Node 0.13+
+Buffer.prototype.set = function (v, offset) {
+  console.log('.set() is deprecated. Access using array indexes instead.')
+  return this.writeUInt8(v, offset)
+}
+
+Buffer.prototype.readUInt8 = function (offset, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset < this.length, 'Trying to read beyond buffer length')
+  }
+
+  if (offset >= this.length)
+    return
+
+  return this[offset]
+}
+
+Buffer.readUInt16 = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  var val
+  if (littleEndian) {
+    val = buf[offset]
+    if (offset + 1 < len)
+      val |= buf[offset + 1] << 8
+  } else {
+    val = buf[offset] << 8
+    if (offset + 1 < len)
+      val |= buf[offset + 1]
+  }
+  return val
+}
+
+Buffer.prototype.readUInt16LE = function (offset, noAssert) {
+  return Buffer.readUInt16(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readUInt16BE = function (offset, noAssert) {
+  return Buffer.readUInt16(this, offset, false, noAssert)
+}
+
+Buffer.readUInt32 = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  var val
+  if (littleEndian) {
+    if (offset + 2 < len)
+      val = buf[offset + 2] << 16
+    if (offset + 1 < len)
+      val |= buf[offset + 1] << 8
+    val |= buf[offset]
+    if (offset + 3 < len)
+      val = val + (buf[offset + 3] << 24 >>> 0)
+  } else {
+    if (offset + 1 < len)
+      val = buf[offset + 1] << 16
+    if (offset + 2 < len)
+      val |= buf[offset + 2] << 8
+    if (offset + 3 < len)
+      val |= buf[offset + 3]
+    val = val + (buf[offset] << 24 >>> 0)
+  }
+  return val
+}
+
+Buffer.prototype.readUInt32LE = function (offset, noAssert) {
+  return Buffer.readUInt32(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readUInt32BE = function (offset, noAssert) {
+  return Buffer.readUInt32(this, offset, false, noAssert)
+}
+
+Buffer.prototype.readInt8 = function (offset, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(offset !== undefined && offset !== null,
+        'missing offset')
+    Buffer.assert(offset < this.length, 'Trying to read beyond buffer length')
+  }
+
+  if (offset >= this.length)
+    return
+
+  var neg = this[offset] & 0x80
+  if (neg)
+    return (0xff - this[offset] + 1) * -1
+  else
+    return this[offset]
+}
+
+Buffer.readInt16 = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  var val = Buffer.readUInt16(buf, offset, littleEndian, true)
+  var neg = val & 0x8000
+  if (neg)
+    return (0xffff - val + 1) * -1
+  else
+    return val
+}
+
+Buffer.prototype.readInt16LE = function (offset, noAssert) {
+  return Buffer.readInt16(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readInt16BE = function (offset, noAssert) {
+  return Buffer.readInt16(this, offset, false, noAssert)
+}
+
+Buffer.readInt32 = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  var val = Buffer.readUInt32(buf, offset, littleEndian, true)
+  var neg = val & 0x80000000
+  if (neg)
+    return (0xffffffff - val + 1) * -1
+  else
+    return val
+}
+
+Buffer.prototype.readInt32LE = function (offset, noAssert) {
+  return Buffer.readInt32(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readInt32BE = function (offset, noAssert) {
+  return Buffer.readInt32(this, offset, false, noAssert)
+}
+
+Buffer.readFloat = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  return ieee754.read(buf, offset, littleEndian, 23, 4)
+}
+
+Buffer.prototype.readFloatLE = function (offset, noAssert) {
+  return Buffer.readFloat(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readFloatBE = function (offset, noAssert) {
+  return Buffer.readFloat(this, offset, false, noAssert)
+}
+
+Buffer.readDouble = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset + 7 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  return ieee754.read(buf, offset, littleEndian, 52, 8)
+}
+
+Buffer.prototype.readDoubleLE = function (offset, noAssert) {
+  return Buffer.readDouble(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readDoubleBE = function (offset, noAssert) {
+  return Buffer.readDouble(this, offset, false, noAssert)
+}
+
+Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset < this.length, 'trying to write beyond buffer length')
+    Buffer.verifuint(value, 0xff)
+  }
+
+  if (offset >= this.length) return
+
+  this[offset] = value
+  return offset + 1
+}
+
+Buffer.writeUInt16 = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 1 < buf.length, 'trying to write beyond buffer length')
+    Buffer.verifuint(value, 0xffff)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) {
+    buf[offset + i] =
+        (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
+            (littleEndian ? i : 1 - i) * 8
+  }
+  return offset + 2
+}
+
+Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
+  return Buffer.writeUInt16(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
+  return Buffer.writeUInt16(this, value, offset, false, noAssert)
+}
+
+Buffer.writeUInt32 = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'trying to write beyond buffer length')
+    Buffer.verifuint(value, 0xffffffff)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) {
+    buf[offset + i] =
+        (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
+  }
+  return offset + 4
+}
+
+Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
+  return Buffer.writeUInt32(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
+  return Buffer.writeUInt32(this, value, offset, false, noAssert)
+}
+
+Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset < this.length, 'Trying to write beyond buffer length')
+    Buffer.verifsint(value, 0x7f, -0x80)
+  }
+
+  if (offset >= this.length)
+    return
+
+  if (value >= 0)
+    this.writeUInt8(value, offset, noAssert)
+  else
+    this.writeUInt8(0xff + value + 1, offset, noAssert)
+  return offset + 1
+}
+
+Buffer.writeInt16 = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 1 < buf.length, 'Trying to write beyond buffer length')
+    Buffer.verifsint(value, 0x7fff, -0x8000)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  if (value >= 0)
+    Buffer.writeUInt16(buf, value, offset, littleEndian, noAssert)
+  else
+    Buffer.writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert)
+  return offset + 2
+}
+
+Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
+  return Buffer.writeInt16(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
+  return Buffer.writeInt16(this, value, offset, false, noAssert)
+}
+
+Buffer.writeInt32 = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
+    Buffer.verifsint(value, 0x7fffffff, -0x80000000)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  if (value >= 0)
+    Buffer.writeUInt32(buf, value, offset, littleEndian, noAssert)
+  else
+    Buffer.writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert)
+  return offset + 4
+}
+
+Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
+  return Buffer.writeInt32(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
+  return Buffer.writeInt32(this, value, offset, false, noAssert)
+}
+
+Buffer.writeFloat = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
+    Buffer.verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  ieee754.write(buf, value, offset, littleEndian, 23, 4)
+  return offset + 4
+}
+
+Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
+  return Buffer.writeFloat(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
+  return Buffer.writeFloat(this, value, offset, false, noAssert)
+}
+
+Buffer.writeDouble = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 7 < buf.length,
+        'Trying to write beyond buffer length')
+    Buffer.verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  ieee754.write(buf, value, offset, littleEndian, 52, 8)
+  return offset + 8
+}
+
+Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
+  return Buffer.writeDouble(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
+  return Buffer.writeDouble(this, value, offset, false, noAssert)
+}
+
+// fill(value, start=0, end=buffer.length)
+Buffer.prototype.fill = function (value, start, end) {
+  if (!value) value = 0
+  if (!start) start = 0
+  if (!end) end = this.length
+
+  Buffer.assert(end >= start, 'end < start')
+
+  // Fill 0 bytes; we're done
+  if (end === start) return
+  if (this.length === 0) return
+
+  Buffer.assert(start >= 0 && start < this.length, 'start out of bounds')
+  Buffer.assert(end >= 0 && end <= this.length, 'end out of bounds')
+
+  var i
+  if (typeof value === 'number') {
+    for (i = start; i < end; i++) {
+      this[i] = value
+    }
+  } else {
+    var bytes = Buffer.utf8ToBytes(value.toString())
+    var len = bytes.length
+    for (i = start; i < end; i++) {
+      this[i] = bytes[i % len]
+    }
+  }
+
+  return this
+}
+
+Buffer.prototype.inspect = function () {
+  var out = []
+  var len = this.length
+  for (var i = 0; i < len; i++) {
+    out[i] = Buffer.toHex(this[i])
+    if (i === exports.INSPECT_MAX_BYTES) {
+      out[i + 1] = '...'
+      break
+    }
+  }
+  return '<Buffer ' + out.join(' ') + '>'
+}
+
+/**
+ * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
+ * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
+ */
+Buffer.prototype.toArrayBuffer = function () {
+  if (typeof Uint8Array !== 'undefined') {
+    if (Buffer._useTypedArrays) {
+      return (new Buffer(this)).buffer
+    } else {
+      var buf = new Uint8Array(this.length)
+      for (var i = 0, len = buf.length; i < len; i += 1) {
+        buf[i] = this[i]
+      }
+      return buf.buffer
+    }
+  } else {
+    throw new Error('Buffer.toArrayBuffer not supported in this browser')
+  }
+}
+
+// HELPER FUNCTIONS
+// ================
+
+var BP = Buffer.prototype
+
+/**
+ * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
+ */
+Buffer._augment = function (arr) {
+  arr._isBuffer = true
+
+  // save reference to original Uint8Array get/set methods before overwriting
+  arr._get = arr.get
+  arr._set = arr.set
+
+  // deprecated, will be removed in node 0.13+
+  arr.get = BP.get
+  arr.set = BP.set
+
+  arr.write = BP.write
+  arr.toString = BP.toString
+  arr.toLocaleString = BP.toString
+  arr.toJSON = BP.toJSON
+  arr.equals = BP.equals
+  arr.compare = BP.compare
+  arr.copy = BP.copy
+  arr.slice = BP.slice
+  arr.readUInt8 = BP.readUInt8
+  arr.readUInt16LE = BP.readUInt16LE
+  arr.readUInt16BE = BP.readUInt16BE
+  arr.readUInt32LE = BP.readUInt32LE
+  arr.readUInt32BE = BP.readUInt32BE
+  arr.readInt8 = BP.readInt8
+  arr.readInt16LE = BP.readInt16LE
+  arr.readInt16BE = BP.readInt16BE
+  arr.readInt32LE = BP.readInt32LE
+  arr.readInt32BE = BP.readInt32BE
+  arr.readFloatLE = BP.readFloatLE
+  arr.readFloatBE = BP.readFloatBE
+  arr.readDoubleLE = BP.readDoubleLE
+  arr.readDoubleBE = BP.readDoubleBE
+  arr.writeUInt8 = BP.writeUInt8
+  arr.writeUInt16LE = BP.writeUInt16LE
+  arr.writeUInt16BE = BP.writeUInt16BE
+  arr.writeUInt32LE = BP.writeUInt32LE
+  arr.writeUInt32BE = BP.writeUInt32BE
+  arr.writeInt8 = BP.writeInt8
+  arr.writeInt16LE = BP.writeInt16LE
+  arr.writeInt16BE = BP.writeInt16BE
+  arr.writeInt32LE = BP.writeInt32LE
+  arr.writeInt32BE = BP.writeInt32BE
+  arr.writeFloatLE = BP.writeFloatLE
+  arr.writeFloatBE = BP.writeFloatBE
+  arr.writeDoubleLE = BP.writeDoubleLE
+  arr.writeDoubleBE = BP.writeDoubleBE
+  arr.fill = BP.fill
+  arr.inspect = BP.inspect
+  arr.toArrayBuffer = BP.toArrayBuffer
+
+  return arr
+}
+
+Buffer.stringtrim = function(str) {
+  if (str.trim) return str.trim()
+  return str.replace(/^\s+|\s+$/g, '')
+}
+
+// slice(start, end)
+Buffer.clamp = function(index, len, defaultValue) {
+  if (typeof index !== 'number') return defaultValue
+  index = ~~index;  // Coerce to integer.
+  if (index >= len) return len
+  if (index >= 0) return index
+  index += len
+  if (index >= 0) return index
+  return 0
+}
+
+Buffer.coerce = function(length) {
+  // Coerce length to a number (possibly NaN), round up
+  // in case it's fractional (e.g. 123.456) then do a
+  // double negate to coerce a NaN to 0. Easy, right?
+  length = ~~Math.ceil(+length)
+  return length < 0 ? 0 : length
+}
+
+Buffer.isArray = function(subject) {
+  return (Array.isArray || function (subject) {
+    return Object.prototype.toString.call(subject) === '[object Array]'
+  })(subject)
+}
+
+Buffer.isArrayish = function(subject) {
+  return Buffer.isArray(subject) || Buffer.isBuffer(subject) ||
+      subject && typeof subject === 'object' &&
+      typeof subject.length === 'number'
+}
+
+Buffer.toHex = function(n) {
+  if (n < 16) return '0' + n.toString(16)
+  return n.toString(16)
+}
+
+Buffer.utf8ToBytes = function(str) {
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    var b = str.charCodeAt(i)
+    if (b <= 0x7F) {
+      byteArray.push(b)
+    } else {
+      var start = i
+      if (b >= 0xD800 && b <= 0xDFFF) i++
+      var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')
+      for (var j = 0; j < h.length; j++) {
+        byteArray.push(parseInt(h[j], 16))
+      }
+    }
+  }
+  return byteArray
+}
+
+Buffer.asciiToBytes = function(str) {
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    // Node's code seems to be doing this and not & 0x7F..
+    byteArray.push(str.charCodeAt(i) & 0xFF)
+  }
+  return byteArray
+}
+
+Buffer.utf16leToBytes = function(str) {
+  var c, hi, lo
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    c = str.charCodeAt(i)
+    hi = c >> 8
+    lo = c % 256
+    byteArray.push(lo)
+    byteArray.push(hi)
+  }
+
+  return byteArray
+}
+
+Buffer.base64ToBytes = function(str) {
+  return base64.toByteArray(str)
+}
+
+Buffer.blitBuffer = function(src, dst, offset, length) {
+  for (var i = 0; i < length; i++) {
+    if ((i + offset >= dst.length) || (i >= src.length))
+      break
+    dst[i + offset] = src[i]
+  }
+  return i
+}
+
+Buffer.decodeUtf8Char = function(str) {
+  try {
+    return decodeURIComponent(str)
+  } catch (err) {
+    return String.fromCharCode(0xFFFD) // UTF 8 invalid char
+  }
+}
 
 /*
- * Return true if necessary JavaScript support is available, else log an error and return false.
+ * We have to make sure that the value is a valid integer. This means that it
+ * is non-negative. It has no fractional component and that it does not
+ * exceed the maximum allowed value.
  */
-NDN.getSupported = function() {
+Buffer.verifuint = function(value, max) {
+  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
+  Buffer.assert(value >= 0, 'specified a negative value for writing an unsigned value')
+  Buffer.assert(value <= max, 'value is larger than maximum value for type')
+  Buffer.assert(Math.floor(value) === value, 'value has a fractional component')
+}
+
+Buffer.verifsint = function(value, max, min) {
+  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
+  Buffer.assert(value <= max, 'value larger than maximum allowed value')
+  Buffer.assert(value >= min, 'value smaller than minimum allowed value')
+  Buffer.assert(Math.floor(value) === value, 'value has a fractional component')
+}
+
+Buffer.verifIEEE754 = function(value, max, min) {
+  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
+  Buffer.assert(value <= max, 'value larger than maximum allowed value')
+  Buffer.assert(value >= min, 'value smaller than minimum allowed value')
+}
+
+Buffer.assert = function(test, message) {
+  if (!test) throw new Error(message || 'Failed assertion')
+}
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * The Log class holds the global static variable LOG.
+ */
+var Log = function Log()
+{
+}
+
+exports.Log = Log;
+
+/**
+ * LOG is the level for logging debugging statements.  0 means no log messages.
+ * @type Number
+ */
+Log.LOG = 0;
+/**
+ * Encapsulate a Buffer and support dynamic reallocation.
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var printStackTrace = require('../../contrib/stacktrace/stacktrace.js').printStackTrace;
+
+/**
+ * NdnCommon has static NDN utility methods and constants.
+ * @constructor
+ */
+var NdnCommon = {};
+
+exports.NdnCommon = NdnCommon;
+
+/**
+ * The practical limit of the size of a network-layer packet. If a packet is
+ * larger than this, the library or application MAY drop it. This constant is
+ * defined in this low-level class so that internal code can use it, but
+ * applications should use the static API method
+ * Face.getMaxNdnPacketSize() which is equivalent.
+ */
+NdnCommon.MAX_NDN_PACKET_SIZE = 8800;
+
+/**
+ * Get the error message plus its stack trace.
+ * @param {Error} error The error object.
+ * @return {string} The error message, plus the stack trace with each line
+ * separated by '\n'.
+ */
+NdnCommon.getErrorWithStackTrace = function(error)
+{
+  return error + '\n' + printStackTrace({e: error}).join('\n');
+};
+
+/**
+ * Check for Indexed DB support and call onComplete with the result as described
+ * below. This has to use an onComplete callback since IndexedDB is async.
+ * @param {function} onComplete This calls onComplete(haveIndexedDb) where
+ * haveIndexedDb is true if the browser has Indexed DB support, otherwise false.
+ */
+NdnCommon.checkIndexedDb = function(onComplete)
+{
+  try {
+    var database = new Dexie("test-Dexie-support");
+    database.version(1).stores({});
+    database.open();
+
+    // Give Dexie a little time to open.
+    setTimeout(function() {
+      try {
+        onComplete(database.isOpen());
+      } catch (ex) {
+        onComplete(false);
+      }
+    }, 200);
+  } catch (ex) {
+    onComplete(false);
+  }
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var NdnCommon = require('./ndn-common.js').NdnCommon;
+
+/**
+ * An ExponentialReExpress uses an internal onTimeout to express the interest again
+ * with double the interestLifetime. See ExponentialReExpress.makeOnTimeout,
+ * which you should call instead of the private constructor.
+ * Create a new ExponentialReExpress where onTimeout expresses the interest
+ * again with double the interestLifetime. If the interesLifetime goes
+ * over settings.maxInterestLifetime, then call the given onTimeout. If this
+ * internally gets onData, just call the given onData.
+ * @constructor
+ */
+var ExponentialReExpress = function ExponentialReExpress
+  (face, onData, onTimeout, settings)
+{
+  settings = (settings || {});
+  this.face = face;
+  this.callerOnData = onData;
+  this.callerOnTimeout = onTimeout;
+
+  this.maxInterestLifetime = (settings.maxInterestLifetime || 16000);
+};
+
+exports.ExponentialReExpress = ExponentialReExpress;
+
+/**
+ * Return a callback to use in expressInterest for onTimeout which will express
+ * the interest again with double the interestLifetime. If the interesLifetime
+ * goes over maxInterestLifetime (see settings below), then call the provided
+ * onTimeout. If a Data packet is received, this calls the provided onData.
+ * Use it like this:
+ *   var onData = function() { ... };
+ *   var onTimeout = function() { ... };
+ *   face.expressInterest
+ *     (interest, onData,
+ *      ExponentialReExpress.makeOnTimeout(face, onData, onTimeout));
+ * @param {Face} face This calls face.expressInterest.
+ * @param {function} onData When a matching data packet is received, this calls
+ * onData(interest, data) where interest is the interest given to
+ * expressInterest and data is the received Data object. This is normally the
+ * same onData you initially passed to expressInterest.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onTimeout If the interesLifetime goes over
+ * maxInterestLifetime, this calls onTimeout(interest). However, if onTimeout is
+ * null, this does not use it.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {Object} settings (optional) If not null, an associative array with
+ * the following defaults:
+ * {
+ *   maxInterestLifetime: 16000 // milliseconds
+ * }
+ * @return {function} The onTimeout callback to pass to expressInterest.
+ */
+ExponentialReExpress.makeOnTimeout = function(face, onData, onTimeout, settings)
+{
+  var reExpress = new ExponentialReExpress(face, onData, onTimeout, settings);
+  return function(interest) { reExpress.onTimeout(interest); };
+};
+
+ExponentialReExpress.prototype.onTimeout = function(interest)
+{
+  var interestLifetime = interest.getInterestLifetimeMilliseconds();
+  if (interestLifetime == null) {
+    // Can't re-express.
+    if (this.callerOnTimeout) {
+      try {
+        this.callerOnTimeout(interest);
+      } catch (ex) {
+        console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+    return;
+  }
+
+  var nextInterestLifetime = interestLifetime * 2;
+  if (nextInterestLifetime > this.maxInterestLifetime) {
+    if (this.callerOnTimeout) {
+      try {
+        this.callerOnTimeout(interest);
+      } catch (ex) {
+        console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+    return;
+  }
+
+  var nextInterest = interest.clone();
+  nextInterest.setInterestLifetimeMilliseconds(nextInterestLifetime);
+  var thisObject = this;
+  this.face.expressInterest
+    (nextInterest, this.callerOnData,
+     function(localInterest) { thisObject.onTimeout(localInterest); });
+};
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A Blob holds an immutable byte array implemented as a Buffer.  This should be
+ * treated like a string which is a pointer to an immutable string. (It is OK to
+ * pass a pointer to the string because the new owner can’t change the bytes of
+ * the string.)  Blob does not inherit from Buffer. Instead you must call buf()
+ * to get the byte array which reminds you that you should not change the
+ * contents.  Also remember that buf() can return null.
+ * @param {Blob|Buffer|Array<number>} value (optional) If value is a Blob, take
+ * another pointer to the Buffer without copying. If value is a Buffer or byte
+ * array, copy to create a new Buffer.  If omitted, buf() will return null.
+ * @param {boolean} copy (optional) If true, copy the contents of
+ * value into a new Buffer.  If false, just use the existing value without
+ * copying. If omitted, then copy the contents (unless value is already a Blob).
+ * IMPORTANT: If copy is false, if you keep a pointer to the value then you must
+ * treat the value as immutable and promise not to change it.
+ * @constructor
+ */
+var Blob = function Blob(value, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  if (value == null)
+    this.buffer = null;
+  else if (typeof value === 'object' && value instanceof Blob)
+    // Use the existing buffer.  Don't need to check for copy.
+    this.buffer = value.buffer;
+  else {
+    if (typeof value === 'string')
+      // Convert from a string to utf-8 byte encoding.
+      this.buffer = new Buffer(value, 'utf8');
+    else {
+      if (copy)
+        // We are copying, so just make another Buffer.
+        this.buffer = new Buffer(value);
+      else {
+        if (Buffer.isBuffer(value))
+          // We can use as-is.
+          this.buffer = value;
+        else
+          // We need a Buffer, so copy.
+          this.buffer = new Buffer(value);
+      }
+    }
+  }
+
+  // Set the length to be "JavaScript-like".
+  this.length = this.buffer != null ? this.buffer.length : 0;
+};
+
+exports.Blob = Blob;
+
+/**
+ * Return the length of the immutable byte array.
+ * @return {number} The length of the array.  If buf() is null, return 0.
+ */
+Blob.prototype.size = function()
+{
+  if (this.buffer != null)
+    return this.buffer.length;
+  else
+    return 0;
+};
+
+/**
+ * Return the immutable byte array.  DO NOT change the contents of the Buffer.
+ * If you need to change it, make a copy.
+ * @return {Buffer} The Buffer holding the immutable byte array, or null.
+ */
+Blob.prototype.buf = function()
+{
+  return this.buffer;
+};
+
+/**
+ * Return true if the array is null, otherwise false.
+ * @return {boolean} True if the array is null.
+ */
+Blob.prototype.isNull = function()
+{
+  return this.buffer == null;
+};
+
+/**
+ * Return the hex representation of the bytes in the byte array.
+ * @return {string} The hex string.
+ */
+Blob.prototype.toHex = function()
+{
+  if (this.buffer == null)
+    return "";
+  else
+    return this.buffer.toString('hex');
+};
+
+/**
+ * Decode the byte array as UTF8 and return the Unicode string.
+ * @return A unicode string, or "" if the buffer is null.
+ */
+Blob.prototype.toString = function()
+{
+  if (this.buffer == null)
+    return "";
+  else
+    return this.buffer.toString('utf8');
+};
+
+/**
+ * Check if the value of this Blob equals the other blob.
+ * @param {Blob} other The other Blob to check.
+ * @return {boolean} if this isNull and other isNull or if the bytes of this
+ * blob equal the bytes of the other.
+ */
+Blob.prototype.equals = function(other)
+{
+  if (this.isNull())
+    return other.isNull();
+  else if (other.isNull())
+    return false;
+  else {
+    if (this.buffer.length != other.buffer.length)
+      return false;
+
+    for (var i = 0; i < this.buffer.length; ++i) {
+      if (this.buffer[i] != other.buffer[i])
+        return false;
+    }
+
+    return true;
+  }
+};
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./blob.js').Blob;
+
+/**
+ * A SignedBlob extends Blob to keep the offsets of a signed portion (e.g., the
+ * bytes of Data packet). This inherits from Blob, including Blob.size and Blob.buf.
+ * @param {Blob|Buffer|Array<number>} value (optional) If value is a Blob, take
+ * another pointer to the Buffer without copying. If value is a Buffer or byte
+ * array, copy to create a new Buffer.  If omitted, buf() will return null.
+ * @param {number} signedPortionBeginOffset (optional) The offset in the
+ * encoding of the beginning of the signed portion. If omitted, set to 0.
+ * @param {number} signedPortionEndOffset (optional) The offset in the encoding
+ * of the end of the signed portion. If omitted, set to 0.
+ * @constructor
+ */
+var SignedBlob = function SignedBlob(value, signedPortionBeginOffset, signedPortionEndOffset)
+{
+  // Call the base constructor.
+  Blob.call(this, value);
+
+  if (this.buffer == null) {
+    this.signedPortionBeginOffset = 0;
+    this.signedPortionEndOffset = 0;
+  }
+  else if (typeof value === 'object' && value instanceof SignedBlob) {
+    // Copy the SignedBlob, allowing override for offsets.
+    this.signedPortionBeginOffset = signedPortionBeginOffset == null ?
+      value.signedPortionBeginOffset : signedPortionBeginOffset;
+    this.signedPortionEndOffset = signedPortionEndOffset == null ?
+      value.signedPortionEndOffset : signedPortionEndOffset;
+  }
+  else {
+    this.signedPortionBeginOffset = signedPortionBeginOffset || 0;
+    this.signedPortionEndOffset = signedPortionEndOffset || 0;
+  }
+
+  if (this.buffer == null)
+    this.signedBuffer = null;
+  else
+    this.signedBuffer = this.buffer.slice
+      (this.signedPortionBeginOffset, this.signedPortionEndOffset);
+};
+
+SignedBlob.prototype = new Blob();
+SignedBlob.prototype.name = "SignedBlob";
+
+exports.SignedBlob = SignedBlob;
+
+/**
+ * Return the length of the signed portion of the immutable byte array.
+ * @return {number} The length of the signed portion.  If signedBuf() is null,
+ * return 0.
+ */
+SignedBlob.prototype.signedSize = function()
+{
+  if (this.signedBuffer != null)
+    return this.signedBuffer.length;
+  else
+    return 0;
+};
+
+/**
+ * Return a the signed portion of the immutable byte array.
+ * @return {Buffer} A slice into the Buffer which is the signed portion.
+ * If the pointer to the array is null, return null.
+ */
+SignedBlob.prototype.signedBuf = function() { return this.signedBuffer; };
+
+/**
+ * Return the offset in the array of the beginning of the signed portion.
+ * @return {number} The offset in the array.
+ */
+SignedBlob.prototype.getSignedPortionBeginOffset = function()
+{
+  return this.signedPortionBeginOffset;
+};
+
+/**
+ * Return the offset in the array of the end of the signed portion.
+ * @return {number} The offset in the array.
+ */
+SignedBlob.prototype.getSignedPortionEndOffset = function()
+{
+  return this.signedPortionEndOffset;
+};
+/**
+ * Encapsulate a Buffer and support dynamic reallocation.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a DynamicBuffer where this.array is a Buffer of size length.
+ * To access the array, use this.array or call slice.
+ * @constructor
+ * @param {number} length the initial length of the array.  If null, use a default.
+ */
+var DynamicBuffer = function DynamicBuffer(length)
+{
+  if (!length)
+    length = 16;
+
+  this.array = new Buffer(length);
+};
+
+exports.DynamicBuffer = DynamicBuffer;
+
+/**
+ * Ensure that this.array has the length, reallocate and copy if necessary.
+ * Update the length of this.array which may be greater than length.
+ * @param {number} length The minimum length for the array.
+ */
+DynamicBuffer.prototype.ensureLength = function(length)
+{
+  if (this.array.length >= length)
+    return;
+
+  // See if double is enough.
+  var newLength = this.array.length * 2;
+  if (length > newLength)
+    // The needed length is much greater, so use it.
+    newLength = length;
+
+  var newArray = new Buffer(newLength);
+  this.array.copy(newArray);
+  this.array = newArray;
+};
+
+/**
+ * Copy the value to this.array at offset, reallocating if necessary.
+ * @param {Buffer} value The buffer to copy.
+ * @param {number} offset The offset in the buffer to start copying into.
+ * @return {number} The new offset which is offset + value.length.
+ */
+DynamicBuffer.prototype.copy = function(value, offset)
+{
+  this.ensureLength(value.length + offset);
+
+  if (Buffer.isBuffer(value))
+    value.copy(this.array, offset);
+  else
+    // Need to make value a Buffer to copy.
+    new Buffer(value).copy(this.array, offset);
+
+  return offset + value.length;
+};
+
+/**
+ * Ensure that this.array has the length. If necessary, reallocate the array
+ *   and shift existing data to the back of the new array.
+ * Update the length of this.array which may be greater than length.
+ * @param {number} length The minimum length for the array.
+ */
+DynamicBuffer.prototype.ensureLengthFromBack = function(length)
+{
+  if (this.array.length >= length)
+    return;
+
+  // See if double is enough.
+  var newLength = this.array.length * 2;
+  if (length > newLength)
+    // The needed length is much greater, so use it.
+    newLength = length;
+
+  var newArray = new Buffer(newLength);
+  // Copy to the back of newArray.
+  this.array.copy(newArray, newArray.length - this.array.length);
+  this.array = newArray;
+};
+
+/**
+ * First call ensureLengthFromBack to make sure the bytearray has
+ * offsetFromBack bytes, then copy value into the array starting
+ * offsetFromBack bytes from the back of the array.
+ * @param {Buffer} value The buffer to copy.
+ * @param {number} offsetFromBack The offset from the back of the array to start
+ * copying.
+ */
+DynamicBuffer.prototype.copyFromBack = function(value, offsetFromBack)
+{
+  this.ensureLengthFromBack(offsetFromBack);
+
+  if (Buffer.isBuffer(value))
+    value.copy(this.array, this.array.length - offsetFromBack);
+  else
+    // Need to make value a Buffer to copy.
+    new Buffer(value).copy(this.array, this.array.length - offsetFromBack);
+};
+
+/**
+ * Return this.array.slice(begin, end);
+ * @param {number} begin The begin index for the slice.
+ * @param {number} end (optional) The end index for the slice.
+ * @return {Buffer} The buffer slice.
+ */
+DynamicBuffer.prototype.slice = function(begin, end)
+{
+  if (end == undefined)
+    return this.array.slice(begin);
+  else
+    return this.array.slice(begin, end);
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A ChangeCounter keeps a target object whose change count is tracked by a
+ * local change count.  You can set to a new target which updates the local
+ * change count, and you can call checkChanged to check if the target (or one of
+ * the target's targets) has been changed. The target object must have a method
+ * getChangeCount.
+ *
+ * Create a new ChangeCounter to track the given target. If target is not null,
+ * this sets the local change counter to target.getChangeCount().
+ * @param {object} target The target to track, as an object with the method
+ * getChangeCount().
+ * @constructor
+ */
+var ChangeCounter = function ChangeCounter(target)
+{
+  this.target = target;
+  this.changeCount = (target == null ? 0 : target.getChangeCount());
+};
+
+exports.ChangeCounter = ChangeCounter;
+
+/**
+ * Get the target object. If the target is changed, then checkChanged will
+ * detect it.
+ * @return {object} The target, as an object with the method
+ * getChangeCount().
+ */
+ChangeCounter.prototype.get = function()
+{
+  return this.target;
+};
+
+/**
+ * Set the target to the given target. If target is not null, this sets the
+ * local change counter to target.getChangeCount().
+ * @param {object} target The target to track, as an object with the method
+ * getChangeCount().
+ */
+ChangeCounter.prototype.set = function(target)
+{
+  this.target = target;
+  this.changeCount = (target == null ? 0 : target.getChangeCount());
+};
+
+/**
+ * If the target's change count is different than the local change count, then
+ * update the local change count and return true. Otherwise return false,
+ * meaning that the target has not changed. Also, if the target is null,
+ * simply return false. This is useful since the target (or one of the target's
+ * targets) may be changed and you need to find out.
+ * @return {boolean} True if the change count has been updated, false if not.
+ */
+ChangeCounter.prototype.checkChanged = function()
+{
+  if (this.target == null)
+    return false;
+
+  var targetChangeCount = this.target.getChangeCount();
+  if (this.changeCount != targetChangeCount) {
+    this.changeCount = targetChangeCount;
+    return true;
+  }
+  else
+    return false;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var NdnCommon = require('./ndn-common.js').NdnCommon;
+
+/**
+ * A SyncPromise is a promise which is immediately fulfilled or rejected, used
+ * to return a promise in synchronous code.
+ * This private constructor creates a SyncPromise fulfilled or rejected with the
+ * given value. You should normally not call this constructor but call
+ * SyncPromise.resolve or SyncPromise.reject. Note that we don't need a
+ * constructor like SyncPromise(function(resolve, reject)) because this would be
+ * for scheduling the function to be called later, which we don't do.
+ * @param {any} value If isRejected is false, this is the value of the fulfilled
+ * promise, else if isRejected is true, this is the error.
+ * @param {boolean} isRejected True to create a promise in the rejected state,
+ * where value is the error.
+ * @constructor
+ */
+var SyncPromise = function SyncPromise(value, isRejected)
+{
+  this.value = value;
+  this.isRejected = isRejected;
+};
+
+exports.SyncPromise = SyncPromise;
+
+/**
+ * If this promise is fulfilled, immediately call onFulfilled with the fulfilled
+ * value as described below. Otherwise, if this promise is rejected, immediately
+ * call onRejected with the error as described below.
+ * @param {function} (optional) onFulfilled If this promise is fulfilled, this
+ * calls onFulfilled(value) with the value of this promise and returns the
+ * result. The function should return a promise. To use all synchronous code,
+ * onFulfilled should return SyncPromise.resolve(newValue).
+ * @param {function} (optional) onRejected If this promise is rejected, this
+ * calls onRejected(err) with the error value of this promise and returns the
+ * result. The function should return a promise. To use all synchronous code,
+ * onFulfilled should return SyncPromise.resolve(newValue) (or throw an
+ * exception).
+ * @return {Promise|SyncPromise} If this promise is fulfilled, return the result
+ * of calling onFulfilled(value). Note that this does not create a promise which
+ * is scheduled to execute later. Rather it immediately calls onFulfilled which
+ * should return a promise. But if onFulfilled is undefined, simply return this
+ * promise to pass it forward. If this promise is rejected, return the result of
+ * calling onRejected(err) with the error value. But if onRejected is undefined,
+ * simply return this promise to pass it forward. However, if onFulfilled or
+ * onRejected throws an exception, then return a new SyncPromise in the rejected
+ * state with the exception.
+ */
+SyncPromise.prototype.then = function(onFulfilled, onRejected)
+{
+  if (this.isRejected) {
+    if (onRejected) {
+      try {
+        return onRejected(this.value);
+      }
+      catch(err) {
+        return new SyncPromise(err, true);
+      }
+    }
+    else
+      // Pass the error forward.
+      return this;
+  }
+  else {
+    if (onFulfilled) {
+      try {
+        return onFulfilled(this.value);
+      }
+      catch(err) {
+        return new SyncPromise(err, true);
+      }
+    }
+    else
+      // Pass the fulfilled value forward.
+      return this;
+  }
+};
+
+/**
+ * Call this.then(undefined, onRejected) and return the result. If this promise
+ * is rejected then onRejected will process it. If this promise is fulfilled,
+ * this simply passes it forward.
+ */
+SyncPromise.prototype.catch = function(onRejected)
+{
+  return this.then(undefined, onRejected);
+};
+
+/**
+ * Return a new SyncPromise which is already fulfilled to the given value.
+ * @param {any} value The value of the promise.
+ */
+SyncPromise.resolve = function(value)
+{
+  return new SyncPromise(value, false);
+};
+
+/**
+ * Return a new SyncPromise which is already rejected with the given error.
+ * @param {any} err The error for the rejected promise.
+ */
+SyncPromise.reject = function(err)
+{
+  return new SyncPromise(err, true);
+};
+
+/**
+ * This static method checks if the promise is a SyncPromise and immediately
+ * returns its value or throws the error if promise is rejected. If promise is
+ * not a SyncPromise, this throws an exception since it is not possible to
+ * immediately get the value. This can be used with "promise-based" code which
+ * you expect to always return a SyncPromise to operate in synchronous mode.
+ * @param {SyncPromise} promise The SyncPromise with the value to get.
+ * @return {any} The value of the promise.
+ * @throws Error If promise is not a SyncPromise.
+ * @throws any If promise is a SyncPromise in the rejected state, this throws
+ * the error.
+ */
+SyncPromise.getValue = function(promise)
+{
+  if (promise instanceof SyncPromise) {
+    if (promise.isRejected)
+      throw promise.value;
+    else
+      return promise.value;
+  }
+  else
+    throw new Error("Cannot return immediately because promise is not a SyncPromise");
+};
+
+/**
+ * This can be called with complete(onComplete, promise) or
+ * complete(onComplete, onError, promise) to handle both synchronous and
+ * asynchronous code based on whether the caller supplies the onComlete callback.
+ * If onComplete is defined, call promise.then with a function which calls
+ * onComplete(value) when fulfilled (possibly in asynchronous mode). If
+ * onComplete is undefined, then we are in synchronous mode so return
+ * SyncPromise.getValue(promise) which will throw an exception if the promise is
+ * not a SyncPromise (or is a SyncPromise in the rejected state).
+ * @param {function} onComplete If defined, this calls promise.then to fulfill
+ * the promise, then calls onComplete(value) with the value of the promise.
+ * If onComplete is undefined, the return value is described below.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an error when this calls promise.then, this calls
+ * onError(err) with the value of the error. If onComplete is undefined, then
+ * onError is ignored and this will call SyncPromise.getValue(promise) which may
+ * throw an exception.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {Promise|SyncPromise} promise If onComplete is defined, this calls
+ * promise.then. Otherwise, this calls SyncPromise.getValue(promise).
+ * @return {any} If onComplete is undefined, return SyncPromise.getValue(promise).
+ * Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * @throws Error If onComplete is undefined and promise is not a SyncPromise.
+ * @throws any If onComplete is undefined and promise is a SyncPromise in the
+ * rejected state.
+ */
+SyncPromise.complete = function(onComplete, onErrorOrPromise, promise)
+{
+  var onError;
+  if (promise)
+    onError = onErrorOrPromise;
+  else {
+    promise = onErrorOrPromise;
+    onError = null;
+  }
+
+  if (onComplete)
+    promise
+    .then(function(value) {
+      try {
+        onComplete(value);
+      } catch (ex) {
+        console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }, function(err) {
+      if (onError) {
+        try {
+          onError(err);
+        } catch (ex) {
+          console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+      else {
+        if (promise instanceof SyncPromise)
+          throw err;
+        else
+          // We are in an async promise callback, so a thrown exception won't
+          // reach the caller. Just log it.
+          console.log("Uncaught exception from a Promise: " +
+            NdnCommon.getErrorWithStackTrace(err));
+      }
+    });
+  else
+    return SyncPromise.getValue(promise);
+};
+/**
+ * This class contains utilities to help parse the data
+ *
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A DataUtils has static methods for converting data.
+ * @constructor
+ */
+var DataUtils = {};
+
+exports.DataUtils = DataUtils;
+
+/*
+ * NOTE THIS IS CURRENTLY NOT BEING USED
+ *
+ */
+
+DataUtils.keyStr = "ABCDEFGHIJKLMNOP" +
+                   "QRSTUVWXYZabcdef" +
+                   "ghijklmnopqrstuv" +
+                   "wxyz0123456789+/" +
+                   "=";
+
+/**
+ * Raw String to Base 64
+ */
+DataUtils.stringtoBase64 = function stringtoBase64(input)
+{
+   //input = escape(input);
+   var output = "";
+   var chr1, chr2, chr3 = "";
+   var enc1, enc2, enc3, enc4 = "";
+   var i = 0;
+
+   do {
+    chr1 = input.charCodeAt(i++);
+    chr2 = input.charCodeAt(i++);
+    chr3 = input.charCodeAt(i++);
+
+    enc1 = chr1 >> 2;
+    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+    enc4 = chr3 & 63;
+
+    if (isNaN(chr2))
+       enc3 = enc4 = 64;
+    else if (isNaN(chr3))
+       enc4 = 64;
+
+    output = output +
+       DataUtils.keyStr.charAt(enc1) +
+       DataUtils.keyStr.charAt(enc2) +
+       DataUtils.keyStr.charAt(enc3) +
+       DataUtils.keyStr.charAt(enc4);
+    chr1 = chr2 = chr3 = "";
+    enc1 = enc2 = enc3 = enc4 = "";
+   } while (i < input.length);
+
+   return output;
+};
+
+/**
+ * Base 64 to Raw String
+ */
+DataUtils.base64toString = function base64toString(input)
+{
+  var output = "";
+  var chr1, chr2, chr3 = "";
+  var enc1, enc2, enc3, enc4 = "";
+  var i = 0;
+
+  // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+  var base64test = /[^A-Za-z0-9\+\/\=]/g;
+  /* Test for invalid characters. */
+  if (base64test.exec(input)) {
+    alert("There were invalid base64 characters in the input text.\n" +
+          "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
+          "Expect errors in decoding.");
+  }
+
+  input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+  do {
+    enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
+    enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
+    enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
+    enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));
+
+    chr1 = (enc1 << 2) | (enc2 >> 4);
+    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+    chr3 = ((enc3 & 3) << 6) | enc4;
+
+    output = output + String.fromCharCode(chr1);
+
+    if (enc3 != 64)
+      output = output + String.fromCharCode(chr2);
+
+    if (enc4 != 64)
+      output = output + String.fromCharCode(chr3);
+
+    chr1 = chr2 = chr3 = "";
+    enc1 = enc2 = enc3 = enc4 = "";
+  } while (i < input.length);
+
+  return output;
+};
+
+/**
+ * Buffer to Hex String
+ */
+DataUtils.toHex = function(buffer)
+{
+  return buffer.toString('hex');
+};
+
+/**
+ * Raw string to hex string.
+ */
+DataUtils.stringToHex = function(args)
+{
+  var ret = "";
+  for (var i = 0; i < args.length; ++i) {
+    var value = args.charCodeAt(i);
+    ret += (value < 16 ? "0" : "") + value.toString(16);
+  }
+  return ret;
+};
+
+/**
+ * Buffer to raw string.
+ */
+DataUtils.toString = function(buffer)
+{
+  return buffer.toString('binary');
+};
+
+/**
+ * Hex String to Buffer.
+ */
+DataUtils.toNumbers = function(str)
+{
+  return new Buffer(str, 'hex');
+};
+
+/**
+ * Hex String to raw string.
+ */
+DataUtils.hexToRawString = function(str)
+{
+  if (typeof str =='string') {
+  var ret = "";
+  str.replace(/(..)/g, function(s) {
+    ret += String.fromCharCode(parseInt(s, 16));
+  });
+  return ret;
+  }
+};
+
+/**
+ * Raw String to Buffer.
+ */
+DataUtils.toNumbersFromString = function(str)
+{
+  return new Buffer(str, 'binary');
+};
+
+/**
+ * If value is a string, then interpret it as a raw string and convert to
+ * a Buffer. Otherwise assume it is a Buffer or array type and just return it.
+ * @param {string|any} value
+ * @return {Buffer}
+ */
+DataUtils.toNumbersIfString = function(value)
+{
+  if (typeof value === 'string')
+    return new Buffer(value, 'binary');
+  else
+    return value;
+};
+
+/**
+ * Encode str as utf8 and return as Buffer.
+ */
+DataUtils.stringToUtf8Array = function(str)
+{
+  return new Buffer(str, 'utf8');
+};
+
+/**
+ * arrays is an array of Buffer. Return a new Buffer which is the concatenation of all.
+ */
+DataUtils.concatArrays = function(arrays)
+{
+  return Buffer.concat(arrays);
+};
+
+// TODO: Take Buffer and use TextDecoder when available.
+DataUtils.decodeUtf8 = function(utftext)
+{
+  var string = "";
+  var i = 0;
+  var c = 0;
+    var c1 = 0;
+    var c2 = 0;
+
+  while (i < utftext.length) {
+    c = utftext.charCodeAt(i);
+
+    if (c < 128) {
+      string += String.fromCharCode(c);
+      i++;
+    }
+    else if (c > 191 && c < 224) {
+      c2 = utftext.charCodeAt(i + 1);
+      string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+      i += 2;
+    }
+    else {
+      c2 = utftext.charCodeAt(i+1);
+      var c3 = utftext.charCodeAt(i+2);
+      string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+      i += 3;
+    }
+  }
+
+  return string;
+};
+
+/**
+ * Return true if a1 and a2 are the same length with equal elements.
+ */
+DataUtils.arraysEqual = function(a1, a2)
+{
+  // A simple sanity check that it is an array.
+  if (!a1.slice)
+    throw new Error("DataUtils.arraysEqual: a1 is not an array");
+  if (!a2.slice)
+    throw new Error("DataUtils.arraysEqual: a2 is not an array");
+
+  if (a1.length != a2.length)
+    return false;
+
+  for (var i = 0; i < a1.length; ++i) {
+    if (a1[i] != a2[i])
+      return false;
+  }
+
+  return true;
+};
+
+/**
+ * Convert the big endian Buffer to an unsigned int.
+ * Don't check for overflow.
+ */
+DataUtils.bigEndianToUnsignedInt = function(bytes)
+{
+  var result = 0;
+  for (var i = 0; i < bytes.length; ++i) {
+    // Multiply by 0x100 instead of shift by 8 because << is restricted to 32 bits.
+    result *= 0x100;
+    result += bytes[i];
+  }
+  return result;
+};
+
+/**
+ * Convert the int value to a new big endian Buffer and return.
+ * If value is 0 or negative, return new Buffer(0).
+ */
+DataUtils.nonNegativeIntToBigEndian = function(value)
+{
+  value = Math.round(value);
+  if (value <= 0)
+    return new Buffer(0);
+
+  // Assume value is not over 64 bits.
+  var size = 8;
+  var result = new Buffer(size);
+  var i = 0;
+  while (value != 0) {
+    ++i;
+    result[size - i] = value & 0xff;
+    // Divide by 0x100 and floor instead of shift by 8 because >> is restricted to 32 bits.
+    value = Math.floor(value / 0x100);
+  }
+  return result.slice(size - i, size);
+};
+
+/**
+ * Modify array to randomly shuffle the elements.
+ */
+DataUtils.shuffle = function(array)
+{
+  for (var i = array.length - 1; i >= 1; --i) {
+    // j is from 0 to i.
+    var j = Math.floor(Math.random() * (i + 1));
+    var temp = array[i];
+    array[i] = array[j];
+    array[j] = temp;
+  }
+};
+
+/**
+ * Decode the base64-encoded private key PEM and return the binary DER.
+ * @param {string} The PEM-encoded private key.
+ * @return {Buffer} The binary DER.
+ *
+ */
+DataUtils.privateKeyPemToDer = function(privateKeyPem)
+{
+  // Remove the '-----XXX-----' from the beginning and the end of the key and
+  // also remove any \n in the key string.
+  var lines = privateKeyPem.split('\n');
+  var privateKey = "";
+  for (var i = 1; i < lines.length - 1; i++)
+    privateKey += lines[i];
+
+  return new Buffer(privateKey, 'base64');
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a new DecodingException wrapping the given error object.
+ * Call with: throw new DecodingException(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+function DecodingException(error)
+{
+  if (error) {
+    error.__proto__ = DecodingException.prototype;
+    return error;
+  }
+}
+DecodingException.prototype = new Error();
+DecodingException.prototype.name = "DecodingException";
+
+exports.DecodingException = DecodingException;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * The Tlv class has static type codes for the NDN-TLV wire format.
+ * @constructor
+ */
+var Tlv = function Tlv()
+{
+};
+
+exports.Tlv = Tlv;
+
+Tlv.Interest =         5;
+Tlv.Data =             6;
+Tlv.Name =             7;
+Tlv.ImplicitSha256DigestComponent = 1;
+Tlv.NameComponent =    8;
+Tlv.Selectors =        9;
+Tlv.Nonce =            10;
+// <Unassigned> =      11;
+Tlv.InterestLifetime = 12;
+Tlv.MinSuffixComponents = 13;
+Tlv.MaxSuffixComponents = 14;
+Tlv.PublisherPublicKeyLocator = 15;
+Tlv.Exclude =          16;
+Tlv.ChildSelector =    17;
+Tlv.MustBeFresh =      18;
+Tlv.Any =              19;
+Tlv.MetaInfo =         20;
+Tlv.Content =          21;
+Tlv.SignatureInfo =    22;
+Tlv.SignatureValue =   23;
+Tlv.ContentType =      24;
+Tlv.FreshnessPeriod =  25;
+Tlv.FinalBlockId =     26;
+Tlv.SignatureType =    27;
+Tlv.KeyLocator =       28;
+Tlv.KeyLocatorDigest = 29;
+Tlv.SelectedDelegation = 32;
+Tlv.FaceInstance =     128;
+Tlv.ForwardingEntry =  129;
+Tlv.StatusResponse =   130;
+Tlv.Action =           131;
+Tlv.FaceID =           132;
+Tlv.IPProto =          133;
+Tlv.Host =             134;
+Tlv.Port =             135;
+Tlv.MulticastInterface = 136;
+Tlv.MulticastTTL =     137;
+Tlv.ForwardingFlags =  138;
+Tlv.StatusCode =       139;
+Tlv.StatusText =       140;
+
+Tlv.SignatureType_DigestSha256 = 0;
+Tlv.SignatureType_SignatureSha256WithRsa = 1;
+Tlv.SignatureType_SignatureSha256WithEcdsa = 3;
+Tlv.SignatureType_SignatureHmacWithSha256 = 4;
+
+Tlv.ContentType_Default = 0;
+Tlv.ContentType_Link =    1;
+Tlv.ContentType_Key =     2;
+
+Tlv.NfdCommand_ControlResponse = 101;
+Tlv.NfdCommand_StatusCode =      102;
+Tlv.NfdCommand_StatusText =      103;
+
+Tlv.ControlParameters_ControlParameters =   104;
+Tlv.ControlParameters_FaceId =              105;
+Tlv.ControlParameters_Uri =                 114;
+Tlv.ControlParameters_LocalControlFeature = 110;
+Tlv.ControlParameters_Origin =              111;
+Tlv.ControlParameters_Cost =                106;
+Tlv.ControlParameters_Flags =               108;
+Tlv.ControlParameters_Strategy =            107;
+Tlv.ControlParameters_ExpirationPeriod =    109;
+
+Tlv.LpPacket_LpPacket =        100;
+Tlv.LpPacket_Fragment =         80;
+Tlv.LpPacket_Sequence =         81;
+Tlv.LpPacket_FragIndex =        82;
+Tlv.LpPacket_FragCount =        83;
+Tlv.LpPacket_Nack =            800;
+Tlv.LpPacket_NackReason =      801;
+Tlv.LpPacket_NextHopFaceId =   816;
+Tlv.LpPacket_IncomingFaceId =  817;
+Tlv.LpPacket_CachePolicy =     820;
+Tlv.LpPacket_CachePolicyType = 821;
+Tlv.LpPacket_IGNORE_MIN =      800;
+Tlv.LpPacket_IGNORE_MAX =      959;
+
+Tlv.Link_Preference = 30;
+Tlv.Link_Delegation = 31;
+
+Tlv.Encrypt_EncryptedContent = 130;
+Tlv.Encrypt_EncryptionAlgorithm = 131;
+Tlv.Encrypt_EncryptedPayload = 132;
+Tlv.Encrypt_InitialVector = 133;
+
+// For RepetitiveInterval.
+Tlv.Encrypt_StartDate = 134;
+Tlv.Encrypt_EndDate = 135;
+Tlv.Encrypt_IntervalStartHour = 136;
+Tlv.Encrypt_IntervalEndHour = 137;
+Tlv.Encrypt_NRepeats = 138;
+Tlv.Encrypt_RepeatUnit = 139;
+Tlv.Encrypt_RepetitiveInterval = 140;
+
+// For Schedule.
+Tlv.Encrypt_WhiteIntervalList = 141;
+Tlv.Encrypt_BlackIntervalList = 142;
+Tlv.Encrypt_Schedule = 143;
+
+/**
+ * Strip off the lower 32 bits of x and divide by 2^32, returning the "high
+ * bytes" above 32 bits.  This is necessary because JavaScript << and >> are
+ * restricted to 32 bits.
+ * (This could be a general function, but we define it here so that the
+ * Tlv encoder/decoder is self-contained.)
+ * @param {number} x
+ * @return {number}
+ */
+Tlv.getHighBytes = function(x)
+{
+  // Don't use floor because we expect the caller to use & and >> on the result
+  // which already strip off the fraction.
+  return (x - (x % 0x100000000)) / 0x100000000;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DynamicBuffer = require('../../util/dynamic-buffer.js').DynamicBuffer; /** @ignore */
+var Tlv = require('./tlv.js').Tlv;
+
+/**
+ * Create a new TlvEncoder with an initialCapacity for the encoding buffer.
+ * @constructor
+ * @param {number} initialCapacity (optional) The initial capacity of the
+ * encoding buffer. If omitted, use a default value.
+ */
+var TlvEncoder = function TlvEncoder(initialCapacity)
+{
+  initialCapacity = initialCapacity || 16;
+  this.output = new DynamicBuffer(initialCapacity);
+  // length is the number of bytes that have been written to the back of
+  //  this.output.array.
+  this.length = 0;
+};
+
+exports.TlvEncoder = TlvEncoder;
+
+/**
+ * Get the number of bytes that have been written to the output.  You can
+ * save this number, write sub TLVs, then subtract the new length from this
+ * to get the total length of the sub TLVs.
+ * @return {number} The number of bytes that have been written to the output.
+ */
+TlvEncoder.prototype.getLength = function()
+{
+  return this.length;
+};
+
+/**
+ * Encode varNumber as a VAR-NUMBER in NDN-TLV and write it to this.output just
+ * before this.length from the back.  Advance this.length.
+ * @param {number} varNumber The non-negative number to encode.
+ */
+TlvEncoder.prototype.writeVarNumber = function(varNumber)
+{
+  if (varNumber < 253) {
+    this.length += 1;
+    this.output.ensureLengthFromBack(this.length);
+    this.output.array[this.output.array.length - this.length] = varNumber & 0xff;
+  }
+  else if (varNumber <= 0xffff) {
+    this.length += 3;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset] = 253;
+    this.output.array[offset + 1] = (varNumber >> 8) & 0xff;
+    this.output.array[offset + 2] = varNumber & 0xff;
+  }
+  else if (varNumber <= 0xffffffff) {
+    this.length += 5;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset] = 254;
+    this.output.array[offset + 1] = (varNumber >> 24) & 0xff;
+    this.output.array[offset + 2] = (varNumber >> 16) & 0xff;
+    this.output.array[offset + 3] = (varNumber >> 8) & 0xff;
+    this.output.array[offset + 4] = varNumber & 0xff;
+  }
+  else {
+    this.length += 9;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset] = 255;
+    var highBytes = Tlv.getHighBytes(varNumber);
+    this.output.array[offset + 1] = (highBytes >> 24) & 0xff;
+    this.output.array[offset + 2] = (highBytes >> 16) & 0xff;
+    this.output.array[offset + 3] = (highBytes >> 8)  & 0xff;
+    this.output.array[offset + 4] = (highBytes)       & 0xff;
+    this.output.array[offset + 5] = (varNumber >> 24) & 0xff;
+    this.output.array[offset + 6] = (varNumber >> 16) & 0xff;
+    this.output.array[offset + 7] = (varNumber >> 8) & 0xff;
+    this.output.array[offset + 8] = varNumber & 0xff;
+  }
+};
+
+/**
+ * Encode the type and length as VAR-NUMBER and write to this.output just before
+ * this.length from the back.  Advance this.length.
+ * @param {number} type The type of the TLV.
+ * @param {number} length The non-negative length of the TLV.
+ */
+TlvEncoder.prototype.writeTypeAndLength = function(type, length)
+{
+  // Write backwards.
+  this.writeVarNumber(length);
+  this.writeVarNumber(type);
+};
+
+/**
+ * Write value as a non-negative integer and write it to this.output just before
+ * this.length from the back. Advance this.length.
+ * @param {number} value The non-negative integer to encode.
+ */
+TlvEncoder.prototype.writeNonNegativeInteger = function(value)
+{
+  if (value < 0)
+    throw new Error("TLV integer value may not be negative");
+
+  // JavaScript doesn't distinguish int from float, so round.
+  value = Math.round(value);
+
+  if (value <= 0xff) {
+    this.length += 1;
+    this.output.ensureLengthFromBack(this.length);
+    this.output.array[this.output.array.length - this.length] = value & 0xff;
+  }
+  else if (value <= 0xffff) {
+    this.length += 2;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset]     = (value >> 8) & 0xff;
+    this.output.array[offset + 1] = value & 0xff;
+  }
+  else if (value <= 0xffffffff) {
+    this.length += 4;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset]     = (value >> 24) & 0xff;
+    this.output.array[offset + 1] = (value >> 16) & 0xff;
+    this.output.array[offset + 2] = (value >> 8) & 0xff;
+    this.output.array[offset + 3] = value & 0xff;
+  }
+  else {
+    this.length += 8;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    var highBytes = Tlv.getHighBytes(value);
+    this.output.array[offset]     = (highBytes >> 24) & 0xff;
+    this.output.array[offset + 1] = (highBytes >> 16) & 0xff;
+    this.output.array[offset + 2] = (highBytes >> 8)  & 0xff;
+    this.output.array[offset + 3] = (highBytes)       & 0xff;
+    this.output.array[offset + 4] = (value >> 24) & 0xff;
+    this.output.array[offset + 5] = (value >> 16) & 0xff;
+    this.output.array[offset + 6] = (value >> 8) & 0xff;
+    this.output.array[offset + 7] = value & 0xff;
+  }
+};
+
+/**
+ * Write the type, then the length of the encoded value then encode value as a
+ * non-negative integer and write it to this.output just before this.length from
+ * the back. Advance this.length.
+ * @param {number} type The type of the TLV.
+ * @param {number} value The non-negative integer to encode.
+ */
+TlvEncoder.prototype.writeNonNegativeIntegerTlv = function(type, value)
+{
+  // Write backwards.
+  var saveNBytes = this.length;
+  this.writeNonNegativeInteger(value);
+  this.writeTypeAndLength(type, this.length - saveNBytes);
+};
+
+/**
+ * If value is negative or null then do nothing, otherwise call
+ * writeNonNegativeIntegerTlv.
+ * @param {number} type The type of the TLV.
+ * @param {number} value If negative or null do nothing, otherwise the integer
+ *   to encode.
+ */
+TlvEncoder.prototype.writeOptionalNonNegativeIntegerTlv = function(type, value)
+{
+  if (value != null && value >= 0)
+    this.writeNonNegativeIntegerTlv(type, value);
+};
+
+/**
+ * Write the buffer value to this.output just before this.length from the back.
+ * Advance this.length.
+ * @param {Buffer} buffer The byte array with the bytes to write.  If value is
+ * null, then do nothing.
+ */
+TlvEncoder.prototype.writeBuffer = function(buffer)
+{
+  if (buffer == null)
+    return;
+
+  this.length += buffer.length;
+  this.output.copyFromBack(buffer, this.length);
+};
+
+/**
+ * Write the type, then the length of the buffer then the buffer value to
+ * this.output just before this.length from the back. Advance this.length.
+ * @param {number} type The type of the TLV.
+ * @param {Buffer} value The byte array with the bytes of the blob.  If value is
+    null, then just write the type and length 0.
+ */
+TlvEncoder.prototype.writeBlobTlv = function(type, value)
+{
+  if (value == null) {
+    this.writeTypeAndLength(type, 0);
+    return;
+  }
+
+  // Write backwards, starting with the blob array.
+  this.writeBuffer(value);
+  this.writeTypeAndLength(type, value.length);
+};
+
+/**
+ * If the byte array is null or zero length then do nothing, otherwise call
+ * writeBlobTlv.
+ * @param {number} type The type of the TLV.
+ * @param {Buffer} value If null or zero length do nothing, otherwise the byte
+ * array with the bytes of the blob.
+ */
+TlvEncoder.prototype.writeOptionalBlobTlv = function(type, value)
+{
+  if (value != null && value.length > 0)
+    this.writeBlobTlv(type, value);
+};
+
+/**
+ * Get a slice of the encoded bytes.
+ * @return {Buffer} A slice backed by the encoding Buffer.
+ */
+TlvEncoder.prototype.getOutput = function()
+{
+  return this.output.array.slice(this.output.array.length - this.length);
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DecodingException = require('../decoding-exception.js').DecodingException;
+
+/**
+ * Create a new TlvDecoder for decoding the input in the NDN-TLV wire format.
+ * @constructor
+ * @param {Buffer} input The buffer with the bytes to decode.
+ */
+var TlvDecoder = function TlvDecoder(input)
+{
+  this.input = input;
+  this.offset = 0;
+};
+
+exports.TlvDecoder = TlvDecoder;
+
+/**
+ * Decode VAR-NUMBER in NDN-TLV and return it. Update offset.
+ * @return {number} The decoded VAR-NUMBER.
+ */
+TlvDecoder.prototype.readVarNumber = function()
+{
+  // Assume array values are in the range 0 to 255.
+  var firstOctet = this.input[this.offset];
+  this.offset += 1;
+  if (firstOctet < 253)
+    return firstOctet;
+  else
+    return this.readExtendedVarNumber(firstOctet);
+};
+
+/**
+ * A private function to do the work of readVarNumber, given the firstOctet
+ * which is >= 253.
+ * @param {number} firstOctet The first octet which is >= 253, used to decode
+ * the remaining bytes.
+ * @return {number} The decoded VAR-NUMBER.
+ */
+TlvDecoder.prototype.readExtendedVarNumber = function(firstOctet)
+{
+  var result;
+  // This is a private function so we know firstOctet >= 253.
+  if (firstOctet == 253) {
+    result = ((this.input[this.offset] << 8) +
+           this.input[this.offset + 1]);
+    this.offset += 2;
+  }
+  else if (firstOctet == 254) {
+    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
+    result = (Math.abs(this.input[this.offset] << 24) +
+          (this.input[this.offset + 1] << 16) +
+          (this.input[this.offset + 2] << 8) +
+           this.input[this.offset + 3]);
+    this.offset += 4;
+  }
+  else {
+    // Get the high byte first because JavaScript << is restricted to 32 bits.
+    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
+    var highByte = Math.abs(this.input[this.offset] << 24) +
+                           (this.input[this.offset + 1] << 16) +
+                           (this.input[this.offset + 2] << 8) +
+                            this.input[this.offset + 3];
+    result = (highByte * 0x100000000 +
+          (this.input[this.offset + 4] << 24) +
+          (this.input[this.offset + 5] << 16) +
+          (this.input[this.offset + 6] << 8) +
+           this.input[this.offset + 7]);
+    this.offset += 8;
+  }
+
+  return result;
+};
+
+/**
+ * Decode the type and length from this's input starting at offset, expecting
+ * the type to be expectedType and return the length. Update offset.  Also make
+ * sure the decoded length does not exceed the number of bytes remaining in the
+ * input.
+ * @param {number} expectedType The expected type.
+ * @return {number} The length of the TLV.
+ * @throws DecodingException if (did not get the expected TLV type or the TLV length
+ * exceeds the buffer length.
+ */
+TlvDecoder.prototype.readTypeAndLength = function(expectedType)
+{
+  var type = this.readVarNumber();
+  if (type != expectedType)
+    throw new DecodingException(new Error("Did not get the expected TLV type"));
+
+  var length = this.readVarNumber();
+  if (this.offset + length > this.input.length)
+    throw new DecodingException(new Error("TLV length exceeds the buffer length"));
+
+  return length;
+};
+
+/**
+ * Decode the type and length from the input starting at offset, expecting the
+ * type to be expectedType.  Update offset.  Also make sure the decoded length
+ * does not exceed the number of bytes remaining in the input. Return the offset
+ * of the end of this parent TLV, which is used in decoding optional nested
+ * TLVs. After reading all nested TLVs, call finishNestedTlvs.
+ * @param {number} expectedType The expected type.
+ * @return {number} The offset of the end of the parent TLV.
+ * @throws DecodingException if did not get the expected TLV type or the TLV
+ * length exceeds the buffer length.
+ */
+TlvDecoder.prototype.readNestedTlvsStart = function(expectedType)
+{
+  return this.readTypeAndLength(expectedType) + this.offset;
+};
+
+/**
+ * Call this after reading all nested TLVs to skip any remaining unrecognized
+ * TLVs and to check if the offset after the final nested TLV matches the
+ * endOffset returned by readNestedTlvsStart.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @throws DecodingException if the TLV length does not equal the total length
+ * of the nested TLVs.
+ */
+TlvDecoder.prototype.finishNestedTlvs = function(endOffset)
+{
+  // We expect offset to be endOffset, so check this first.
+  if (this.offset == endOffset)
+    return;
+
+  // Skip remaining TLVs.
+  while (this.offset < endOffset) {
+    // Skip the type VAR-NUMBER.
+    this.readVarNumber();
+    // Read the length and update offset.
+    var length = this.readVarNumber();
+    this.offset += length;
+
+    if (this.offset > this.input.length)
+      throw new DecodingException(new Error("TLV length exceeds the buffer length"));
+  }
+
+  if (this.offset != endOffset)
+    throw new DecodingException(new Error
+      ("TLV length does not equal the total length of the nested TLVs"));
+};
+
+/**
+ * Decode the type from this's input starting at offset, and if it is the
+ * expectedType, then return true, else false.  However, if this's offset is
+ * greater than or equal to endOffset, then return false and don't try to read
+ * the type. Do not update offset.
+ * @param {number} expectedType The expected type.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @return {boolean} true if the type of the next TLV is the expectedType,
+ *  otherwise false.
+ */
+TlvDecoder.prototype.peekType = function(expectedType, endOffset)
+{
+  if (this.offset >= endOffset)
+    // No more sub TLVs to look at.
+    return false;
+  else {
+    var saveOffset = this.offset;
+    var type = this.readVarNumber();
+    // Restore offset.
+    this.offset = saveOffset;
+
+    return type == expectedType;
+  }
+};
+
+/**
+ * Decode a non-negative integer in NDN-TLV and return it. Update offset by
+ * length.
+ * @param {number} length The number of bytes in the encoded integer.
+ * @return {number} The integer.
+ * @throws DecodingException if length is an invalid length for a TLV
+ * non-negative integer.
+ */
+TlvDecoder.prototype.readNonNegativeInteger = function(length)
+{
+  var result;
+  if (length == 1)
+    result = this.input[this.offset];
+  else if (length == 2)
+    result = ((this.input[this.offset] << 8) +
+           this.input[this.offset + 1]);
+  else if (length == 4)
+    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
+    result = (Math.abs(this.input[this.offset] << 24) +
+          (this.input[this.offset + 1] << 16) +
+          (this.input[this.offset + 2] << 8) +
+           this.input[this.offset + 3]);
+  else if (length == 8) {
+    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
+    var highByte = Math.abs(this.input[this.offset] << 24) +
+                       (this.input[this.offset + 1] << 16) +
+                       (this.input[this.offset + 2] << 8) +
+                        this.input[this.offset + 3];
+    result = (highByte * 0x100000000 +
+          Math.abs(this.input[this.offset + 4] << 24) +
+          (this.input[this.offset + 5] << 16) +
+          (this.input[this.offset + 6] << 8) +
+           this.input[this.offset + 7]);
+  }
+  else
+    throw new DecodingException(new Error("Invalid length for a TLV nonNegativeInteger"));
+
+  this.offset += length;
+  return result;
+};
+
+/**
+ * Decode the type and length from this's input starting at offset, expecting
+ * the type to be expectedType. Then decode a non-negative integer in NDN-TLV
+ * and return it.  Update offset.
+ * @param {number} expectedType The expected type.
+ * @return {number} The integer.
+ * @throws DecodingException if did not get the expected TLV type or can't
+ * decode the value.
+ */
+TlvDecoder.prototype.readNonNegativeIntegerTlv = function(expectedType)
+{
+  var length = this.readTypeAndLength(expectedType);
+  return this.readNonNegativeInteger(length);
+};
+
+/**
+ * Peek at the next TLV, and if it has the expectedType then call
+ * readNonNegativeIntegerTlv and return the integer.  Otherwise, return null.
+ * However, if this's offset is greater than or equal to endOffset, then return
+ * null and don't try to read the type.
+ * @param {number} expectedType The expected type.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @return {number} The integer or null if the next TLV doesn't have the
+ * expected type.
+ */
+TlvDecoder.prototype.readOptionalNonNegativeIntegerTlv = function
+  (expectedType, endOffset)
+{
+  if (this.peekType(expectedType, endOffset))
+    return this.readNonNegativeIntegerTlv(expectedType);
+  else
+    return null;
+};
+
+/**
+ * Decode the type and length from this's input starting at offset, expecting
+ * the type to be expectedType. Then return an array of the bytes in the value.
+ * Update offset.
+ * @param {number} expectedType The expected type.
+ * @return {Buffer} The bytes in the value as a slice on the buffer.  This is
+ * not a copy of the bytes in the input buffer.  If you need a copy, then you
+ * must make a copy of the return value.
+ * @throws DecodingException if did not get the expected TLV type.
+ */
+TlvDecoder.prototype.readBlobTlv = function(expectedType)
+{
+  var length = this.readTypeAndLength(expectedType);
+  var result = this.input.slice(this.offset, this.offset + length);
+
+  // readTypeAndLength already checked if length exceeds the input buffer.
+  this.offset += length;
+  return result;
+};
+
+/**
+ * Peek at the next TLV, and if it has the expectedType then call readBlobTlv
+ * and return the value.  Otherwise, return null. However, if this's offset is
+ * greater than or equal to endOffset, then return null and don't try to read
+ * the type.
+ * @param {number} expectedType The expected type.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @return {Buffer} The bytes in the value as a slice on the buffer or null if
+ * the next TLV doesn't have the expected type.  This is not a copy of the bytes
+ * in the input buffer.  If you need a copy, then you must make a copy of the
+ * return value.
+ */
+TlvDecoder.prototype.readOptionalBlobTlv = function(expectedType, endOffset)
+{
+  if (this.peekType(expectedType, endOffset))
+    return this.readBlobTlv(expectedType);
+  else
+    return null;
+};
+
+/**
+ * Peek at the next TLV, and if it has the expectedType then read a type and
+ * value, ignoring the value, and return true. Otherwise, return false.
+ * However, if this's offset is greater than or equal to endOffset, then return
+ * false and don't try to read the type.
+ * @param {number} expectedType The expected type.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @return {boolean} true, or else false if the next TLV doesn't have the
+ * expected type.
+ */
+TlvDecoder.prototype.readBooleanTlv = function(expectedType, endOffset)
+{
+  if (this.peekType(expectedType, endOffset)) {
+    var length = this.readTypeAndLength(expectedType);
+    // We expect the length to be 0, but update offset anyway.
+    this.offset += length;
+    return true;
+  }
+  else
+    return false;
+};
+
+/**
+ * Get the offset into the input, used for the next read.
+ * @return {number} The offset.
+ */
+TlvDecoder.prototype.getOffset = function()
+{
+  return this.offset;
+};
+
+/**
+ * Set the offset into the input, used for the next read.
+ * @param {number} offset The new offset.
+ */
+TlvDecoder.prototype.seek = function(offset)
+{
+  this.offset = offset;
+};
+
+/**
+ * Return an array of a slice of the input for the given offset range.
+ * @param {number} beginOffset The offset in the input of the beginning of the
+ * slice.
+ * @param {number} endOffset The offset in the input of the end of the slice.
+ * @return {Buffer} The bytes in the value as a slice on the buffer.  This is
+ * not a copy of the bytes in the input buffer.  If you need a copy, then you
+ * must make a copy of the return value.
+ */
+TlvDecoder.prototype.getSlice = function(beginOffset, endOffset)
+{
+  return this.input.slice(beginOffset, endOffset);
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var TlvDecoder = require('./tlv-decoder.js').TlvDecoder;
+
+/**
+ * A TlvStructureDecoder finds the end of an NDN-TLV element, even if the
+ * element is supplied in parts.
+ * Create and initialize a TlvStructureDecoder.
+ * @constructor
+ */
+var TlvStructureDecoder = function TlvStructureDecoder()
+{
+  this.gotElementEnd_ = false;
+  this.offset_ = 0;
+  this.state_ = TlvStructureDecoder.READ_TYPE;
+  this.headerLength_ = 0;
+  this.useHeaderBuffer_ = false;
+  // 8 bytes is enough to hold the extended bytes in the length encoding
+  // where it is an 8-byte number.
+  this.headerBuffer_ = new Buffer(8);
+  this.nBytesToRead_ = 0;
+};
+
+exports.TlvStructureDecoder = TlvStructureDecoder;
+
+TlvStructureDecoder.READ_TYPE =         0;
+TlvStructureDecoder.READ_TYPE_BYTES =   1;
+TlvStructureDecoder.READ_LENGTH =       2;
+TlvStructureDecoder.READ_LENGTH_BYTES = 3;
+TlvStructureDecoder.READ_VALUE_BYTES =  4;
+
+/**
+ * Continue scanning input starting from this.offset_ to find the element end.
+ * If the end of the element which started at offset 0 is found, this returns
+ * true and getOffset() is the length of the element.  Otherwise, this returns
+ * false which means you should read more into input and call again.
+ * @param {Buffer} input The input buffer. You have to pass in input each time
+ * because the buffer could be reallocated.
+ * @return {boolean} true if found the element end, false if not.
+ */
+TlvStructureDecoder.prototype.findElementEnd = function(input)
+{
+  if (this.gotElementEnd_)
+    // Someone is calling when we already got the end.
+    return true;
+
+  var decoder = new TlvDecoder(input);
+
+  while (true) {
+    if (this.offset_ >= input.length)
+      // All the cases assume we have some input. Return and wait for more.
+      return false;
+
+    if (this.state_ == TlvStructureDecoder.READ_TYPE) {
+      var firstOctet = input[this.offset_];
+      this.offset_ += 1;
+      if (firstOctet < 253)
+        // The value is simple, so we can skip straight to reading the length.
+        this.state_ = TlvStructureDecoder.READ_LENGTH;
+      else {
+        // Set up to skip the type bytes.
+        if (firstOctet == 253)
+          this.nBytesToRead_ = 2;
+        else if (firstOctet == 254)
+          this.nBytesToRead_ = 4;
+        else
+          // value == 255.
+          this.nBytesToRead_ = 8;
+
+        this.state_ = TlvStructureDecoder.READ_TYPE_BYTES;
+      }
+    }
+    else if (this.state_ == TlvStructureDecoder.READ_TYPE_BYTES) {
+      var nRemainingBytes = input.length - this.offset_;
+      if (nRemainingBytes < this.nBytesToRead_) {
+        // Need more.
+        this.offset_ += nRemainingBytes;
+        this.nBytesToRead_ -= nRemainingBytes;
+        return false;
+      }
+
+      // Got the type bytes. Move on to read the length.
+      this.offset_ += this.nBytesToRead_;
+      this.state_ = TlvStructureDecoder.READ_LENGTH;
+    }
+    else if (this.state_ == TlvStructureDecoder.READ_LENGTH) {
+      var firstOctet = input[this.offset_];
+      this.offset_ += 1;
+      if (firstOctet < 253) {
+        // The value is simple, so we can skip straight to reading
+        //  the value bytes.
+        this.nBytesToRead_ = firstOctet;
+        if (this.nBytesToRead_ == 0) {
+          // No value bytes to read. We're finished.
+          this.gotElementEnd_ = true;
+          return true;
+        }
+
+        this.state_ = TlvStructureDecoder.READ_VALUE_BYTES;
+      }
+      else {
+        // We need to read the bytes in the extended encoding of
+        //  the length.
+        if (firstOctet == 253)
+          this.nBytesToRead_ = 2;
+        else if (firstOctet == 254)
+          this.nBytesToRead_ = 4;
+        else
+          // value == 255.
+          this.nBytesToRead_ = 8;
+
+        // We need to use firstOctet in the next state.
+        this.firstOctet_ = firstOctet;
+        this.state_ = TlvStructureDecoder.READ_LENGTH_BYTES;
+      }
+    }
+    else if (this.state_ == TlvStructureDecoder.READ_LENGTH_BYTES) {
+      var nRemainingBytes = input.length - this.offset_;
+      if (!this.useHeaderBuffer_ && nRemainingBytes >= this.nBytesToRead_) {
+        // We don't have to use the headerBuffer. Set nBytesToRead.
+        decoder.seek(this.offset_);
+
+        this.nBytesToRead_ = decoder.readExtendedVarNumber(this.firstOctet_);
+        // Update this.offset_ to the decoder's offset after reading.
+        this.offset_ = decoder.getOffset();
+      }
+      else {
+        this.useHeaderBuffer_ = true;
+
+        var nNeededBytes = this.nBytesToRead_ - this.headerLength_;
+        if (nNeededBytes > nRemainingBytes) {
+          // We can't get all of the header bytes from this input.
+          // Save in headerBuffer.
+          if (this.headerLength_ + nRemainingBytes > this.headerBuffer_.length)
+            // We don't expect this to happen.
+            throw new Error
+              ("Cannot store more header bytes than the size of headerBuffer");
+          input.slice(this.offset_, this.offset_ + nRemainingBytes).copy
+            (this.headerBuffer_, this.headerLength_);
+          this.offset_ += nRemainingBytes;
+          this.headerLength_ += nRemainingBytes;
+
+          return false;
+        }
+
+        // Copy the remaining bytes into headerBuffer, read the
+        //   length and set nBytesToRead.
+        if (this.headerLength_ + nNeededBytes > this.headerBuffer_.length)
+          // We don't expect this to happen.
+          throw new Error
+            ("Cannot store more header bytes than the size of headerBuffer");
+        input.slice(this.offset_, this.offset_ + nNeededBytes).copy
+          (this.headerBuffer_, this.headerLength_);
+        this.offset_ += nNeededBytes;
+
+        // Use a local decoder just for the headerBuffer.
+        var bufferDecoder = new TlvDecoder(this.headerBuffer_);
+        // Replace nBytesToRead with the length of the value.
+        this.nBytesToRead_ = bufferDecoder.readExtendedVarNumber(this.firstOctet_);
+      }
+
+      if (this.nBytesToRead_ == 0) {
+        // No value bytes to read. We're finished.
+        this.gotElementEnd_ = true;
+        return true;
+      }
+
+      // Get ready to read the value bytes.
+      this.state_ = TlvStructureDecoder.READ_VALUE_BYTES;
+    }
+    else if (this.state_ == TlvStructureDecoder.READ_VALUE_BYTES) {
+      var nRemainingBytes = input.length - this.offset_;
+      if (nRemainingBytes < this.nBytesToRead_) {
+        // Need more.
+        this.offset_ += nRemainingBytes;
+        this.nBytesToRead_ -= nRemainingBytes;
+        return false;
+      }
+
+      // Got the bytes. We're finished.
+      this.offset_ += this.nBytesToRead_;
+      this.gotElementEnd_ = true;
+      return true;
+    }
+    else
+      // We don't expect this to happen.
+      throw new Error("findElementEnd: unrecognized state");
+  }
+};
+
+/**
+ * Get the current offset into the input buffer.
+ * @return {number} The offset.
+ */
+TlvStructureDecoder.prototype.getOffset = function()
+{
+  return this.offset_;
+};
+
+/**
+ * Set the offset into the input, used for the next read.
+ * @param {number} offset The new offset.
+ */
+TlvStructureDecoder.prototype.seek = function(offset)
+{
+  this.offset_ = offset;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var TlvEncoder = require('./tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
+var TlvDecoder = require('./tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+
+/**
+ * ProtobufTlv has static methods to encode and decode an Protobuf Message
+ * object as NDN-TLV. The Protobuf tag value is used as the TLV type code. A
+ * Protobuf message is encoded/decoded as a nested TLV encoding. Protobuf types
+ * uint32, uint64 and enum are encoded/decoded as TLV nonNegativeInteger. (It is
+ * an error if an enum value is negative.) Protobuf types bytes and string are
+ * encoded/decoded as TLV bytes. The Protobuf type bool is encoded/decoded as a
+ * TLV boolean (a zero length value for True, omitted for False). The Protobuf
+ * type double is encoded/decoded as an 8-byte little-endian IEEE 754 double.
+ * Other Protobuf types are an error.
+ *
+ * Protobuf has no "outer" message type, so you need to put your TLV message
+ * inside an outer "typeless" message.
+ * @constructor
+ */
+var ProtobufTlv = function ProtobufTlv()
+{
+};
+
+exports.ProtobufTlv = ProtobufTlv;
+
+// Load ProtoBuf.Reflect.Message.Field dynamically so that protobufjs is optional.
+ProtobufTlv._Field = null;
+ProtobufTlv.establishField = function()
+{
+  if (ProtobufTlv._Field === null) {
     try {
-        var dummy = new Uint8Array(1).subarray(0, 1);
+      // Using protobuf.min.js in the browser.
+      ProtobufTlv._Field = dcodeIO.ProtoBuf.Reflect.Message.Field;
+    }
+    catch (ex) {
+      // Using protobufjs in node.
+      ProtobufTlv._Field = require("protobufjs").Reflect.Message.Field;
+    }
+  }
+}
+
+/**
+ * Encode the Protobuf message object as NDN-TLV. This calls
+ * message.encodeAB() to ensure that all required fields are present and
+ * raises an exception if not. (This does not use the result of toArrayBuffer().)
+ * @param {ProtoBuf.Builder.Message} message The Protobuf message object.
+ * @param {ProtoBuf.Reflect.T} descriptor The reflection descriptor for the
+ * message. For example, if the message is of type "MyNamespace.MyMessage" then
+ * the descriptor is builder.lookup("MyNamespace.MyMessage").
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+ProtobufTlv.encode = function(message, descriptor)
+{
+  ProtobufTlv.establishField();
+
+  message.encodeAB();
+  var encoder = new TlvEncoder();
+  ProtobufTlv._encodeMessageValue(message, descriptor, encoder);
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode the input as NDN-TLV and update the fields of the Protobuf message
+ * object.
+ * @param {ProtoBuf.Builder.Message} message The Protobuf message object. This
+ * does not first clear the object.
+ * @param {ProtoBuf.Reflect.T} descriptor The reflection descriptor for the
+ * message. For example, if the message is of type "MyNamespace.MyMessage" then
+ * the descriptor is builder.lookup("MyNamespace.MyMessage").
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ */
+ProtobufTlv.decode = function(message, descriptor, input)
+{
+  ProtobufTlv.establishField();
+
+  // If input is a blob, get its buf().
+  var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
+                     input.buf() : input;
+
+  var decoder = new TlvDecoder(decodeBuffer);
+  ProtobufTlv._decodeMessageValue
+    (message, descriptor, decoder, decodeBuffer.length);
+};
+
+ProtobufTlv._encodeMessageValue = function(message, descriptor, encoder)
+{
+  var fields = descriptor.getChildren(ProtobufTlv._Field);
+  // Encode the fields backwards.
+  for (var iField = fields.length - 1; iField >= 0; --iField) {
+    var field = fields[iField];
+    var tlvType = field.id;
+
+    var values;
+    if (field.repeated)
+      values = message[field.name];
+    else {
+      if (message[field.name] != null)
+        // Make a singleton list.
+        values = [message[field.name]];
+      else
+        continue;
+    }
+
+    // Encode the values backwards.
+    for (var iValue = values.length - 1; iValue >= 0; --iValue) {
+      var value = values[iValue];
+
+      if (field.type.name == "message") {
+        var saveLength =  encoder.getLength();
+
+        // Encode backwards.
+        ProtobufTlv._encodeMessageValue(value, field.resolvedType, encoder);
+        encoder.writeTypeAndLength(tlvType, encoder.getLength() - saveLength);
+      }
+      else if (field.type.name == "uint32" ||
+               field.type.name == "uint64")
+        encoder.writeNonNegativeIntegerTlv(tlvType, value);
+      else if (field.type.name == "enum") {
+        if (value < 0)
+          throw new Error("ProtobufTlv::encode: ENUM value may not be negative");
+        encoder.writeNonNegativeIntegerTlv(tlvType, value);
+      }
+      else if (field.type.name == "bytes") {
+        var buffer = value.toBuffer();
+        if (buffer.length == undefined)
+          // We are not running in Node.js, so assume we are using the dcodeIO
+          // browser implementation based on ArrayBuffer.
+          buffer = new Uint8Array(value.toArrayBuffer());
+        encoder.writeBlobTlv(tlvType, buffer);
+      }
+      else if (field.type.name == "string")
+        // Use Blob to convert.
+        encoder.writeBlobTlv(tlvType, new Blob(value, false).buf());
+      else if (field.type.name == "bool") {
+        if (value)
+          encoder.writeTypeAndLength(tlvType, 0);
+      }
+      else if (field.type.name == "double") {
+        var encoding = new Buffer(8);
+        encoding.writeDoubleLE(value, 0);
+        encoder.writeBlobTlv(tlvType, encoding);
+      }
+      else
+        throw new Error("ProtobufTlv::encode: Unknown field type");
+    }
+  }
+};
+
+ProtobufTlv._decodeMessageValue = function(message, descriptor, decoder, endOffset)
+{
+  var fields = descriptor.getChildren(ProtobufTlv._Field);
+  for (var iField = 0; iField < fields.length; ++iField) {
+    var field = fields[iField];
+    var tlvType = field.id;
+
+    if (!field.required && !decoder.peekType(tlvType, endOffset))
+      continue;
+
+    if (field.repeated) {
+      while (decoder.peekType(tlvType, endOffset)) {
+        if (field.type.name == "message") {
+          var innerEndOffset = decoder.readNestedTlvsStart(tlvType);
+          var value = new (field.resolvedType.build())();
+          message.add(field.name, value);
+          ProtobufTlv._decodeMessageValue
+            (value, field.resolvedType, decoder, innerEndOffset);
+          decoder.finishNestedTlvs(innerEndOffset);
+        }
+        else
+          message.add
+            (field.name,
+             ProtobufTlv._decodeFieldValue(field, tlvType, decoder, endOffset));
+      }
+    }
+    else {
+      if (field.type.name == "message") {
+        var innerEndOffset = decoder.readNestedTlvsStart(tlvType);
+        var value = new (field.resolvedType.build())();
+        message.set(field.name, value);
+        ProtobufTlv._decodeMessageValue
+          (value, field.resolvedType, decoder, innerEndOffset);
+        decoder.finishNestedTlvs(innerEndOffset);
+      }
+      else
+        message.set
+          (field.name,
+           ProtobufTlv._decodeFieldValue(field, tlvType, decoder, endOffset));
+    }
+  }
+};
+
+/**
+ * This is a helper for _decodeMessageValue. Decode a single field and return
+ * the value. Assume the field.type.name is not "message".
+ */
+ProtobufTlv._decodeFieldValue = function(field, tlvType, decoder, endOffset)
+{
+  if (field.type.name == "uint32" ||
+      field.type.name == "uint64" ||
+      field.type.name == "enum")
+    return decoder.readNonNegativeIntegerTlv(tlvType);
+  else if (field.type.name == "bytes")
+    return decoder.readBlobTlv(tlvType);
+  else if (field.type.name == "string")
+    return decoder.readBlobTlv(tlvType).toString();
+  else if (field.type.name == "bool")
+    return decoder.readBooleanTlv(tlvType, endOffset);
+  else if (field.type.name == "double")
+    return decoder.readBlobTlv(tlvType).readDoubleLE(0);
+  else
+    throw new Error("ProtobufTlv.decode: Unknown field type");
+};
+
+/**
+ * Return a Name made from the component array in a Protobuf message object,
+ * assuming that it was defined with "repeated bytes". For example:
+ * message Name {
+ *   repeated bytes component = 8;
+ * }
+ * @param {Array} componentArray The array from the Protobuf message object
+ * representing the "repeated bytes" component array.
+ * @return A new Name.
+ */
+ProtobufTlv.toName = function(componentArray)
+{
+  var name = new Name();
+  for (var i = 0; i < componentArray.length; ++i)
+    name.append
+      (new Blob(new Buffer(componentArray[i].toBinary(), "binary")), false);
+
+  return name;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * @constructor
+ */
+var OID = function OID(oid)
+{
+  if (typeof oid === 'string') {
+    var splitString = oid.split(".");
+    this.oid = [];
+    for (var i = 0; i < splitString.length; ++i)
+      this.oid.push(parseInt(splitString[i]));
+  }
+  else
+    // Assume oid is an array of int.  Make a copy.
+    this.oid = oid.slice(0, oid.length);
+};
+
+exports.OID = OID;
+
+OID.prototype.getIntegerList = function()
+{
+  return this.oid;
+};
+
+OID.prototype.setIntegerList = function(oid)
+{
+  // Make a copy.
+  this.oid = oid.slice(0, oid.length);
+};
+
+OID.prototype.toString = function()
+{
+  var result = "";
+  for (var i = 0; i < this.oid.length; ++i) {
+    if (i !== 0)
+      result += ".";
+    result += this.oid[i];
+  }
+
+  return result;
+};
+
+OID.prototype.equals = function(other)
+{
+  if (!(other instanceof OID))
+    return false;
+  if (this.oid.length !== other.oid.length)
+    return false;
+
+  for (var i = 0; i < this.oid.length; ++i) {
+    if (this.oid[i] != other.oid[i])
+      return false;
+  }
+  return true;
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a WireFormat base class where the encode and decode methods throw an error. You should use a derived class like TlvWireFormat.
+ * @constructor
+ */
+var WireFormat = function WireFormat() {
+};
+
+exports.WireFormat = WireFormat;
+
+/**
+ * Encode name and return the encoding.  Your derived class should override.
+ * @param {Name} name The Name to encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeName = function(name)
+{
+  throw new Error("encodeName is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as a name and set the fields of the Name object.
+ * Your derived class should override.
+ * @param {Name} name The Name object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeName = function(name, input, copy)
+{
+  throw new Error("decodeName is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode interest and return the encoding.  Your derived class should override.
+ * @param {Interest} interest The Interest to encode.
+ * @return {object} An associative array with fields
+ * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
+ * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
+ * the encoding of the beginning of the signed portion, and
+ * signedPortionEndOffset is the offset in the encoding of the end of the signed
+ * portion. The signed portion starts from the first name component and ends
+ * just before the final name component (which is assumed to be a signature for
+ * a signed interest).
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeInterest = function(interest)
+{
+  throw new Error("encodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as an interest and set the fields of the interest object.
+ * Your derived class should override.
+ * @param {Interest} interest The Interest object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion. The signed portion starts from the first
+ * name component and ends just before the final name component (which is
+ * assumed to be a signature for a signed interest).
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeInterest = function(interest, input, copy)
+{
+  throw new Error("decodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode data and return the encoding and signed offsets. Your derived class
+ * should override.
+ * @param {Data} data The Data object to encode.
+ * @return {object} An associative array with fields
+ * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
+ * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
+ * the encoding of the beginning of the signed portion, and
+ * signedPortionEndOffset is the offset in the encoding of the end of the
+ * signed portion.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeData = function(data)
+{
+  throw new Error("encodeData is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as a data packet, set the fields in the data object, and return
+ * the signed offsets.  Your derived class should override.
+ * @param {Data} data The Data object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeData = function(data, input, copy)
+{
+  throw new Error("decodeData is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode controlParameters and return the encoding.  Your derived class should
+ * override.
+ * @param {ControlParameters} controlParameters The ControlParameters object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeControlParameters = function(controlParameters)
+{
+  throw new Error("encodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as a controlParameters and set the fields of the
+ * controlParameters object. Your derived class should override.
+ * @param {ControlParameters} controlParameters The ControlParameters object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeControlParameters = function
+  (controlParameters, input, copy)
+{
+  throw new Error("decodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode controlResponse and return the encoding.  Your derived class should
+ * override.
+ * @param {ControlResponse} controlResponse The ControlResponse object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeControlResponse = function(controlResponse)
+{
+  throw new Error("encodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as a controlResponse and set the fields of the
+ * controlResponse object. Your derived class should override.
+ * @param {ControlResponse} controlResponse The ControlResponse object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeControlResponse = function
+  (controlResponse, input, copy)
+{
+  throw new Error("decodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode signature as a SignatureInfo and return the encoding. Your derived
+ * class should override.
+ * @param {Signature} signature An object of a subclass of Signature to encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeSignatureInfo = function(signature)
+{
+  throw new Error("encodeSignatureInfo is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode signatureInfo as a signature info and signatureValue as the related
+ * SignatureValue, and return a new object which is a subclass of Signature.
+ * Your derived class should override.
+ * @param {Buffer} signatureInfo The buffer with the signature info bytes to
+ * decode.
+ * @param {Buffer} signatureValue The buffer with the signature value to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {Signature} A new object which is a subclass of Signature.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeSignatureInfoAndValue = function
+  (signatureInfo, signatureValue, copy)
+{
+  throw new Error("decodeSignatureInfoAndValue is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode the signatureValue in the Signature object as a SignatureValue (the
+ * signature bits) and return the encoding. Your derived class should override.
+ * @param {Signature} signature An object of a subclass of Signature with the
+ * signature value to encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeSignatureValue = function(signature)
+{
+  throw new Error("encodeSignatureValue is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object.
+ * Your derived class should override.
+ * @param {LpPacket} lpPacket The LpPacket object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.decodeLpPacket = function(lpPacket, input, copy)
+{
+  throw new Error
+    ("decodeLpPacket is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Encode the DelegationSet and return the encoding.  Your derived class
+ * should override.
+ * @param {DelegationSet} delegationSet The DelegationSet object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.encodeDelegationSet = function(delegationSet)
+{
+  throw new Error
+    ("encodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Decode input as an DelegationSet and set the fields of the
+ * delegationSet object. Your derived class should override.
+ * @param {DelegationSet} delegationSet The DelegationSet object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.decodeDelegationSet = function(delegationSet, input, copy)
+{
+  throw new Error
+    ("decodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Encode the EncryptedContent and return the encoding.  Your derived class
+ * should override.
+ * @param {EncryptedContent} encryptedContent The EncryptedContent object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.encodeEncryptedContent = function(encryptedContent)
+{
+  throw new Error
+    ("encodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Decode input as an EncryptedContent and set the fields of the
+ * encryptedContent object. Your derived class should override.
+ * @param {EncryptedContent} encryptedContent The EncryptedContent object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.decodeEncryptedContent = function
+  (encryptedContent, input, copy)
+{
+  throw new Error
+    ("decodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Set the static default WireFormat used by default encoding and decoding
+ * methods.
+ * @param {WireFormat} wireFormat An object of a subclass of WireFormat.
+ */
+WireFormat.setDefaultWireFormat = function(wireFormat)
+{
+  WireFormat.defaultWireFormat = wireFormat;
+};
+
+/**
+ * Return the default WireFormat used by default encoding and decoding methods
+ * which was set with setDefaultWireFormat.
+ * @return {WireFormat} An object of a subclass of WireFormat.
+ */
+WireFormat.getDefaultWireFormat = function()
+{
+  return WireFormat.defaultWireFormat;
+};
+
+// Invoke TlvWireFormat to set the default format.
+// Since tlv-wire-format.js includes this file, put this at the bottom
+// to avoid problems with cycles of require.
+var TlvWireFormat = require('./tlv-wire-format.js').TlvWireFormat;
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DataUtils = require('./data-utils.js').DataUtils; /** @ignore */
+var Tlv = require('./tlv/tlv.js').Tlv; /** @ignore */
+var TlvStructureDecoder = require('./tlv/tlv-structure-decoder.js').TlvStructureDecoder; /** @ignore */
+var DecodingException = require('./decoding-exception.js').DecodingException; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * A ElementReader lets you call onReceivedData multiple times which uses a
+ * TlvStructureDecoder to detect the end of a TLV element and calls
+ * elementListener.onReceivedElement(element) with the element.  This handles
+ * the case where a single call to onReceivedData may contain multiple elements.
+ * @constructor
+ * @param {object} elementListener An object with an onReceivedElement method.
+ */
+var ElementReader = function ElementReader(elementListener)
+{
+  this.elementListener_ = elementListener;
+  this.dataParts_ = [];
+  this.tlvStructureDecoder_ = new TlvStructureDecoder();
+};
+
+exports.ElementReader = ElementReader;
+
+/**
+ * Continue to read data until the end of an element, then call
+ * this.elementListener_.onReceivedElement(element). The buffer passed to
+ * onReceivedElement is only valid during this call.  If you need the data
+ * later, you must copy.
+ * @param {Buffer} data The Buffer with the incoming element's bytes.
+ */
+ElementReader.prototype.onReceivedData = function(data)
+{
+  // Process multiple elements in the data.
+  while (true) {
+    var gotElementEnd;
+    var offset;
+
+    try {
+      if (this.dataParts_.length === 0) {
+        // This is the beginning of an element.
+        if (data.length <= 0)
+          // Wait for more data.
+          return;
+      }
+
+      // Scan the input to check if a whole TLV element has been read.
+      this.tlvStructureDecoder_.seek(0);
+      gotElementEnd = this.tlvStructureDecoder_.findElementEnd(data);
+      offset = this.tlvStructureDecoder_.getOffset();
     } catch (ex) {
-        console.log("NDN not available: Uint8Array not supported. " + ex);
+      // Reset to read a new element on the next call.
+      this.dataParts_ = [];
+      this.tlvStructureDecoder_ = new TlvStructureDecoder();
+
+      throw ex;
+    }
+
+    if (gotElementEnd) {
+      // Got the remainder of an element.  Report to the caller.
+      var element;
+      if (this.dataParts_.length === 0)
+        element = data.slice(0, offset);
+      else {
+        this.dataParts_.push(data.slice(0, offset));
+        element = DataUtils.concatArrays(this.dataParts_);
+        this.dataParts_ = [];
+      }
+
+      // Reset to read a new element. Do this before calling onReceivedElement
+      // in case it throws an exception.
+      data = data.slice(offset, data.length);
+      this.tlvStructureDecoder_ = new TlvStructureDecoder();
+
+      this.elementListener_.onReceivedElement(element);
+      if (data.length == 0)
+        // No more data in the packet.
+        return;
+
+      // else loop back to decode.
+    }
+    else {
+      // Save a copy. We will call concatArrays later.
+      var totalLength = data.length;
+      for (var i = 0; i < this.dataParts_.length; ++i)
+        totalLength += this.dataParts_[i].length;
+      if (totalLength > NdnCommon.MAX_NDN_PACKET_SIZE) {
+        // Reset to read a new element on the next call.
+        this.dataParts_ = [];
+        this.tlvStructureDecoder_ = new TlvStructureDecoder();
+
+        throw new DecodingException(new Error
+          ("The incoming packet exceeds the maximum limit Face.getMaxNdnPacketSize()"));
+      }
+
+      this.dataParts_.push(new Buffer(data));
+      if (LOG > 3) console.log('Incomplete packet received. Length ' + data.length + '. Wait for more input.');
+      return;
+    }
+  }
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a new DerDecodingException wrapping the given error object.
+ * Call with: throw new DerDecodingException(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+function DerDecodingException(error)
+{
+  if (error) {
+    error.__proto__ = DerDecodingException.prototype;
+    return error;
+  }
+}
+DerDecodingException.prototype = new Error();
+DerDecodingException.prototype.name = "DerDecodingException";
+
+exports.DerDecodingException = DerDecodingException;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a new DerEncodingException wrapping the given error object.
+ * Call with: throw new DerEncodingException(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+function DerEncodingException(error)
+{
+  if (error) {
+    error.__proto__ = DerEncodingException.prototype;
+    return error;
+  }
+}
+DerEncodingException.prototype = new Error();
+DerEncodingException.prototype.name = "DerEncodingException";
+
+exports.DerEncodingException = DerEncodingException;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From PyNDN der.py by Adeola Bannis <thecodemaiden@gmail.com>.
+ * @author: Originally from code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * The DerNodeType enum defines the known DER node types.
+ */
+var DerNodeType = function DerNodeType()
+{
+}
+
+exports.DerNodeType = DerNodeType;
+
+DerNodeType.Eoc = 0;
+DerNodeType.Boolean = 1;
+DerNodeType.Integer = 2;
+DerNodeType.BitString = 3;
+DerNodeType.OctetString = 4;
+DerNodeType.Null = 5;
+DerNodeType.ObjectIdentifier = 6;
+DerNodeType.ObjectDescriptor = 7;
+DerNodeType.External = 40;
+DerNodeType.Real = 9;
+DerNodeType.Enumerated = 10;
+DerNodeType.EmbeddedPdv = 43;
+DerNodeType.Utf8String = 12;
+DerNodeType.RelativeOid = 13;
+DerNodeType.Sequence = 48;
+DerNodeType.Set = 49;
+DerNodeType.NumericString = 18;
+DerNodeType.PrintableString = 19;
+DerNodeType.T61String = 20;
+DerNodeType.VideoTexString = 21;
+DerNodeType.Ia5String = 22;
+DerNodeType.UtcTime = 23;
+DerNodeType.GeneralizedTime = 24;
+DerNodeType.GraphicString = 25;
+DerNodeType.VisibleString = 26;
+DerNodeType.GeneralString = 27;
+DerNodeType.UniversalString = 28;
+DerNodeType.CharacterString = 29;
+DerNodeType.BmpString = 30;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From PyNDN der_node.py by Adeola Bannis <thecodemaiden@gmail.com>.
+ * @author: Originally from code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DynamicBuffer = require('../../util/dynamic-buffer.js').DynamicBuffer; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DerDecodingException = require('./der-decoding-exception.js').DerDecodingException; /** @ignore */
+var DerEncodingException = require('./der-encoding-exception.js').DerEncodingException; /** @ignore */
+var DerNodeType = require('./der-node-type.js').DerNodeType;
+
+/**
+ * DerNode implements the DER node types used in encoding/decoding DER-formatted
+ * data.
+ *
+ * Create a generic DER node with the given nodeType. This is a private
+ * constructor used by one of the public DerNode subclasses defined below.
+ * @param {number} nodeType One of the defined DER DerNodeType constants.
+ * @constructor
+ */
+var DerNode = function DerNode(nodeType)
+{
+  this.nodeType_ = nodeType;
+  this.parent_ = null;
+  this.header_ = new Buffer(0);
+  this.payload_ = new DynamicBuffer(0);
+  this.payloadPosition_ = 0;
+};
+
+exports.DerNode = DerNode;
+
+/**
+ * Return the number of bytes in DER
+ * @return {number}
+ */
+DerNode.prototype.getSize = function()
+{
+  return this.header_.length + this.payloadPosition_;
+};
+
+/**
+ * Encode the given size and update the header.
+ * @param {number} size
+ */
+DerNode.prototype.encodeHeader = function(size)
+{
+  var buffer = new DynamicBuffer(10);
+  var bufferPosition = 0;
+  buffer.array[bufferPosition++] = this.nodeType_;
+  if (size < 0)
+    // We don't expect this to happen since this is an internal method and
+    // always called with the non-negative size() of some buffer.
+    throw new Error("encodeHeader: DER object has negative length");
+  else if (size <= 127)
+    buffer.array[bufferPosition++] = size & 0xff;
+  else {
+    var tempBuf = new DynamicBuffer(10);
+    // We encode backwards from the back.
+
+    var val = size;
+    var n = 0;
+    while (val != 0) {
+      ++n;
+      tempBuf.ensureLengthFromBack(n);
+      tempBuf.array[tempBuf.array.length - n] = val & 0xff;
+      val >>= 8;
+    }
+    var nTempBufBytes = n + 1;
+    tempBuf.ensureLengthFromBack(nTempBufBytes);
+    tempBuf.array[tempBuf.array.length - nTempBufBytes] = ((1<<7) | n) & 0xff;
+
+    buffer.copy(tempBuf.slice(tempBuf.array.length - nTempBufBytes), bufferPosition);
+    bufferPosition += nTempBufBytes;
+  }
+
+  this.header_ = buffer.slice(0, bufferPosition);
+};
+
+/**
+ * Extract the header from an input buffer and return the size.
+ * @param {Buffer} inputBuf The input buffer to read from.
+ * @param {number} startIdx The offset into the buffer.
+ * @return {number} The parsed size in the header.
+ */
+DerNode.prototype.decodeHeader = function(inputBuf, startIdx)
+{
+  var idx = startIdx;
+
+  var nodeType = inputBuf[idx] & 0xff;
+  idx += 1;
+
+  this.nodeType_ = nodeType;
+
+  var sizeLen = inputBuf[idx] & 0xff;
+  idx += 1;
+
+  var header = new DynamicBuffer(10);
+  var headerPosition = 0;
+  header.array[headerPosition++] = nodeType;
+  header.array[headerPosition++] = sizeLen;
+
+  var size = sizeLen;
+  var isLongFormat = (sizeLen & (1 << 7)) != 0;
+  if (isLongFormat) {
+    var lenCount = sizeLen & ((1<<7) - 1);
+    size = 0;
+    while (lenCount > 0) {
+      var b = inputBuf[idx];
+      idx += 1;
+      header.ensureLength(headerPosition + 1);
+      header.array[headerPosition++] = b;
+      size = 256 * size + (b & 0xff);
+      lenCount -= 1;
+    }
+  }
+
+  this.header_ = header.slice(0, headerPosition);
+  return size;
+};
+
+/**
+ * Get the raw data encoding for this node.
+ * @return {Blob} The raw data encoding.
+ */
+DerNode.prototype.encode = function()
+{
+  var buffer = new Buffer(this.getSize());
+
+  this.header_.copy(buffer);
+  this.payload_.slice(0, this.payloadPosition_).copy(buffer, this.header_.length);
+
+  return new Blob(buffer, false);
+};
+
+/**
+ * Decode and store the data from an input buffer.
+ * @param {Buffer} inputBuf The input buffer to read from. This reads from
+ * startIdx (regardless of the buffer's position) and does not change the
+ * position.
+ * @param {number} startIdx The offset into the buffer.
+ */
+DerNode.prototype.decode = function(inputBuf, startIdx)
+{
+  var idx = startIdx;
+  var payloadSize = this.decodeHeader(inputBuf, idx);
+  var skipBytes = this.header_.length;
+  if (payloadSize > 0) {
+    idx += skipBytes;
+    this.payloadAppend(inputBuf.slice(idx, idx + payloadSize));
+  }
+};
+
+/**
+ * Copy buffer to this.payload_ at this.payloadPosition_ and update
+ * this.payloadPosition_.
+ * @param {Buffer} buffer The buffer to copy.
+ */
+DerNode.prototype.payloadAppend = function(buffer)
+{
+  this.payloadPosition_ = this.payload_.copy(buffer, this.payloadPosition_);
+}
+
+/**
+ * Parse the data from the input buffer recursively and return the root as an
+ * object of a subclass of DerNode.
+ * @param {Buffer} inputBuf The input buffer to read from.
+ * @param {number} startIdx (optional) The offset into the buffer. If omitted,
+ * use 0.
+ * @return {DerNode} An object of a subclass of DerNode.
+ */
+DerNode.parse = function(inputBuf, startIdx)
+{
+  if (startIdx == undefined)
+    startIdx = 0;
+
+  var nodeType = inputBuf[startIdx] & 0xff;
+  // Don't increment idx. We're just peeking.
+
+  var newNode;
+  if (nodeType === DerNodeType.Boolean)
+    newNode = new DerNode.DerBoolean();
+  else if (nodeType === DerNodeType.Integer)
+    newNode = new DerNode.DerInteger();
+  else if (nodeType === DerNodeType.BitString)
+    newNode = new DerNode.DerBitString();
+  else if (nodeType === DerNodeType.OctetString)
+    newNode = new DerNode.DerOctetString();
+  else if (nodeType === DerNodeType.Null)
+    newNode = new DerNode.DerNull();
+  else if (nodeType === DerNodeType.ObjectIdentifier)
+    newNode = new DerNode.DerOid();
+  else if (nodeType === DerNodeType.Sequence)
+    newNode = new DerNode.DerSequence();
+  else if (nodeType === DerNodeType.PrintableString)
+    newNode = new DerNode.DerPrintableString();
+  else if (nodeType === DerNodeType.GeneralizedTime)
+    newNode = new DerNode.DerGeneralizedTime();
+  else
+    throw new DerDecodingException(new Error("Unimplemented DER type " + nodeType));
+
+  newNode.decode(inputBuf, startIdx);
+  return newNode;
+};
+
+/**
+ * Convert the encoded data to a standard representation. Overridden by some
+ * subclasses (e.g. DerBoolean).
+ * @return {Blob} The encoded data as a Blob.
+ */
+DerNode.prototype.toVal = function()
+{
+  return this.encode();
+};
+
+/**
+ * Get a copy of the payload bytes.
+ * @return {Blob} A copy of the payload.
+ */
+DerNode.prototype.getPayload = function()
+{
+  return new Blob(this.payload_.slice(0, this.payloadPosition_), true);
+};
+
+/**
+ * If this object is a DerNode.DerSequence, get the children of this node.
+ * Otherwise, throw an exception. (DerSequence overrides to implement this
+ * method.)
+ * @return {Array<DerNode>} The children as an array of DerNode.
+ * @throws DerDecodingException if this object is not a DerSequence.
+ */
+DerNode.prototype.getChildren = function()
+{
+  throw new DerDecodingException(new Error
+    ("getChildren: This DerNode is not DerSequence"));
+};
+
+/**
+ * Check that index is in bounds for the children list, return children[index].
+ * @param {Array<DerNode>} children The list of DerNode, usually returned by
+ * another call to getChildren.
+ * @param {number} index The index of the children.
+ * @return {DerNode.DerSequence} children[index].
+ * @throws DerDecodingException if index is out of bounds or if children[index]
+ * is not a DerSequence.
+ */
+DerNode.getSequence = function(children, index)
+{
+  if (index < 0 || index >= children.length)
+    throw new DerDecodingException(new Error
+      ("getSequence: Child index is out of bounds"));
+
+  if (!(children[index] instanceof DerNode.DerSequence))
+    throw new DerDecodingException(new Error
+      ("getSequence: Child DerNode is not a DerSequence"));
+
+  return children[index];
+};
+
+/**
+ * A DerStructure extends DerNode to hold other DerNodes.
+ * Create a DerStructure with the given nodeType. This is a private
+ * constructor. To create an object, use DerSequence.
+ * @param {number} nodeType One of the defined DER DerNodeType constants.
+ */
+DerNode.DerStructure = function DerStructure(nodeType)
+{
+  // Call the base constructor.
+  DerNode.call(this, nodeType);
+
+  this.childChanged_ = false;
+  this.nodeList_ = []; // Of DerNode.
+  this.size_ = 0;
+};
+DerNode.DerStructure.prototype = new DerNode();
+DerNode.DerStructure.prototype.name = "DerStructure";
+
+/**
+ * Get the total length of the encoding, including children.
+ * @return {number} The total (header + payload) length.
+ */
+DerNode.DerStructure.prototype.getSize = function()
+{
+  if (this.childChanged_) {
+    this.updateSize();
+    this.childChanged_ = false;
+  }
+
+  this.encodeHeader(this.size_);
+  return this.size_ + this.header_.length;
+};
+
+/**
+ * Get the children of this node.
+ * @return {Array<DerNode>} The children as an array of DerNode.
+ */
+DerNode.DerStructure.prototype.getChildren = function()
+{
+  return this.nodeList_;
+};
+
+DerNode.DerStructure.prototype.updateSize = function()
+{
+  var newSize = 0;
+
+  for (var i = 0; i < this.nodeList_.length; ++i) {
+    var n = this.nodeList_[i];
+    newSize += n.getSize();
+  }
+
+  this.size_ = newSize;
+  this.childChanged_ = false;
+};
+
+/**
+ * Add a child to this node.
+ * @param {DerNode} node The child node to add.
+ * @param {boolean} (optional) notifyParent Set to true to cause any containing
+ * nodes to update their size.  If omitted, use false.
+ */
+DerNode.DerStructure.prototype.addChild = function(node, notifyParent)
+{
+  node.parent_ = this;
+  this.nodeList_.push(node);
+
+  if (notifyParent) {
+    if (this.parent_ != null)
+      this.parent_.setChildChanged();
+  }
+
+  this.childChanged_ = true;
+};
+
+/**
+ * Mark the child list as dirty, so that we update size when necessary.
+ */
+DerNode.DerStructure.prototype.setChildChanged = function()
+{
+  if (this.parent_ != null)
+    this.parent_.setChildChanged();
+  this.childChanged_ = true;
+};
+
+/**
+ * Override the base encode to return raw data encoding for this node and its
+ * children.
+ * @return {Blob} The raw data encoding.
+ */
+DerNode.DerStructure.prototype.encode = function()
+{
+  var buffer = new DynamicBuffer(10);
+  var bufferPosition = 0;
+  this.updateSize();
+  this.encodeHeader(this.size_);
+  bufferPosition = buffer.copy(this.header_, bufferPosition);
+
+  for (var i = 0; i < this.nodeList_.length; ++i) {
+    var n = this.nodeList_[i];
+    var encodedChild = n.encode();
+    bufferPosition = buffer.copy(encodedChild.buf(), bufferPosition);
+  }
+
+  return new Blob(buffer.slice(0, bufferPosition), false);
+};
+
+/**
+ * Override the base decode to decode and store the data from an input
+ * buffer. Recursively populates child nodes.
+ * @param {Buffer} inputBuf The input buffer to read from.
+ * @param {number} startIdx The offset into the buffer.
+ */
+DerNode.DerStructure.prototype.decode = function(inputBuf, startIdx)
+{
+  var idx = startIdx;
+  this.size_ = this.decodeHeader(inputBuf, idx);
+  idx += this.header_.length;
+
+  var accSize = 0;
+  while (accSize < this.size_) {
+    var node = DerNode.parse(inputBuf, idx);
+    var size = node.getSize();
+    idx += size;
+    accSize += size;
+    this.addChild(node, false);
+  }
+};
+
+////////
+// Now for all the node types...
+////////
+
+/**
+ * A DerByteString extends DerNode to handle byte strings.
+ * Create a DerByteString with the given inputData and nodeType. This is a
+ * private constructor used by one of the public subclasses such as
+ * DerOctetString or DerPrintableString.
+ * @param {Buffer} inputData An input buffer containing the string to encode.
+ * @param {number} nodeType One of the defined DER DerNodeType constants.
+ */
+DerNode.DerByteString = function DerByteString(inputData, nodeType)
+{
+  // Call the base constructor.
+  DerNode.call(this, nodeType);
+
+  if (inputData != null) {
+    this.payloadAppend(inputData);
+    this.encodeHeader(inputData.length);
+  }
+};
+DerNode.DerByteString.prototype = new DerNode();
+DerNode.DerByteString.prototype.name = "DerByteString";
+
+/**
+ * Override to return just the byte string.
+ * @return {Blob} The byte string as a copy of the payload buffer.
+ */
+DerNode.DerByteString.prototype.toVal = function()
+{
+  return this.getPayload();
+};
+
+/**
+ * DerBoolean extends DerNode to encode a boolean value.
+ * Create a new DerBoolean for the value.
+ * @param {boolean} value The value to encode.
+ */
+DerNode.DerBoolean = function DerBoolean(value)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.Boolean);
+
+  if (value != undefined) {
+    var val = value ? 0xff : 0x00;
+    this.payload_.ensureLength(this.payloadPosition_ + 1);
+    this.payload_.array[this.payloadPosition_++] = val;
+    this.encodeHeader(1);
+  }
+};
+DerNode.DerBoolean.prototype = new DerNode();
+DerNode.DerBoolean.prototype.name = "DerBoolean";
+
+DerNode.DerBoolean.prototype.toVal = function()
+{
+  var val = this.payload_.array[0];
+  return val != 0x00;
+};
+
+/**
+ * DerInteger extends DerNode to encode an integer value.
+ * Create a new DerInteger for the value.
+ * @param {number|Buffer} integer The value to encode. If integer is a Buffer
+ * byte array of a positive integer, you must ensure that the first byte is less
+ * than 0x80.
+ */
+DerNode.DerInteger = function DerInteger(integer)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.Integer);
+
+  if (integer != undefined) {
+    if (Buffer.isBuffer(integer)) {
+      if (integer.length > 0 && integer[0] >= 0x80)
+        throw new DerEncodingException(new Error
+          ("DerInteger: Negative integers are not currently supported"));
+
+      if (integer.length == 0)
+        this.payloadAppend(new Buffer([0]));
+      else
+        this.payloadAppend(integer);
+    }
+    else {
+      // JavaScript doesn't distinguish int from float, so round.
+      integer = Math.round(integer);
+
+      if (integer < 0)
+        throw new DerEncodingException(new Error
+          ("DerInteger: Negative integers are not currently supported"));
+
+      // Convert the integer to bytes the easy/slow way.
+      var temp = new DynamicBuffer(10);
+      // We encode backwards from the back.
+      var length = 0;
+      while (true) {
+        ++length;
+        temp.ensureLengthFromBack(length);
+        temp.array[temp.array.length - length] = integer & 0xff;
+        integer >>= 8;
+
+        if (integer <= 0)
+          // We check for 0 at the end so we encode one byte if it is 0.
+          break;
+      }
+
+      if (temp.array[temp.array.length - length] >= 0x80) {
+        // Make it a non-negative integer.
+        ++length;
+        temp.ensureLengthFromBack(length);
+        temp.array[temp.array.length - length] = 0;
+      }
+
+      this.payloadAppend(temp.slice(temp.array.length - length));
+    }
+
+    this.encodeHeader(this.payloadPosition_);
+  }
+};
+DerNode.DerInteger.prototype = new DerNode();
+DerNode.DerInteger.prototype.name = "DerInteger";
+
+DerNode.DerInteger.prototype.toVal = function()
+{
+  if (this.payloadPosition_ > 0 && this.payload_.array[0] >= 0x80)
+    throw new DerDecodingException(new Error
+      ("DerInteger: Negative integers are not currently supported"));
+
+  var result = 0;
+  for (var i = 0; i < this.payloadPosition_; ++i) {
+    result <<= 8;
+    result += this.payload_.array[i];
+  }
+
+  return result;
+};
+
+/**
+ * A DerBitString extends DerNode to handle a bit string.
+ * Create a DerBitString with the given padding and inputBuf.
+ * @param {Buffer} inputBuf An input buffer containing the bit octets to encode.
+ * @param {number} paddingLen The number of bits of padding at the end of the bit
+ * string.  Should be less than 8.
+ */
+DerNode.DerBitString = function DerBitString(inputBuf, paddingLen)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.BitString);
+
+  if (inputBuf != undefined) {
+    this.payload_.ensureLength(this.payloadPosition_ + 1);
+    this.payload_.array[this.payloadPosition_++] = paddingLen & 0xff;
+    this.payloadAppend(inputBuf);
+    this.encodeHeader(this.payloadPosition_);
+  }
+};
+DerNode.DerBitString.prototype = new DerNode();
+DerNode.DerBitString.prototype.name = "DerBitString";
+
+/**
+ * DerOctetString extends DerByteString to encode a string of bytes.
+ * Create a new DerOctetString for the inputData.
+ * @param {Buffer} inputData An input buffer containing the string to encode.
+ */
+DerNode.DerOctetString = function DerOctetString(inputData)
+{
+  // Call the base constructor.
+  DerNode.DerByteString.call(this, inputData, DerNodeType.OctetString);
+};
+DerNode.DerOctetString.prototype = new DerNode.DerByteString();
+DerNode.DerOctetString.prototype.name = "DerOctetString";
+
+/**
+ * A DerNull extends DerNode to encode a null value.
+ * Create a DerNull.
+ */
+DerNode.DerNull = function DerNull()
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.Null);
+  this.encodeHeader(0);
+};
+DerNode.DerNull.prototype = new DerNode();
+DerNode.DerNull.prototype.name = "DerNull";
+
+/**
+ * A DerOid extends DerNode to represent an object identifier.
+ * Create a DerOid with the given object identifier. The object identifier
+ * string must begin with 0,1, or 2 and must contain at least 2 digits.
+ * @param {string|OID} oid The OID string or OID object to encode.
+ */
+DerNode.DerOid = function DerOid(oid)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.ObjectIdentifier);
+
+  if (oid != undefined) {
+    if (typeof oid === 'string') {
+      var splitString = oid.split(".");
+      var parts = [];
+      for (var i = 0; i < splitString.length; ++i)
+        parts.push(parseInt(splitString[i]));
+
+      this.prepareEncoding(parts);
+    }
+    else
+      // Assume oid is of type OID.
+      this.prepareEncoding(oid.getIntegerList());
+  }
+};
+DerNode.DerOid.prototype = new DerNode();
+DerNode.DerOid.prototype.name = "DerOid";
+
+/**
+ * Encode a sequence of integers into an OID object and set the payload.
+ * @param {Array<number>} value The array of integers.
+ */
+DerNode.DerOid.prototype.prepareEncoding = function(value)
+{
+  var firstNumber;
+  if (value.length == 0)
+    throw new DerEncodingException(new Error("No integer in OID"));
+  else {
+    if (value[0] >= 0 && value[0] <= 2)
+      firstNumber = value[0] * 40;
+    else
+      throw new DerEncodingException(new Error("First integer in OID is out of range"));
+  }
+
+  if (value.length >= 2) {
+    if (value[1] >= 0 && value[1] <= 39)
+      firstNumber += value[1];
+    else
+      throw new DerEncodingException(new Error("Second integer in OID is out of range"));
+  }
+
+  var encodedBuffer = new DynamicBuffer(10);
+  var encodedBufferPosition = 0;
+  encodedBufferPosition = encodedBuffer.copy
+    (DerNode.DerOid.encode128(firstNumber), encodedBufferPosition);
+
+  if (value.length > 2) {
+    for (var i = 2; i < value.length; ++i)
+      encodedBufferPosition = encodedBuffer.copy
+        (DerNode.DerOid.encode128(value[i]), encodedBufferPosition);
+  }
+
+  this.encodeHeader(encodedBufferPosition);
+  this.payloadAppend(encodedBuffer.slice(0, encodedBufferPosition));
+};
+
+/**
+ * Compute the encoding for one part of an OID, where values greater than 128
+ * must be encoded as multiple bytes.
+ * @param {number} value A component of an OID.
+ * @return {Buffer} The encoded buffer.
+ */
+DerNode.DerOid.encode128 = function(value)
+{
+  var mask = (1 << 7) - 1;
+  var outBytes = new DynamicBuffer(10);
+  var outBytesLength = 0;
+  // We encode backwards from the back.
+
+  if (value < 128) {
+    ++outBytesLength;
+    outBytes.array[outBytes.array.length - outBytesLength] = value & mask;
+  }
+  else {
+    ++outBytesLength;
+    outBytes.array[outBytes.array.length - outBytesLength] = value & mask;
+    value >>= 7;
+
+    while (value != 0) {
+      ++outBytesLength;
+      outBytes.ensureLengthFromBack(outBytesLength);
+      outBytes.array[outBytes.array.length - outBytesLength] =
+        (value & mask) | (1 << 7);
+      value >>= 7;
+    }
+  }
+
+  return outBytes.slice(outBytes.array.length - outBytesLength);
+};
+
+/**
+ * Convert an encoded component of the encoded OID to the original integer.
+ * @param {number} offset The offset into this node's payload.
+ * @param {Array<number>} skip Set skip[0] to the number of payload bytes to skip.
+ * @return {number} The original integer.
+ */
+DerNode.DerOid.prototype.decode128 = function(offset, skip)
+{
+  var flagMask = 0x80;
+  var result = 0;
+  var oldOffset = offset;
+
+  while ((this.payload_.array[offset] & flagMask) != 0) {
+    result = 128 * result + (this.payload_.array[offset] & 0xff) - 128;
+    offset += 1;
+  }
+
+  result = result * 128 + (this.payload_.array[offset] & 0xff);
+
+  skip[0] = offset - oldOffset + 1;
+  return result;
+};
+
+/**
+ * Override to return the string representation of the OID.
+ * @return {string} The string representation of the OID.
+ */
+DerNode.DerOid.prototype.toVal = function()
+{
+  var offset = 0;
+  var components = []; // of number.
+
+  while (offset < this.payloadPosition_) {
+    var skip = [0];
+    var nextVal = this.decode128(offset, skip);
+    offset += skip[0];
+    components.push(nextVal);
+  }
+
+  // For some odd reason, the first digits are represented in one byte.
+  var firstByte = components[0];
+  var firstDigit = Math.floor(firstByte / 40);
+  var secondDigit = firstByte % 40;
+
+  var result = firstDigit + "." + secondDigit;
+  for (var i = 1; i < components.length; ++i)
+    result += "." + components[i];
+
+  return result;
+};
+
+/**
+ * A DerSequence extends DerStructure to contains an ordered sequence of other
+ * nodes.
+ * Create a DerSequence.
+ */
+DerNode.DerSequence = function DerSequence()
+{
+  // Call the base constructor.
+  DerNode.DerStructure.call(this, DerNodeType.Sequence);
+};
+DerNode.DerSequence.prototype = new DerNode.DerStructure();
+DerNode.DerSequence.prototype.name = "DerSequence";
+
+/**
+ * A DerPrintableString extends DerByteString to handle a a printable string. No
+ * escaping or other modification is done to the string.
+ * Create a DerPrintableString with the given inputData.
+ * @param {Buffer} inputData An input buffer containing the string to encode.
+ */
+DerNode.DerPrintableString = function DerPrintableString(inputData)
+{
+  // Call the base constructor.
+  DerNode.DerByteString.call(this, inputData, DerNodeType.PrintableString);
+};
+DerNode.DerPrintableString.prototype = new DerNode.DerByteString();
+DerNode.DerPrintableString.prototype.name = "DerPrintableString";
+
+/**
+ * A DerGeneralizedTime extends DerNode to represent a date and time, with
+ * millisecond accuracy.
+ * Create a DerGeneralizedTime with the given milliseconds since 1970.
+ * @param {number} msSince1970 The timestamp as milliseconds since Jan 1, 1970.
+ */
+DerNode.DerGeneralizedTime = function DerGeneralizedTime(msSince1970)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.GeneralizedTime);
+
+  if (msSince1970 != undefined) {
+    var derTime = DerNode.DerGeneralizedTime.toDerTimeString(msSince1970);
+    // Use Blob to convert to a Buffer.
+    this.payloadAppend(new Blob(derTime).buf());
+    this.encodeHeader(this.payloadPosition_);
+  }
+};
+DerNode.DerGeneralizedTime.prototype = new DerNode();
+DerNode.DerGeneralizedTime.prototype.name = "DerGeneralizedTime";
+
+/**
+ * Convert a UNIX timestamp to the internal string representation.
+ * @param {type} msSince1970 Timestamp as milliseconds since Jan 1, 1970.
+ * @return {string} The string representation.
+ */
+DerNode.DerGeneralizedTime.toDerTimeString = function(msSince1970)
+{
+  var utcTime = new Date(Math.round(msSince1970));
+  return utcTime.getUTCFullYear() +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCMonth() + 1) +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCDate()) +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCHours()) +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCMinutes()) +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCSeconds()) +
+         "Z";
+};
+
+/**
+ * A private method to zero pad an integer to 2 digits.
+ * @param {number} x The number to pad.  Assume it is a non-negative integer.
+ * @return {string} The padded string.
+ */
+DerNode.DerGeneralizedTime.to2DigitString = function(x)
+{
+  var result = x.toString();
+  return result.length === 1 ? "0" + result : result;
+};
+
+/**
+ * Override to return the milliseconds since 1970.
+ * @return {number} The timestamp value as milliseconds since 1970.
+ */
+DerNode.DerGeneralizedTime.prototype.toVal = function()
+{
+  var timeStr = this.payload_.slice(0, this.payloadPosition_).toString();
+  return Date.UTC
+    (parseInt(timeStr.substr(0, 4)),
+     parseInt(timeStr.substr(4, 2) - 1),
+     parseInt(timeStr.substr(6, 2)),
+     parseInt(timeStr.substr(8, 2)),
+     parseInt(timeStr.substr(10, 2)),
+     parseInt(timeStr.substr(12, 2)));
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From PyNDN boost_info_parser by Adeola Bannis.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var fs = require('fs');
+
+/**
+ * BoostInfoTree is provided for compatibility with the Boost INFO property list
+ * format used in ndn-cxx.
+ *
+ * Each node in the tree may have a name and a value as well as associated
+ * sub-trees. The sub-tree names are not unique, and so sub-trees are stored as
+ * dictionaries where the key is a sub-tree name and the values are the
+ * sub-trees sharing the same name.
+ *
+ * Nodes can be accessed with a path syntax, as long as nodes in the path do not
+ * contain the path separator '/' in their names.
+ * @constructor
+ */
+var BoostInfoTree = function BoostInfoTree(value, parent)
+{
+  // subtrees is an array of {key: treeName, value: subtreeList} where
+  // treeName is a string and subtreeList is an array of BoostInfoTree.
+  // We can't use a dictionary because we want the keys to be in order.
+  this.subtrees = [];
+  this.value = value;
+  this.parent = parent;
+
+  this.lastChild = null;
+};
+
+/**
+ * Insert a BoostInfoTree as a sub-tree with the given name.
+ * @param {string} treeName The name of the new sub-tree.
+ * @param {BoostInfoTree} newTree The sub-tree to add.
+ */
+BoostInfoTree.prototype.addSubtree = function(treeName, newTree)
+{
+  var subtreeList = this.find(treeName);
+  if (subtreeList !== null)
+    subtreeList.push(newTree);
+  else
+    this.subtrees.push({key: treeName, value: [newTree]});
+
+  newTree.parent = this;
+  this.lastChild = newTree;
+};
+
+/**
+ * Create a new BoostInfo and insert it as a sub-tree with the given name.
+ * @param {string} treeName The name of the new sub-tree.
+ * @param {string} value The value associated with the new sub-tree.
+ * @return {BoostInfoTree} The created sub-tree.
+ */
+BoostInfoTree.prototype.createSubtree = function(treeName, value)
+{
+  var newTree = new BoostInfoTree(value, this);
+  this.addSubtree(treeName, newTree);
+  return newTree;
+};
+
+/**
+ * Look up using the key and return a list of the subtrees.
+ * @param {string} key The key which may be a path separated with '/'.
+ * @return {Array<BoostInfoTree>} A new array with pointers to the subtrees.
+ */
+BoostInfoTree.prototype.get = function(key)
+{
+  // Strip beginning '/'.
+  key = key.replace(/^\/+/, "");
+  if (key.length === 0)
+    return [this];
+  var path = key.split('/');
+
+  var subtrees = this.find(path[0]);
+  if (subtrees === null)
+    return [];
+  if (path.length == 1)
+    return subtrees.slice(0);
+
+  var newPath = path.slice(1).join('/');
+  var foundVals = [];
+  for (var i = 0; i < subtrees.length; ++i) {
+    var t = subtrees[i];
+    var partial = t.get(newPath);
+    foundVals = foundVals.concat(partial);
+  }
+  return foundVals;
+};
+
+/**
+ * Look up using the key and return string value of the first subtree.
+ * @param {string} key The key which may be a path separated with '/'.
+ * @return {string} The string value or null if not found.
+ */
+BoostInfoTree.prototype.getFirstValue = function(key)
+{
+  var list = this.get(key);
+  if (list.length >= 1)
+    return list[0].value;
+  else
+    return null;
+};
+
+BoostInfoTree.prototype.getValue = function() { return this.value; };
+
+BoostInfoTree.prototype.getParent = function() { return this.parent; };
+
+BoostInfoTree.prototype.getLastChild = function() { return this.lastChild; };
+
+BoostInfoTree.prototype.prettyPrint = function(indentLevel)
+{
+  indentLevel = indentLevel || 1;
+
+  var prefix = Array(indentLevel + 1).join(' ');
+  var s = "";
+
+  if (this.parent != null) {
+    if (this.value && this.value.length > 0)
+      s += "\"" + this.value + "\"";
+    s += "\n";
+  }
+
+  if (this.subtrees.length > 0) {
+    if (this.parent)
+      s += prefix + "{\n";
+    var nextLevel = Array(indentLevel + 2 + 1).join(' ');
+    for (var i = 0; i < this.subtrees.length; ++i) {
+      for (var iSubTree = 0; iSubTree < this.subtrees[i].value.length; ++iSubTree)
+        s += nextLevel + this.subtrees[i].key + " " +
+             this.subtrees[i].value[iSubTree].prettyPrint(indentLevel + 2);
+    }
+
+    if (this.parent)
+      s +=  prefix + "}\n";
+  }
+
+  return s;
+};
+
+BoostInfoTree.prototype.toString = function()
+{
+  return this.prettyPrint();
+};
+
+/**
+ * Use treeName to find the array of BoostInfoTree in this.subtrees.
+ * @param {string} treeName The key in this.subtrees to search for. This does a
+ * flat search in subtrees_.  It does not split by '/' into a path.
+ * @return {Array<BoostInfoTree>} A array of BoostInfoTree, or null if not found.
+ */
+BoostInfoTree.prototype.find = function(treeName)
+{
+  for (var i = 0; i < this.subtrees.length; ++i) {
+    if (this.subtrees[i].key == treeName)
+      return this.subtrees[i].value;
+  }
+
+  return null;
+};
+
+/**
+ * A BoostInfoParser reads files in Boost's INFO format and constructs a
+ * BoostInfoTree.
+ * @constructor
+ */
+var BoostInfoParser = function BoostInfoParser()
+{
+  this.root = new BoostInfoTree();
+};
+
+exports.BoostInfoParser = BoostInfoParser;
+exports.BoostInfoTree = BoostInfoTree; // debug
+
+/**
+ * Add the contents of the file or input string to the root BoostInfoTree. There
+ * are two forms:
+ * read(fileName) reads fileName from the file system.
+ * read(input, inputName) reads from the input, in which case inputName is used
+ * only for log messages, etc.
+ * @param {string} fileName The path to the INFO file.
+ * @param {string} input The contents of the INFO file, with lines separated by
+ * "\n" or "\r\n".
+ * @param {string} inputName Use with input for log messages, etc.
+ */
+BoostInfoParser.prototype.read = function(fileNameOrInput, inputName)
+{
+  var input;
+  if (typeof inputName == 'string')
+    input = fileNameOrInput;
+  else {
+    // No inputName, so assume the first arg is the file name.
+    var fileName = fileNameOrInput;
+    inputName = fileName;
+    input = fs.readFileSync(fileName).toString();
+  }
+
+  var ctx = this.root;
+  var thisParser = this;
+  input.split(/\r?\n/).forEach(function(line) {
+    ctx = thisParser.parseLine(line.trim(), ctx);
+  });
+};
+
+/**
+ * Write the root tree of this BoostInfoParser as file in Boost's INFO format.
+ * @param {string} fileName The output path.
+ */
+BoostInfoParser.prototype.write = function(fileName)
+{
+  fs.writeFileSync(fileName, "" + this.root);
+};
+
+/**
+ * Get the root tree of this parser.
+ * @return {BoostInfoTree} The root BoostInfoTree.
+ */
+BoostInfoParser.prototype.getRoot = function() { return this.root; };
+
+/**
+ * Similar to Python's shlex.split, split s into an array of strings which are
+ * separated by whitespace, treating a string within quotes as a single entity
+ * regardless of whitespace between the quotes. Also allow a backslash to escape
+ * the next character.
+ * @param {string} s The input string to split.
+ * @return {Array<string>} An array of strings.
+ */
+BoostInfoParser.shlex_split = function(s)
+{
+  var result = [];
+  if (s == "")
+    return result;
+  var whiteSpace = " \t\n\r";
+  var iStart = 0;
+
+  while (true) {
+    // Move iStart past whitespace.
+    while (whiteSpace.indexOf(s[iStart]) >= 0) {
+      iStart += 1;
+      if (iStart >= s.length)
+        // Done.
+        return result;
+    }
+
+    // Move iEnd to the end of the token.
+    var iEnd = iStart;
+    var inQuotation = false;
+    var token = "";
+    while (true) {
+      if (s[iEnd] == '\\') {
+        // Append characters up to the backslash, skip the backslash and
+        //   move iEnd past the escaped character.
+        token += s.substring(iStart, iEnd);
+        iStart = iEnd + 1;
+        iEnd = iStart;
+        if (iEnd >= s.length)
+          // An unusual case: A backslash at the end of the string.
+          break;
+      }
+      else {
+        if (inQuotation) {
+          if (s[iEnd] == '\"') {
+            // Append characters up to the end quote and skip.
+            token += s.substring(iStart, iEnd);
+            iStart = iEnd + 1;
+            inQuotation = false;
+          }
+        }
+        else {
+          if (s[iEnd] == '\"') {
+            // Append characters up to the start quote and skip.
+            token += s.substring(iStart, iEnd);
+            iStart = iEnd + 1;
+            inQuotation = true;
+          }
+          else
+            if (whiteSpace.indexOf(s[iEnd]) >= 0)
+              break;
+        }
+      }
+
+      iEnd += 1;
+      if (iEnd >= s.length)
+        break;
+    }
+
+    token += s.substring(iStart, iEnd);
+    result.push(token);
+    if (iEnd >= s.length)
+      // Done.
+      return result;
+
+    iStart = iEnd;
+  }
+};
+
+BoostInfoParser.prototype.parseLine = function(line, context)
+{
+  // Skip blank lines and comments.
+  var commentStart = line.indexOf(';');
+  if (commentStart >= 0)
+    line = line.substring(0, commentStart).trim();
+  if (line.length == 0)
+    return context;
+
+  // Usually we are expecting key and optional value.
+  var strings = BoostInfoParser.shlex_split(line);
+  var isSectionStart = false;
+  var isSectionEnd = false;
+  for (var i = 0; i < strings.length; ++i) {
+    isSectionStart = (isSectionStart || strings[i] == "{");
+    isSectionEnd = (isSectionEnd || strings[i] == "}");
+  }
+
+  if (!isSectionStart && !isSectionEnd) {
+    var key = strings[0];
+    var val;
+    if (strings.length > 1)
+      val = strings[1];
+    context.createSubtree(key, val);
+
+    return context;
+  }
+
+  // OK, who is the joker who put a { on the same line as the key name?!
+  var sectionStart = line.indexOf('{');
+  if (sectionStart > 0) {
+    var firstPart = line.substring(0, sectionStart);
+    var secondPart = line.substring(sectionStart);
+
+    var ctx = this.parseLine(firstPart, context);
+    return this.parseLine(secondPart, ctx);
+  }
+
+  // If we encounter a {, we are beginning a new context.
+  // TODO: Error if there was already a subcontext here.
+  if (line[0] == '{') {
+    context = context.getLastChild();
+    return context;
+  }
+
+  // If we encounter a }, we are ending a list context.
+  if (line[0] == '}') {
+    context = context.getParent();
+    return context;
+  }
+
+  throw runtime_error("BoostInfoParser: input line is malformed");
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var InterestFilter = require('../interest-filter.js').InterestFilter; /** @ignore */
+var ForwardingFlags = require('../forwarding-flags.js').ForwardingFlags; /** @ignore */
+var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * A MemoryContentCache holds a set of Data packets and answers an Interest to
+ * return the correct Data packet. The cache is periodically cleaned up to
+ * remove each stale Data packet based on its FreshnessPeriod (if it has one).
+ * @note This class is an experimental feature.  See the API docs for more detail at
+ * http://named-data.net/doc/ndn-ccl-api/memory-content-cache.html .
+ *
+ * Create a new MemoryContentCache to use the given Face.
+ *
+ * @param {Face} face The Face to use to call registerPrefix and
+ * setInterestFilter, and which will call this object's OnInterest callback.
+ * @param {number} cleanupIntervalMilliseconds (optional) The interval
+ * in milliseconds between each check to clean up stale content in the cache. If
+ * omitted, use a default of 1000 milliseconds. If this is a large number, then
+ * effectively the stale content will not be removed from the cache.
+ * @constructor
+ */
+var MemoryContentCache = function MemoryContentCache
+  (face, cleanupIntervalMilliseconds)
+{
+  cleanupIntervalMilliseconds = (cleanupIntervalMilliseconds || 1000.0);
+
+  this.face = face;
+  this.cleanupIntervalMilliseconds = cleanupIntervalMilliseconds;
+  this.nextCleanupTime = new Date().getTime() + cleanupIntervalMilliseconds;
+
+  this.onDataNotFoundForPrefix = {}; /**< The map key is the prefix.toUri().
+                                          The value is an OnInterest function. */
+  this.interestFilterIdList = []; /**< elements are number */
+  this.registeredPrefixIdList = []; /**< elements are number */
+  this.noStaleTimeCache = []; /**< elements are MemoryContentCache.Content */
+  this.staleTimeCache = [];   /**< elements are MemoryContentCache.StaleTimeContent */
+  //StaleTimeContent::Compare contentCompare_;
+  this.emptyComponent = new Name.Component();
+  this.pendingInterestTable = [];
+
+  var thisMemoryContentCache = this;
+  this.storePendingInterestCallback = function
+    (localPrefix, localInterest, localFace, localInterestFilterId, localFilter) {
+       thisMemoryContentCache.storePendingInterest(localInterest, localFace);
+    };
+};
+
+exports.MemoryContentCache = MemoryContentCache;
+
+/**
+ * Call registerPrefix on the Face given to the constructor so that this
+ * MemoryContentCache will answer interests whose name has the prefix.
+ * Alternatively, if the Face's registerPrefix has already been called,
+ * then you can call this object's setInterestFilter.
+ * @param {Name} prefix The Name for the prefix to register. This copies the Name.
+ * @param {function} onRegisterFailed If this fails to register the prefix for
+ * any reason, this calls onRegisterFailed(prefix) where prefix is the prefix
+ * given to registerPrefix.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onRegisterSuccess (optional) When this receives a success
+ * message, this calls onRegisterSuccess[0](prefix, registeredPrefixId). If
+ * onRegisterSuccess is [null] or omitted, this does not use it. (As a special
+ * case, this optional parameter is supplied as an array of one function,
+ * instead of just a function, in order to detect when it is used instead of the
+ * following optional onDataNotFound function.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onDataNotFound (optional) If a data packet for an interest
+ * is not found in the cache, this forwards the interest by calling
+ * onDataNotFound(prefix, interest, face, interestFilterId, filter). Your
+ * callback can find the Data packet for the interest and call
+ * face.putData(data). If your callback cannot find the Data packet, it can
+ * optionally call storePendingInterest(interest, face) to store the pending
+ * interest in this object to be satisfied by a later call to add(data). If you
+ * want to automatically store all pending interests, you can simply use
+ * getStorePendingInterest() for onDataNotFound. If onDataNotFound is omitted or
+ * null, this does not use it.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {ForwardingFlags} flags (optional) See Face.registerPrefix.
+ * @param {WireFormat} wireFormat (optional) See Face.registerPrefix.
+ */
+MemoryContentCache.prototype.registerPrefix = function
+  (prefix, onRegisterFailed, onRegisterSuccess, onDataNotFound, flags, wireFormat)
+{
+  var arg3 = onRegisterSuccess;
+  var arg4 = onDataNotFound;
+  var arg5 = flags;
+  var arg6 = wireFormat;
+  // arg3,                arg4,            arg5,            arg6 may be:
+  // [OnRegisterSuccess], OnDataNotFound,  ForwardingFlags, WireFormat
+  // [OnRegisterSuccess], OnDataNotFound,  ForwardingFlags, null
+  // [OnRegisterSuccess], OnDataNotFound,  WireFormat,      null
+  // [OnRegisterSuccess], OnDataNotFound,  null,            null
+  // [OnRegisterSuccess], ForwardingFlags, WireFormat,      null
+  // [OnRegisterSuccess], ForwardingFlags, null,            null
+  // [OnRegisterSuccess], WireFormat,      null,            null
+  // [OnRegisterSuccess], null,            null,            null
+  // OnDataNotFound,      ForwardingFlags, WireFormat,      null
+  // OnDataNotFound,      ForwardingFlags, null,            null
+  // OnDataNotFound,      WireFormat,      null,            null
+  // OnDataNotFound,      null,            null,            null
+  // ForwardingFlags,     WireFormat,      null,            null
+  // ForwardingFlags,     null,            null,            null
+  // WireFormat,          null,            null,            null
+  // null,                null,            null,            null
+  if (typeof arg3 === "object" && arg3.length === 1 &&
+      typeof arg3[0] === "function")
+    onRegisterSuccess = arg3[0];
+  else
+    onRegisterSuccess = null;
+
+  if (typeof arg3 === "function")
+    onDataNotFound = arg3;
+  else if (typeof arg4 === "function")
+    onDataNotFound = arg4;
+  else
+    onDataNotFound = null;
+
+  if (arg3 instanceof ForwardingFlags)
+    flags = arg3;
+  else if (arg4 instanceof ForwardingFlags)
+    flags = arg4;
+  else if (arg5 instanceof ForwardingFlags)
+    flags = arg5;
+  else
+    flags = new ForwardingFlags();
+
+  if (arg3 instanceof WireFormat)
+    wireFormat = arg3;
+  else if (arg4 instanceof WireFormat)
+    wireFormat = arg4;
+  else if (arg5 instanceof WireFormat)
+    wireFormat = arg5;
+  else if (arg6 instanceof WireFormat)
+    wireFormat = arg6;
+  else
+    wireFormat = WireFormat.getDefaultWireFormat();
+
+  if (onDataNotFound)
+    this.onDataNotFoundForPrefix[prefix.toUri()] = onDataNotFound;
+  var registeredPrefixId = this.face.registerPrefix
+    (prefix, this.onInterest.bind(this), onRegisterFailed, onRegisterSuccess,
+     flags, wireFormat);
+  this.registeredPrefixIdList.push(registeredPrefixId);
+};
+
+/**
+ * Call setInterestFilter on the Face given to the constructor so that this
+ * MemoryContentCache will answer interests whose name matches the filter.
+ * There are two forms of setInterestFilter.
+ * The first form uses the exact given InterestFilter:
+ * setInterestFilter(filter, [onDataNotFound]).
+ * The second form creates an InterestFilter from the given prefix Name:
+ * setInterestFilter(prefix, [onDataNotFound]).
+ * @param {InterestFilter} filter The InterestFilter with a prefix and optional
+ * regex filter used to match the name of an incoming Interest. This makes a
+ * copy of filter.
+ * @param {Name} prefix The Name prefix used to match the name of an incoming
+ * Interest.
+ * @param {function} onDataNotFound (optional) If a data packet for an interest
+ * is not found in the cache, this forwards the interest by calling
+ * onDataNotFound(prefix, interest, face, interestFilterId, filter). Your
+ * callback can find the Data packet for the interest and call
+ * face.putData(data). If your callback cannot find the Data packet, it can
+ * optionally call storePendingInterest(interest, face) to store the pending
+ * interest in this object to be satisfied by a later call to add(data). If you
+ * want to automatically store all pending interests, you can simply use
+ * getStorePendingInterest() for onDataNotFound. If onDataNotFound is omitted or
+ * null, this does not use it.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+MemoryContentCache.prototype.setInterestFilter = function
+  (filterOrPrefix, onDataNotFound)
+{
+  if (onDataNotFound) {
+    var prefix;
+    if (typeof filterOrPrefix === 'object' && filterOrPrefix instanceof InterestFilter)
+      prefix = filterOrPrefix.getPrefix();
+    else
+      prefix = filterOrPrefix;
+    this.onDataNotFoundForPrefix[prefix.toUri()] = onDataNotFound;
+  }
+  var interestFilterId = this.face.setInterestFilter
+    (filterOrPrefix, this.onInterest.bind(this));
+  this.interestFilterIdList.push(interestFilterId);
+};
+
+/**
+ * Call Face.unsetInterestFilter and Face.removeRegisteredPrefix for all the
+ * prefixes given to the setInterestFilter and registerPrefix method on this
+ * MemoryContentCache object so that it will not receive interests any more. You
+ * can call this if you want to "shut down" this MemoryContentCache while your
+ * application is still running.
+ */
+MemoryContentCache.prototype.unregisterAll = function()
+{
+  for (var i = 0; i < this.interestFilterIdList.length; ++i)
+    this.face.unsetInterestFilter(this.interestFilterIdList[i]);
+  this.interestFilterIdList = [];
+
+  for (var i = 0; i < this.registeredPrefixIdList.length; ++i)
+    this.face.removeRegisteredPrefix(this.registeredPrefixIdList[i]);
+  this.registeredPrefixIdList = [];
+
+  // Also clear each onDataNotFoundForPrefix given to registerPrefix.
+  this.onDataNotFoundForPrefix = {};
+};
+
+/**
+ * Add the Data packet to the cache so that it is available to use to answer
+ * interests. If data.getMetaInfo().getFreshnessPeriod() is not null, set the
+ * staleness time to now plus data.getMetaInfo().getFreshnessPeriod(), which is
+ * checked during cleanup to remove stale content. This also checks if
+ * cleanupIntervalMilliseconds milliseconds have passed and removes stale
+ * content from the cache. After removing stale content, remove timed-out
+ * pending interests from storePendingInterest(), then if the added Data packet
+ * satisfies any interest, send it through the face and remove the interest
+ * from the pending interest table.
+ * @param {Data} data The Data packet object to put in the cache. This copies
+ * the fields from the object.
+ */
+MemoryContentCache.prototype.add = function(data)
+{
+  this.doCleanup();
+
+  if (data.getMetaInfo().getFreshnessPeriod() != null &&
+      data.getMetaInfo().getFreshnessPeriod() >= 0.0) {
+    // The content will go stale, so use staleTimeCache.
+    var content = new MemoryContentCache.StaleTimeContent(data);
+    // Insert into staleTimeCache, sorted on content.staleTimeMilliseconds.
+    // Search from the back since we expect it to go there.
+    var i = this.staleTimeCache.length - 1;
+    while (i >= 0) {
+      if (this.staleTimeCache[i].staleTimeMilliseconds <= content.staleTimeMilliseconds)
+        break;
+      --i;
+    }
+    // Element i is the greatest less than or equal to
+    // content.staleTimeMilliseconds, so insert after it.
+    this.staleTimeCache.splice(i + 1, 0, content);
+  }
+  else
+    // The data does not go stale, so use noStaleTimeCache.
+    this.noStaleTimeCache.push(new MemoryContentCache.Content(data));
+
+  // Remove timed-out interests and check if the data packet matches any pending
+  // interest.
+  // Go backwards through the list so we can erase entries.
+  var nowMilliseconds = new Date().getTime();
+  for (var i = this.pendingInterestTable.length - 1; i >= 0; --i) {
+    if (this.pendingInterestTable[i].isTimedOut(nowMilliseconds)) {
+      this.pendingInterestTable.splice(i, 1);
+      continue;
+    }
+    if (this.pendingInterestTable[i].getInterest().matchesName(data.getName())) {
+      try {
+        // Send to the same face from the original call to onInterest.
+        // wireEncode returns the cached encoding if available.
+        this.pendingInterestTable[i].getFace().send(data.wireEncode().buf());
+      }
+      catch (ex) {
+        if (LOG > 0)
+          console.log("" + ex);
+        return;
+      }
+
+      // The pending interest is satisfied, so remove it.
+      this.pendingInterestTable.splice(i, 1);
+    }
+  }
+};
+
+/**
+ * Store an interest from an OnInterest callback in the internal pending
+ * interest table (normally because there is no Data packet available yet to
+ * satisfy the interest). add(data) will check if the added Data packet
+ * satisfies any pending interest and send it through the face.
+ * @param {Interest} interest The Interest for which we don't have a Data packet
+ * yet. You should not modify the interest after calling this.
+ * @param {Face} face The Face with the connection which received
+ * the interest. This comes from the OnInterest callback.
+ */
+MemoryContentCache.prototype.storePendingInterest = function(interest, face)
+{
+  this.pendingInterestTable.push
+    (new MemoryContentCache.PendingInterest(interest, face));
+};
+
+/**
+ * Return a callback to use for onDataNotFound in registerPrefix which simply
+ * calls storePendingInterest() to store the interest that doesn't match a
+ * Data packet. add(data) will check if the added Data packet satisfies any
+ * pending interest and send it.
+ * @return {function} A callback to use for onDataNotFound in registerPrefix().
+ */
+MemoryContentCache.prototype.getStorePendingInterest = function()
+{
+  return this.storePendingInterestCallback;
+};
+
+/**
+ * This is the OnInterest callback which is called when the library receives
+ * an interest whose name has the prefix given to registerPrefix. First check
+ * if cleanupIntervalMilliseconds milliseconds have passed and remove stale
+ * content from the cache. Then search the cache for the Data packet, matching
+ * any interest selectors including ChildSelector, and send the Data packet
+ * to the face. If no matching Data packet is in the cache, call
+ * the callback in onDataNotFoundForPrefix (if defined).
+ */
+MemoryContentCache.prototype.onInterest = function
+  (prefix, interest, face, interestFilterId, filter)
+{
+  this.doCleanup();
+
+  var selectedComponent = 0;
+  var selectedEncoding = null;
+  // We need to iterate over both arrays.
+  var totalSize = this.staleTimeCache.length + this.noStaleTimeCache.length;
+  for (var i = 0; i < totalSize; ++i) {
+    var content;
+    if (i < this.staleTimeCache.length)
+      content = this.staleTimeCache[i];
+    else
+      // We have iterated over the first array. Get from the second.
+      content = this.noStaleTimeCache[i - this.staleTimeCache.length];
+
+    if (interest.matchesName(content.getName())) {
+      if (interest.getChildSelector() < 0) {
+        // No child selector, so send the first match that we have found.
+        face.send(content.getDataEncoding());
+        return;
+      }
+      else {
+        // Update selectedEncoding based on the child selector.
+        var component;
+        if (content.getName().size() > interest.getName().size())
+          component = content.getName().get(interest.getName().size());
+        else
+          component = this.emptyComponent;
+
+        var gotBetterMatch = false;
+        if (selectedEncoding === null)
+          // Save the first match.
+          gotBetterMatch = true;
+        else {
+          if (interest.getChildSelector() == 0) {
+            // Leftmost child.
+            if (component.compare(selectedComponent) < 0)
+              gotBetterMatch = true;
+          }
+          else {
+            // Rightmost child.
+            if (component.compare(selectedComponent) > 0)
+              gotBetterMatch = true;
+          }
+        }
+
+        if (gotBetterMatch) {
+          selectedComponent = component;
+          selectedEncoding = content.getDataEncoding();
+        }
+      }
+    }
+  }
+
+  if (selectedEncoding !== null)
+    // We found the leftmost or rightmost child.
+    face.send(selectedEncoding);
+  else {
+    // Call the onDataNotFound callback (if defined).
+    var onDataNotFound = this.onDataNotFoundForPrefix[prefix.toUri()];
+    if (onDataNotFound)
+      onDataNotFound(prefix, interest, face, interestFilterId, filter);
+  }
+};
+
+/**
+ * Check if now is greater than nextCleanupTime and, if so, remove stale
+ * content from staleTimeCache and reset nextCleanupTime based on
+ * cleanupIntervalMilliseconds. Since add(Data) does a sorted insert into
+ * staleTimeCache, the check for stale data is quick and does not require
+ * searching the entire staleTimeCache.
+ */
+MemoryContentCache.prototype.doCleanup = function()
+{
+  var now = new Date().getTime();
+  if (now >= this.nextCleanupTime) {
+    // staleTimeCache is sorted on staleTimeMilliseconds, so we only need to
+    // erase the stale entries at the front, then quit.
+    while (this.staleTimeCache.length > 0 && this.staleTimeCache[0].isStale(now))
+      this.staleTimeCache.shift();
+
+    this.nextCleanupTime = now + this.cleanupIntervalMilliseconds;
+  }
+};
+
+/**
+ * Content is a private class to hold the name and encoding for each entry
+ * in the cache. This base class is for a Data packet without a FreshnessPeriod.
+ *
+ * Create a new Content entry to hold data's name and wire encoding.
+ * @param {Data} data The Data packet whose name and wire encoding are copied.
+ */
+MemoryContentCache.Content = function MemoryContentCacheContent(data)
+{
+  // Allow an undefined data so that StaleTimeContent can set the prototype.
+  if (data) {
+    // Copy the name.
+    this.name = new Name(data.getName());
+    // wireEncode returns the cached encoding if available.
+    this.dataEncoding = data.wireEncode().buf();
+  }
+};
+
+MemoryContentCache.Content.prototype.getName = function() { return this.name; };
+
+MemoryContentCache.Content.prototype.getDataEncoding = function() { return this.dataEncoding; };
+
+/**
+ * StaleTimeContent extends Content to include the staleTimeMilliseconds for
+ * when this entry should be cleaned up from the cache.
+ *
+ * Create a new StaleTimeContent to hold data's name and wire encoding as well
+ * as the staleTimeMilliseconds which is now plus
+ * data.getMetaInfo().getFreshnessPeriod().
+ * @param {Data} data The Data packet whose name and wire encoding are copied.
+ */
+MemoryContentCache.StaleTimeContent = function MemoryContentCacheStaleTimeContent
+  (data)
+{
+  // Call the base constructor.
+  MemoryContentCache.Content.call(this, data);
+
+  // Set up staleTimeMilliseconds which is The time when the content becomse
+  // stale in milliseconds according to new Date().getTime().
+  this.staleTimeMilliseconds = new Date().getTime() +
+    data.getMetaInfo().getFreshnessPeriod();
+};
+
+MemoryContentCache.StaleTimeContent.prototype = new MemoryContentCache.Content();
+MemoryContentCache.StaleTimeContent.prototype.name = "StaleTimeContent";
+
+/**
+ * Check if this content is stale.
+ * @param {number} nowMilliseconds The current time in milliseconds from
+ * new Date().getTime().
+ * @return {boolean} True if this content is stale, otherwise false.
+ */
+MemoryContentCache.StaleTimeContent.prototype.isStale = function(nowMilliseconds)
+{
+  return this.staleTimeMilliseconds <= nowMilliseconds;
+};
+
+/**
+ * A PendingInterest holds an interest which onInterest received but could
+ * not satisfy. When we add a new data packet to the cache, we will also check
+ * if it satisfies a pending interest.
+ */
+MemoryContentCache.PendingInterest = function MemoryContentCachePendingInterest
+  (interest, face)
+{
+  this.interest = interest;
+  this.face = face;
+
+  if (this.interest.getInterestLifetimeMilliseconds() >= 0.0)
+    this.timeoutMilliseconds = (new Date()).getTime() +
+      this.interest.getInterestLifetimeMilliseconds();
+  else
+    this.timeoutMilliseconds = -1.0;
+};
+
+/**
+ * Return the interest given to the constructor.
+ */
+MemoryContentCache.PendingInterest.prototype.getInterest = function()
+{
+  return this.interest;
+};
+
+/**
+ * Return the face given to the constructor.
+ */
+MemoryContentCache.PendingInterest.prototype.getFace = function()
+{
+  return this.face;
+};
+
+/**
+ * Check if this interest is timed out.
+ * @param {number} nowMilliseconds The current time in milliseconds from
+ * new Date().getTime().
+ * @return {boolean} True if this interest timed out, otherwise false.
+ */
+MemoryContentCache.PendingInterest.prototype.isTimedOut = function(nowMilliseconds)
+{
+  return this.timeoutTimeMilliseconds >= 0.0 &&
+         nowMilliseconds >= this.timeoutTimeMilliseconds;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From PyNDN ndn_regex.py by Adeola Bannis.
+ * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../name.js').Name;
+
+/**
+ * An NdnRegexMatcher has static methods to convert an NDN regex
+ * (http://redmine.named-data.net/projects/ndn-cxx/wiki/Regex) to a JavaScript
+ * RegExp that can match against URIs.
+ * @constructor
+ */
+var NdnRegexMatcher = function NdnRegexMatcher()
+{
+};
+
+exports.NdnRegexMatcher = NdnRegexMatcher;
+
+/**
+ * Determine if the provided NDN regex matches the given Name.
+ * @param {string} pattern The NDN regex.
+ * @param {Name} name The Name to match against the regex.
+ * @return {Object} The match object from String.match, or null if the pattern
+ * does not match.
+ */
+NdnRegexMatcher.match = function(pattern, name)
+{
+  var nameUri = name.toUri();
+
+  pattern = NdnRegexMatcher.sanitizeSets(pattern);
+
+  pattern = pattern.replace(/<>/g, "(?:<.+?>)");
+  pattern = pattern.replace(/>/g, "");
+  pattern = pattern.replace(/<(?!!)/g, "/");
+
+  return nameUri.match(new RegExp(pattern));
+};
+
+NdnRegexMatcher.sanitizeSets = function(pattern)
+{
+  var newPattern = pattern;
+
+  // Positive sets can be changed to (comp1|comp2).
+  // Negative sets must be changed to negative lookahead assertions.
+
+  var regex1 = /\[(\^?)(.*?)\]/g;
+  var match;
+  while ((match = regex1.exec(pattern)) !== null) {
+    // Insert | between components.
+    // Match 2 is the last match, so we use the hack of working backwards from
+    //   lastIndex.  If possible, this should be changed to a more direct solution.
+    var start = regex1.lastIndex - "]".length - match[2].length;
+    var end = start + match[2].length;
+    if (start - end === 0)
+      continue;
+    var oldStr = match[2];
+    var newStr = oldStr.replace(/></g, ">|<");
+    newPattern = newPattern.substr(0, start) + newStr + newPattern.substr(end);
+  }
+
+  // Replace [] with (),  or (?! ) for negative lookahead.
+  // If we use negative lookahead, we also have to consume one component.
+  var isNegative = newPattern.indexOf("[^") >= 0;
+  if (isNegative) {
+    newPattern = newPattern.replace(/\[\^/g, "(?:(?!");
+    newPattern = newPattern.replace(/\]/g, ")(?:/.*)*)");
+  }
+  else {
+    newPattern = newPattern.replace(/\[/g, "(");
+    newPattern = newPattern.replace(/\]/g, ")");
+  }
+
+  return newPattern;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-cxx util/segment-fetcher https://github.com/named-data/ndn-cxx
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Blob = require('./blob.js').Blob; /** @ignore */
+var KeyChain = require('../security/key-chain.js').KeyChain; /** @ignore */
+var NdnCommon = require('./ndn-common.js').NdnCommon;
+
+/**
+ * SegmentFetcher is a utility class to fetch the latest version of segmented data.
+ *
+ * SegmentFetcher assumes that the data is named /<prefix>/<version>/<segment>,
+ * where:
+ * - <prefix> is the specified name prefix,
+ * - <version> is an unknown version that needs to be discovered, and
+ * - <segment> is a segment number. (The number of segments is unknown and is
+ *   controlled by the `FinalBlockId` field in at least the last Data packet.
+ *
+ * The following logic is implemented in SegmentFetcher:
+ *
+ * 1. Express the first Interest to discover the version:
+ *
+ *    >> Interest: /<prefix>?ChildSelector=1&MustBeFresh=true
+ *
+ * 2. Infer the latest version of the Data: <version> = Data.getName().get(-2)
+ *
+ * 3. If the segment number in the retrieved packet == 0, go to step 5.
+ *
+ * 4. Send an Interest for segment 0:
+ *
+ *    >> Interest: /<prefix>/<version>/<segment=0>
+ *
+ * 5. Keep sending Interests for the next segment while the retrieved Data does
+ *    not have a FinalBlockId or the FinalBlockId != Data.getName().get(-1).
+ *
+ *    >> Interest: /<prefix>/<version>/<segment=(N+1))>
+ *
+ * 6. Call the onComplete callback with a Blob that concatenates the content
+ *    from all the segmented objects.
+ *
+ * If an error occurs during the fetching process, the onError callback is called
+ * with a proper error code.  The following errors are possible:
+ *
+ * - `INTEREST_TIMEOUT`: if any of the Interests times out
+ * - `DATA_HAS_NO_SEGMENT`: if any of the retrieved Data packets don't have a segment
+ *   as the last component of the name (not counting the implicit digest)
+ * - `SEGMENT_VERIFICATION_FAILED`: if any retrieved segment fails
+ *   the user-provided VerifySegment callback or KeyChain verifyData.
+ * - `IO_ERROR`: for I/O errors when sending an Interest.
+ *
+ * In order to validate individual segments, a KeyChain needs to be supplied.
+ * If verifyData fails, the fetching process is aborted with
+ * SEGMENT_VERIFICATION_FAILED. If data validation is not required, pass null.
+ *
+ * Example:
+ *     var onComplete = function(content) { ... }
+ *
+ *     var onError = function(errorCode, message) { ... }
+ *
+ *     var interest = new Interest(new Name("/data/prefix"));
+ *     interest.setInterestLifetimeMilliseconds(1000);
+ *
+ *     SegmentFetcher.fetch(face, interest, null, onComplete, onError);
+ *
+ * This is a private constructor to create a new SegmentFetcher to use the Face.
+ * An application should use SegmentFetcher.fetch. If validatorKeyChain is not
+ * null, use it and ignore verifySegment. After creating the SegmentFetcher,
+ * call fetchFirstSegment.
+ * @param {Face} face This calls face.expressInterest to fetch more segments.
+ * @param validatorKeyChain {KeyChain} If this is not null, use its verifyData
+ * instead of the verifySegment callback.
+ * @param {function} verifySegment When a Data packet is received this calls
+ * verifySegment(data) where data is a Data object. If it returns False then
+ * abort fetching and call onError with
+ * SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onComplete When all segments are received, call
+ * onComplete(content) where content is a Blob which has the concatenation of
+ * the content of all the segments.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError Call onError.onError(errorCode, message) for
+ * timeout or an error processing segments. errorCode is a value from
+ * SegmentFetcher.ErrorCode and message is a related string.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @constructor
+ */
+var SegmentFetcher = function SegmentFetcher
+  (face, validatorKeyChain, verifySegment, onComplete, onError)
+{
+  this.face = face;
+  this.validatorKeyChain = validatorKeyChain;
+  this.verifySegment = verifySegment;
+  this.onComplete = onComplete;
+  this.onError = onError;
+
+  this.contentParts = []; // of Buffer
+};
+
+exports.SegmentFetcher = SegmentFetcher;
+
+/**
+ * An ErrorCode value is passed in the onError callback.
+ */
+SegmentFetcher.ErrorCode = {
+  INTEREST_TIMEOUT: 1,
+  DATA_HAS_NO_SEGMENT: 2,
+  SEGMENT_VERIFICATION_FAILED: 3
+};
+
+/**
+ * DontVerifySegment may be used in fetch to skip validation of Data packets.
+ */
+SegmentFetcher.DontVerifySegment = function(data)
+{
+  return true;
+};
+
+/**
+ * Initiate segment fetching. For more details, see the documentation for the
+ * class. There are two forms of fetch:
+ * fetch(face, baseInterest, validatorKeyChain, onComplete, onError)
+ * and
+ * fetch(face, baseInterest, verifySegment, onComplete, onError)
+ * @param {Face} face This calls face.expressInterest to fetch more segments.
+ * @param {Interest} baseInterest An Interest for the initial segment of the
+ * requested data, where baseInterest.getName() has the name prefix. This
+ * interest may include a custom InterestLifetime and selectors that will
+ * propagate to all subsequent Interests. The only exception is that the initial
+ * Interest will be forced to include selectors "ChildSelector=1" and
+ * "MustBeFresh=true" which will be turned off in subsequent Interests.
+ * @param validatorKeyChain {KeyChain} When a Data packet is received this calls
+ * validatorKeyChain.verifyData(data). If validation fails then abortfetching
+ * and call onError with SEGMENT_VERIFICATION_FAILED. This does not make a copy
+ * of the KeyChain; the object must remain valid while fetching.
+ * If validatorKeyChain is null, this does not validate the data packet.
+ * @param {function} verifySegment When a Data packet is received this calls
+ * verifySegment(data) where data is a Data object. If it returns False then
+ * abort fetching and call onError with
+ * SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED. If data validation is
+ * not required, use SegmentFetcher.DontVerifySegment.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onComplete When all segments are received, call
+ * onComplete(content) where content is a Blob which has the concatenation of
+ * the content of all the segments.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError Call onError.onError(errorCode, message) for
+ * timeout or an error processing segments. errorCode is a value from
+ * SegmentFetcher.ErrorCode and message is a related string.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+SegmentFetcher.fetch = function
+  (face, baseInterest, validatorKeyChainOrVerifySegment, onComplete, onError)
+{
+  if (validatorKeyChainOrVerifySegment == null ||
+      validatorKeyChainOrVerifySegment instanceof KeyChain)
+    new SegmentFetcher
+      (face, validatorKeyChainOrVerifySegment, SegmentFetcher.DontVerifySegment,
+       onComplete, onError)
+      .fetchFirstSegment(baseInterest);
+  else
+    new SegmentFetcher
+      (face, null, validatorKeyChainOrVerifySegment, onComplete, onError)
+      .fetchFirstSegment(baseInterest);
+};
+
+SegmentFetcher.prototype.fetchFirstSegment = function(baseInterest)
+{
+  var interest = new Interest(baseInterest);
+  interest.setChildSelector(1);
+  interest.setMustBeFresh(true);
+  var thisSegmentFetcher = this;
+  this.face.expressInterest
+    (interest,
+     function(originalInterest, data)
+       { thisSegmentFetcher.onData(originalInterest, data); },
+     function(interest) { thisSegmentFetcher.onTimeout(interest); });
+};
+
+SegmentFetcher.prototype.fetchNextSegment = function
+  (originalInterest, dataName, segment)
+{
+  // Start with the original Interest to preserve any special selectors.
+  var interest = new Interest(originalInterest);
+  // Changing a field clears the nonce so that the library will generate a new
+  // one.
+  interest.setChildSelector(0);
+  interest.setMustBeFresh(false);
+  interest.setName(dataName.getPrefix(-1).appendSegment(segment));
+  var thisSegmentFetcher = this;
+  this.face.expressInterest
+    (interest, function(originalInterest, data)
+       { thisSegmentFetcher.onData(originalInterest, data); },
+     function(interest) { thisSegmentFetcher.onTimeout(interest); });
+};
+
+SegmentFetcher.prototype.onData = function(originalInterest, data)
+{
+  if (this.validatorKeyChain != null) {
+    try {
+      var thisSegmentFetcher = this;
+      this.validatorKeyChain.verifyData
+        (data,
+         function(localData) {
+           thisSegmentFetcher.onVerified(localData, originalInterest);
+         },
+         this.onValidationFailed.bind(this));
+    } catch (ex) {
+      console.log("Error in KeyChain.verifyData: " + ex);
+    }
+  }
+  else {
+    if (!this.verifySegment(data)) {
+      try {
+        this.onError
+          (SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,
+           "Segment verification failed");
+      } catch (ex) {
+        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return;
+    }
+
+    this.onVerified(data, originalInterest);
+  }
+};
+
+SegmentFetcher.prototype.onVerified = function(data, originalInterest)
+{
+  if (!SegmentFetcher.endsWithSegmentNumber(data.getName())) {
+    // We don't expect a name without a segment number.  Treat it as a bad packet.
+    try {
+      this.onError
+        (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
+         "Got an unexpected packet without a segment number: " +
+          data.getName().toUri());
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+  else {
+    var currentSegment = 0;
+    try {
+      currentSegment = data.getName().get(-1).toSegment();
+    }
+    catch (ex) {
+      try {
+        this.onError
+          (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
+           "Error decoding the name segment number " +
+           data.getName().get(-1).toEscapedString() + ": " + ex);
+      } catch (ex) {
+        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return;
+    }
+
+    var expectedSegmentNumber = this.contentParts.length;
+    if (currentSegment != expectedSegmentNumber)
+      // Try again to get the expected segment.  This also includes the case
+      // where the first segment is not segment 0.
+      this.fetchNextSegment
+        (originalInterest, data.getName(), expectedSegmentNumber);
+    else {
+      // Save the content and check if we are finished.
+      this.contentParts.push(data.getContent().buf());
+
+      if (data.getMetaInfo().getFinalBlockId().getValue().size() > 0) {
+        var finalSegmentNumber = 0;
+        try {
+          finalSegmentNumber = (data.getMetaInfo().getFinalBlockId().toSegment());
+        }
+        catch (ex) {
+          try {
+            this.onError
+              (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
+               "Error decoding the FinalBlockId segment number " +
+               data.getMetaInfo().getFinalBlockId().toEscapedString() +
+               ": " + ex);
+          } catch (ex) {
+            console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+          }
+          return;
+        }
+
+        if (currentSegment == finalSegmentNumber) {
+          // We are finished.
+
+          // Concatenate to get content.
+          var content = Buffer.concat(this.contentParts);
+          try {
+            this.onComplete(new Blob(content, false));
+          } catch (ex) {
+            console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
+          }
+          return;
+        }
+      }
+
+      // Fetch the next segment.
+      this.fetchNextSegment
+        (originalInterest, data.getName(), expectedSegmentNumber + 1);
+    }
+  }
+}
+
+SegmentFetcher.prototype.onValidationFailed = function(data, reason)
+{
+  try {
+    this.onError
+      (SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,
+       "Segment verification failed for " + data.getName().toUri() +
+       " . Reason: " + reason);
+  } catch (ex) {
+    console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+};
+
+SegmentFetcher.prototype.onTimeout = function(interest)
+{
+  try {
+    this.onError
+      (SegmentFetcher.ErrorCode.INTEREST_TIMEOUT,
+       "Time out for interest " + interest.getName().toUri());
+  } catch (ex) {
+    console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+};
+
+/**
+ * Check if the last component in the name is a segment number.
+ * @param {Name} name The name to check.
+ * @return {boolean} True if the name ends with a segment number, otherwise false.
+ */
+SegmentFetcher.endsWithSegmentNumber = function(name)
+{
+  return name.size() >= 1 && name.get(-1).isSegment();
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Transport is a base class for specific transport classes such as TcpTransport.
+ * @constructor
+ */
+var Transport = function Transport()
+{
+};
+
+exports.Transport = Transport;
+
+/**
+ * Transport.ConnectionInfo is a base class for connection information used by
+ * subclasses of Transport.
+ */
+Transport.ConnectionInfo = function TransportConnectionInfo()
+{
+};
+
+/**
+ * Determine whether this transport connecting according to connectionInfo is to
+ * a node on the current machine. This affects the processing of
+ * Face.registerPrefix(): if the NFD is local, registration occurs with the
+ * '/localhost/nfd...' prefix; if non-local, the library will attempt to use
+ * remote prefix registration using '/localhop/nfd...'
+ * @param {Transport.ConnectionInfo} connectionInfo A ConnectionInfo with the
+ * host to check.
+ * @param {function} onResult On success, this calls onResult(isLocal) where
+ * isLocal is true if the host is local, false if not. We use callbacks because
+ * this may need to do an asynchronous DNS lookup.
+ * @param {function} onError On failure for DNS lookup or other error, this
+ * calls onError(message) where message is an error string.
+ */
+Transport.prototype.isLocal = function(connectionInfo, onResult, onError)
+{
+  onError("Transport.isLocal is not implemented");
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A MicroForwarderTransport extends Transport to connect to the browser's
+ * micro forwarder service. This assumes that the MicroForwarder extensions has
+ * been installed.
+ * @constructor
+ */
+var MicroForwarderTransport = function MicroForwarderTransport()
+{
+  // Call the base constructor.
+  Transport.call(this);
+
+  this.elementReader = null;
+  this.connectionInfo = null; // Read by Face.
+  this.onReceivedObject = null;
+
+  var thisTransport = this;
+  window.addEventListener("message", function(event) {
+    // We only accept messages from ourselves
+    if (event.source != window)
+      return;
+
+    if (event.data.type && (event.data.type == "FromMicroForwarderStub")) {
+      var obj = event.data.object;
+      if (obj.type && obj.type == "Buffer") {
+        if (thisTransport.elementReader != null)
+          thisTransport.elementReader.onReceivedData(new Buffer(obj.data));
+      }
+      else {
+        if (thisTransport.onReceivedObject)
+          thisTransport.onReceivedObject(obj);
+      }
+    }
+  }, false);
+};
+
+MicroForwarderTransport.prototype = new Transport();
+MicroForwarderTransport.prototype.name = "MicroForwarderTransport";
+
+/**
+ * Create a new MicroForwarderTransport.ConnectionInfo which extends
+ * Transport.ConnectionInfo to hold info for the micro forwarer connection.
+ */
+MicroForwarderTransport.ConnectionInfo = function MicroForwarderTransportConnectionInfo()
+{
+  // Call the base constructor.
+  Transport.ConnectionInfo .call(this);
+};
+
+MicroForwarderTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
+MicroForwarderTransport.ConnectionInfo.prototype.name = "MicroForwarderTransport.ConnectionInfo";
+
+/**
+ * Check if the fields of this MicroForwarderTransport.ConnectionInfo equal the other
+ * MicroForwarderTransport.ConnectionInfo.
+ * @param {MicroForwarderTransport.ConnectionInfo} The other object to check.
+ * @return {boolean} True if the objects have equal fields, false if not.
+ */
+MicroForwarderTransport.ConnectionInfo.prototype.equals = function(other)
+{
+  if (other == null)
+    return false;
+  return true;
+};
+
+MicroForwarderTransport.ConnectionInfo.prototype.toString = function()
+{
+  return "{}";
+};
+
+/**
+ * Set the onReceivedObject callback, replacing any previous callback.
+ * @param {function} onReceivedObject (optional) If supplied and the received
+ * object type field is not "Buffer" then just call this.onReceivedObject(obj).
+ * If this is null, then don't call it.
+ */
+MicroForwarderTransport.prototype.setOnReceivedObject = function(onReceivedObject)
+{
+  this.onReceivedObject = onReceivedObject;
+}
+
+/**
+ * Determine whether this transport connecting according to connectionInfo is to
+ * a node on the current machine. Unix transports are always local.
+ * @param {MicroForwarderTransport.ConnectionInfo} connectionInfo This is ignored.
+ * @param {function} onResult This calls onResult(true) because micro forwarder
+ * transports are always local.
+ * @param {function} onError This is ignored.
+ */
+MicroForwarderTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
+{
+  onResult(true);
+};
+
+/**
+ * Connect to the micro forwarder according to the info in connectionInfo.
+ * Listen on the connection to read an entire packet element and call
+ * elementListener.onReceivedElement(element). However, if the received object
+ * type field is not "Buffer" then just call this.onReceivedObject(obj).
+ * @param {MicroForwarderTransport.ConnectionInfo} connectionInfo
+ * @param {object} elementListener The elementListener with function
+ * onReceivedElement which must remain valid during the life of this object.
+ * @param {function} onopenCallback Once connected, call onopenCallback().
+ * @param {function} onclosedCallback (optional) If the connection is closed by
+ * the remote host, call onclosedCallback(). If omitted or null, don't call it.
+ */
+MicroForwarderTransport.prototype.connect = function
+  (connectionInfo, elementListener, onopenCallback, onclosedCallback)
+{
+  // The window listener is already set up.
+  this.elementReader = new ElementReader(elementListener);
+  this.connectionInfo = connectionInfo;
+  onopenCallback();
+};
+
+/**
+ * Send the JavaScript over the connection created by connect.
+ * @param {object} obj The object to send. It should have a field "type". If
+ * "type" is "Buffer" then it is processed like an NDN packet.
+ */
+MicroForwarderTransport.prototype.sendObject = function(obj)
+{
+  window.postMessage({
+    type: "FromMicroForwarderTransport",
+    object: obj
+  }, "*");
+};
+
+/**
+ * Send the buffer over the connection created by connect.
+ * @param {Buffer} buffer The bytes to send.
+ */
+MicroForwarderTransport.prototype.send = function(buffer)
+{
+  if (this.connectionInfo == null) {
+    console.log("MicroForwarderTransport connection is not established.");
+    return;
+  }
+
+  this.sendObject(buffer.toJSON());
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A RuntimePortTransport extends Transport to connect to a WebExtensions
+ * runtime.port.
+ * @param {function} onReceivedObject (optional) If supplied and the received
+ * object type field is not "Buffer" then just call this.onReceivedObject(obj).
+ * If this is null, then don't call it.
+ * @constructor
+ */
+var RuntimePortTransport = function RuntimePortTransport(onReceivedObject)
+{
+  // Call the base constructor.
+  Transport.call(this);
+
+  this.elementReader = null;
+  this.connectionInfo = null; // Read by Face.
+  this.onReceivedObject = onReceivedObject;
+  this.port = null;
+};
+
+RuntimePortTransport.prototype = new Transport();
+RuntimePortTransport.prototype.name = "RuntimePortTransport";
+
+/**
+ * Create a new RuntimePortTransport.ConnectionInfo which extends
+ * Transport.ConnectionInfo to hold the runtime.port used to connect.
+ * @param {runtime.port} port The runtime.port object.
+ */
+RuntimePortTransport.ConnectionInfo = function RuntimePortTransportConnectionInfo
+  (port)
+{
+  // Call the base constructor.
+  Transport.ConnectionInfo .call(this);
+
+  this.port = port;
+};
+
+RuntimePortTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
+RuntimePortTransport.ConnectionInfo.prototype.name = "RuntimePortTransport.ConnectionInfo";
+
+/**
+ * Check if the fields of this RuntimePortTransport.ConnectionInfo equal the other
+ * RuntimePortTransport.ConnectionInfo.
+ * @param {RuntimePortTransport.ConnectionInfo} The other object to check.
+ * @return {boolean} True if the objects have equal fields, false if not.
+ */
+RuntimePortTransport.ConnectionInfo.prototype.equals = function(other)
+{
+  if (other == null || other.port == undefined)
+    return false;
+  return this.port == other.port;
+};
+
+RuntimePortTransport.ConnectionInfo.prototype.toString = function()
+{
+  return "{}";
+};
+
+/**
+ * Set the onReceivedObject callback, replacing any previous callback.
+ * @param {function} onReceivedObject (optional) If supplied and the received
+ * object type field is not "Buffer" then just call this.onReceivedObject(obj).
+ * If this is null, then don't call it.
+ */
+RuntimePortTransport.prototype.setOnReceivedObject = function(onReceivedObject)
+{
+  this.onReceivedObject = onReceivedObject;
+}
+
+/**
+ * Determine whether this transport connecting according to connectionInfo is to
+ * a node on the current machine. RuntimePortTransport is always local.
+ * @param {RuntimePortTransport.ConnectionInfo} connectionInfo This is ignored.
+ * @param {function} onResult This calls onResult(true) because a runtime.port
+ * is always local.
+ * @param {function} onError This is ignored.
+ */
+RuntimePortTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
+{
+  onResult(true);
+};
+
+/**
+ * Connect to the runtime.port in connectionInfo. For a received object obj, if
+ * obj.type is "Buffer", read an entire packet element from obj.data and call
+ * elementListener.onReceivedElement(element). Otherwise just call
+ * onReceivedObject(obj) using the callback given to the constructor.
+ * @param {RuntimePortTransport.ConnectionInfo} connectionInfo The
+ * ConnectionInfo with the runtime.port.
+ * @param {object} elementListener The elementListener with function
+ * onReceivedElement which must remain valid during the life of this object.
+ * @param {function} onOpenCallback Once connected, call onOpenCallback().
+ * @param {function} onClosedCallback (optional) If the connection is closed by
+ * the remote host, call onClosedCallback(). If omitted or null, don't call it.
+ */
+RuntimePortTransport.prototype.connect = function
+  (connectionInfo, elementListener, onOpenCallback, onClosedCallback)
+{
+  // The window listener is already set up.
+  this.elementReader = new ElementReader(elementListener);
+  this.connectionInfo = connectionInfo;
+  this.port = this.connectionInfo.port;
+
+  // Add a listener to wait for a message object from the tab
+  var thisTransport = this;
+  this.port.onMessage.addListener(function(obj) {
+    if (obj.type == "Buffer")
+      thisTransport.elementReader.onReceivedData
+        (Buffer.isBuffer(obj.data) ? obj.data : new Buffer(obj.data));
+    else {
+      if (thisTransport.onReceivedObject != null)
+        thisTransport.onReceivedObject(obj);
+    }
+  });
+
+  this.port.onDisconnect.addListener(function() {
+    thisTransport.port = null;
+    if (onClosedCallback != null)
+      onClosedCallback();
+  });
+
+  onOpenCallback();
+};
+
+/**
+ * Send the JavaScript object over the connection created by connect.
+ * @param {object} obj The object to send. If it is a JSON Buffer then it is
+ * processed like an NDN packet.
+ */
+RuntimePortTransport.prototype.sendObject = function(obj)
+{
+  if (this.port == null) {
+    console.log("RuntimePortTransport connection is not established.");
+    return;
+  }
+
+  this.port.postMessage(obj);
+};
+
+/**
+ * Send the buffer over the connection created by connect.
+ * @param {Buffer} buffer The bytes to send.
+ */
+RuntimePortTransport.prototype.send = function(buffer)
+{
+  this.sendObject(buffer.toJSON());
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var ElementReader = require('../encoding/element-reader.js').ElementReader; /** @ignore */
+var LOG = require('../log.js').Log.LOG; /** @ignore */
+var Transport = require('./transport.js').Transport; /** @ignore */
+var Face;
+
+/**
+ * @constructor
+ */
+var WebSocketTransport = function WebSocketTransport()
+{
+  // Call the base constructor.
+  Transport.call(this);
+
+  if (!WebSocket)
+    throw new Error("WebSocket support is not available on this platform.");
+
+  this.ws = null;
+  this.connectionInfo = null; // Read by Face.
+  this.elementReader = null;
+  this.defaultGetConnectionInfo = Face.makeShuffledHostGetConnectionInfo
+    (["A.ws.ndn.ucla.edu", "B.ws.ndn.ucla.edu", "C.ws.ndn.ucla.edu", "D.ws.ndn.ucla.edu",
+      "E.ws.ndn.ucla.edu", "F.ws.ndn.ucla.edu", "G.ws.ndn.ucla.edu", "H.ws.ndn.ucla.edu",
+      "I.ws.ndn.ucla.edu", "J.ws.ndn.ucla.edu", "K.ws.ndn.ucla.edu", "L.ws.ndn.ucla.edu",
+      "M.ws.ndn.ucla.edu", "N.ws.ndn.ucla.edu"],
+     9696,
+     function(host, port) { return new WebSocketTransport.ConnectionInfo(host, port); });
+};
+
+WebSocketTransport.prototype = new Transport();
+WebSocketTransport.prototype.name = "WebSocketTransport";
+
+WebSocketTransport.importFace = function(face){
+  Face = face;
+};
+
+exports.WebSocketTransport = WebSocketTransport;
+
+/**
+ * Create a new WebSocketTransport.ConnectionInfo which extends
+ * Transport.ConnectionInfo to hold the host and port info for the WebSocket
+ * connection.
+ * @param {string} host The host for the connection. However, if the host string
+ * begins with "ws:" or "wss:", then ignore port and use the string as the full
+ * endpoint URI.
+ * @param {number} port (optional) The port number for the connection. If
+ * omitted, use 9696.
+ */
+WebSocketTransport.ConnectionInfo = function WebSocketTransportConnectionInfo
+  (host, port)
+{
+  // Call the base constructor.
+  Transport.ConnectionInfo .call(this);
+
+  port = (port !== undefined ? port : 9696);
+
+  this.host = host;
+  this.port = port;
+};
+
+WebSocketTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
+WebSocketTransport.ConnectionInfo.prototype.name = "WebSocketTransport.ConnectionInfo";
+
+/**
+ * Check if the fields of this WebSocketTransport.ConnectionInfo equal the other
+ * WebSocketTransport.ConnectionInfo.
+ * @param {WebSocketTransport.ConnectionInfo} The other object to check.
+ * @return {boolean} True if the objects have equal fields, false if not.
+ */
+WebSocketTransport.ConnectionInfo.prototype.equals = function(other)
+{
+  if (other == null || other.host == undefined || other.port == undefined)
+    return false;
+  return this.host == other.host && this.port == other.port;
+};
+
+WebSocketTransport.ConnectionInfo.prototype.toString = function()
+{
+  if (this.hostIsUri())
+    return "{ uri: " + this.host + " }";
+  else
+    return "{ host: " + this.host + ", port: " + this.port + " }";
+};
+
+WebSocketTransport.ConnectionInfo.prototype.hostIsUri = function()
+{
+  return this.host.substr(0, 3) == "ws:" ||
+         this.host.substr(0, 4) == "wss:";
+}
+
+/**
+ * Determine whether this transport connecting according to connectionInfo is to
+ * a node on the current machine. WebSocket transports are always non-local.
+ * @param {WebSocketTransport.ConnectionInfo} connectionInfo This is ignored.
+ * @param {function} onResult This calls onResult(false) because WebSocket
+ * transports are always non-local.
+ * @param {function} onError This is ignored.
+ */
+WebSocketTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
+{
+  onResult(false);
+};
+
+/**
+ * Connect to a WebSocket according to the info in connectionInfo. Listen on
+ * the port to read an entire packet element and call
+ * elementListener.onReceivedElement(element). Note: this connect method
+ * previously took a Face object which is deprecated and renamed as the method
+ * connectByFace.
+ * @param {WebSocketTransport.ConnectionInfo} connectionInfo A
+ * WebSocketTransport.ConnectionInfo.
+ * @param {object} elementListener The elementListener with function
+ * onReceivedElement which must remain valid during the life of this object.
+ * @param {function} onopenCallback Once connected, call onopenCallback().
+ * @param {function} onclosedCallback (optional) If the connection is closed by
+ * the remote host, call onclosedCallback(). If omitted or null, don't call it.
+ */
+WebSocketTransport.prototype.connect = function
+  (connectionInfo, elementListener, onopenCallback, onclosedCallback)
+{
+  this.close();
+
+  var uri = connectionInfo.hostIsUri() ?
+    connectionInfo.host : 'ws://' + connectionInfo.host + ':' + connectionInfo.port;
+  this.ws = new WebSocket(uri);
+  if (LOG > 0) console.log('ws connection created.');
+    this.connectionInfo = connectionInfo;
+
+  this.ws.binaryType = "arraybuffer";
+
+  this.elementReader = new ElementReader(elementListener);
+  var self = this;
+  this.ws.onmessage = function(ev) {
+    var result = ev.data;
+    //console.log('RecvHandle called.');
+
+    if (result == null || result == undefined || result == "") {
+      console.log('INVALID ANSWER');
+    }
+    else if (result instanceof ArrayBuffer) {
+      // The Buffer constructor expects an instantiated array.
+      var bytearray = new Buffer(new Uint8Array(result));
+
+      if (LOG > 3) console.log('BINARY RESPONSE IS ' + bytearray.toString('hex'));
+
+      try {
+        // Find the end of the element and call onReceivedElement.
+        self.elementReader.onReceivedData(bytearray);
+      } catch (ex) {
+        console.log("NDN.ws.onmessage exception: " + ex);
+        return;
+      }
+    }
+  }
+
+  this.ws.onopen = function(ev) {
+    if (LOG > 3) console.log(ev);
+    if (LOG > 3) console.log('ws.onopen: WebSocket connection opened.');
+    if (LOG > 3) console.log('ws.onopen: ReadyState: ' + this.readyState);
+    // Face.registerPrefix will fetch the ndndid when needed.
+
+    onopenCallback();
+  }
+
+  this.ws.onerror = function(ev) {
+    console.log('ws.onerror: ReadyState: ' + this.readyState);
+    console.log(ev);
+    console.log('ws.onerror: WebSocket error: ' + ev.data);
+  }
+
+  this.ws.onclose = function(ev) {
+    console.log('ws.onclose: WebSocket connection closed.');
+    self.ws = null;
+
+    if (onclosedCallback != null)
+      onclosedCallback();
+  }
+};
+
+/**
+ * @deprecated This is deprecated. You should not call Transport.connect
+ * directly, since it is called by Face methods.
+ */
+WebSocketTransport.prototype.connectByFace = function(face, onopenCallback)
+{
+  this.connect
+    (face.connectionInfo, face, onopenCallback,
+     function() { face.closeByTransport(); });
+};
+
+/**
+ * Send the Uint8Array data.
+ */
+WebSocketTransport.prototype.send = function(data)
+{
+  if (this.ws != null) {
+    // If we directly use data.buffer to feed ws.send(),
+    // WebSocket may end up sending a packet with 10000 bytes of data.
+    // That is, WebSocket will flush the entire buffer
+    // regardless of the offset of the Uint8Array. So we have to create
+    // a new Uint8Array buffer with just the right size and copy the
+    // content from binaryInterest to the new buffer.
+    //    ---Wentao
+    var bytearray = new Uint8Array(data.length);
+    bytearray.set(data);
+    this.ws.send(bytearray.buffer);
+    if (LOG > 3) console.log('ws.send() returned.');
+  }
+  else
+    console.log('WebSocket connection is not established.');
+};
+
+/**
+ * Close the connection.
+ */
+WebSocketTransport.prototype.close = function()
+{
+  if (this.ws != null)
+    delete this.ws;
+}
+
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// The Face constructor uses TcpTransport by default which is not available in the browser, so override to WebSocketTransport.
+exports.TcpTransport = require("./transport/web-socket-transport").WebSocketTransport;
+/**
+ * This class represents a Name as an array of components where each is a byte array.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cheraoui, Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
+var LOG = require('./log.js').Log.LOG;
+var DecodingException = require('./encoding/decoding-exception.js').DecodingException;
+
+/**
+ * Create a new Name from components.
+ *
+ * @constructor
+ * @param {string|Name|Array<string|Array<number>|ArrayBuffer|Buffer|Name>} components if a string, parse it as a URI.  If a Name, add a deep copy of its components.
+ * Otherwise it is an array of components which are appended according to Name.append, so
+ * convert each and store it as an array of Buffer.  If a component is a string, encode as utf8.
+ */
+var Name = function Name(components)
+{
+  if (typeof components == 'string') {
+    if (LOG > 3) console.log('Content Name String ' + components);
+    this.components = Name.createNameArray(components);
+  }
+  else if (typeof components === 'object') {
+    this.components = [];
+    if (components instanceof Name)
+      this.append(components);
+    else {
+      for (var i = 0; i < components.length; ++i)
+        this.append(components[i]);
+    }
+  }
+  else if (components == null)
+    this.components = [];
+  else
+    if (LOG > 1) console.log("NO CONTENT NAME GIVEN");
+
+  this.changeCount = 0;
+};
+
+exports.Name = Name;
+
+/**
+ * Create a new GENERIC Name.Component with a copy of the given value.
+ * (To create an ImplicitSha256Digest component, use fromImplicitSha256Digest.)
+ * @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer} value If the value is a string, encode it as utf8 (but don't unescape).
+ * @constructor
+ */
+Name.Component = function NameComponent(value)
+{
+  if (typeof value === 'object' && value instanceof Name.Component) {
+    // The copy constructor.
+    this.value_ = value.value_;
+    this.type_ = value.type_;
+    return;
+  }
+
+  if (!value)
+    this.value_ = new Blob([]);
+  else if (typeof value === 'object' && typeof ArrayBuffer !== 'undefined' &&
+           value instanceof ArrayBuffer)
+    // Make a copy.  Turn the value into a Uint8Array since the Buffer
+    //   constructor doesn't take an ArrayBuffer.
+    this.value_ = new Blob(new Buffer(new Uint8Array(value)), false);
+  else if (typeof value === 'object' && value instanceof Blob)
+    this.value_ = value;
+  else
+    // Blob will make a copy if needed.
+    this.value_ = new Blob(value);
+
+  this.type_ = Name.Component.ComponentType.GENERIC;
+};
+
+/**
+ * A Name.Component.ComponentType specifies the recognized types of a name
+ * component.
+ */
+Name.Component.ComponentType = {
+  IMPLICIT_SHA256_DIGEST: 1,
+  GENERIC: 8
+};
+
+/**
+ * Get the component value.
+ * @return {Blob} The component value.
+ */
+Name.Component.prototype.getValue = function()
+{
+  return this.value_;
+};
+
+/**
+ * @deprecated Use getValue. This method returns a Buffer which is the former
+ * behavior of getValue, and should only be used while updating your code.
+ */
+Name.Component.prototype.getValueAsBuffer = function()
+{
+  // Assume the caller won't modify it.
+  return this.value_.buf();
+};
+
+/**
+ * @deprecated Use getValue which returns a Blob.
+ */
+Object.defineProperty(Name.Component.prototype, "value",
+  { get: function() { return this.getValueAsBuffer(); } });
+
+/**
+ * Convert this component value to a string by escaping characters according to the NDN URI Scheme.
+ * This also adds "..." to a value with zero or more ".".
+ * This adds a type code prefix as needed, such as "sha256digest=".
+ * @return {string} The escaped string.
+ */
+Name.Component.prototype.toEscapedString = function()
+{
+  if (this.type_ === Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST)
+    return "sha256digest=" + this.value_.toHex();
+  else
+    return Name.toEscapedString(this.value_.buf());
+};
+
+/**
+ * Check if this component is a segment number according to NDN naming
+ * conventions for "Segment number" (marker 0x00).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return {number}  True if this is a segment number.
+ */
+Name.Component.prototype.isSegment = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0x00 &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a segment byte offset according to NDN
+ * naming conventions for segment "Byte offset" (marker 0xFB).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return  True if this is a segment byte offset.
+ */
+Name.Component.prototype.isSegmentOffset = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFB &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a version number  according to NDN naming
+ * conventions for "Versioning" (marker 0xFD).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return {number}  True if this is a version number.
+ */
+Name.Component.prototype.isVersion = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFD &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a timestamp  according to NDN naming
+ * conventions for "Timestamp" (marker 0xFC).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return  True if this is a timestamp.
+ */
+Name.Component.prototype.isTimestamp = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFC &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a sequence number according to NDN naming
+ * conventions for "Sequencing" (marker 0xFE).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return  True if this is a sequence number.
+ */
+Name.Component.prototype.isSequenceNumber = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFE &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a generic component.
+ * @return {boolean} True if this is an generic component.
+ */
+Name.Component.prototype.isGeneric = function()
+{
+  return this.type_ === Name.Component.ComponentType.GENERIC;
+};
+
+/**
+ * Check if this component is an ImplicitSha256Digest component.
+ * @return {boolean} True if this is an ImplicitSha256Digest component.
+ */
+Name.Component.prototype.isImplicitSha256Digest = function()
+{
+  return this.type_ === Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST;
+};
+
+/**
+ * Interpret this name component as a network-ordered number and return an integer.
+ * @return {number} The integer number.
+ */
+Name.Component.prototype.toNumber = function()
+{
+  return DataUtils.bigEndianToUnsignedInt(this.value_.buf());
+};
+
+/**
+ * Interpret this name component as a network-ordered number with a marker and
+ * return an integer.
+ * @param {number} marker The required first byte of the component.
+ * @return {number} The integer number.
+ * @throws Error If the first byte of the component does not equal the marker.
+ */
+Name.Component.prototype.toNumberWithMarker = function(marker)
+{
+  if (this.value_.size() == 0 || this.value_.buf()[0] != marker)
+    throw new Error("Name component does not begin with the expected marker");
+
+  return DataUtils.bigEndianToUnsignedInt(this.value_.buf().slice(1));
+};
+
+/**
+ * Interpret this name component as a segment number according to NDN naming
+ * conventions for "Segment number" (marker 0x00).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return {number} The integer segment number.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toSegment = function()
+{
+  return this.toNumberWithMarker(0x00);
+};
+
+/**
+ * Interpret this name component as a segment byte offset according to NDN
+ * naming conventions for segment "Byte offset" (marker 0xFB).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return The integer segment byte offset.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toSegmentOffset = function()
+{
+  return this.toNumberWithMarker(0xFB);
+};
+
+/**
+ * Interpret this name component as a version number  according to NDN naming
+ * conventions for "Versioning" (marker 0xFD). Note that this returns
+ * the exact number from the component without converting it to a time
+ * representation.
+ * @return {number} The integer version number.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toVersion = function()
+{
+  return this.toNumberWithMarker(0xFD);
+};
+
+/**
+ * Interpret this name component as a timestamp  according to NDN naming
+ * conventions for "Timestamp" (marker 0xFC).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return The number of microseconds since the UNIX epoch (Thursday,
+ * 1 January 1970) not counting leap seconds.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toTimestamp = function()
+{
+  return this.toNumberWithMarker(0xFC);
+};
+
+/**
+ * Interpret this name component as a sequence number according to NDN naming
+ * conventions for "Sequencing" (marker 0xFE).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return The integer sequence number.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toSequenceNumber = function()
+{
+  return this.toNumberWithMarker(0xFE);
+};
+
+/**
+ * Create a component whose value is the nonNegativeInteger encoding of the
+ * number.
+ * @param {number} number
+ * @return {Name.Component}
+ */
+Name.Component.fromNumber = function(number)
+{
+  var encoder = new TlvEncoder(8);
+  encoder.writeNonNegativeInteger(number);
+  return new Name.Component(new Blob(encoder.getOutput(), false));
+};
+
+/**
+ * Create a component whose value is the marker appended with the
+ * nonNegativeInteger encoding of the number.
+ * @param {number} number
+ * @param {number} marker
+ * @return {Name.Component}
+ */
+Name.Component.fromNumberWithMarker = function(number, marker)
+{
+  var encoder = new TlvEncoder(9);
+  // Encode backwards.
+  encoder.writeNonNegativeInteger(number);
+  encoder.writeNonNegativeInteger(marker);
+  return new Name.Component(new Blob(encoder.getOutput(), false));
+};
+
+/**
+ * Create a component with the encoded segment number according to NDN
+ * naming conventions for "Segment number" (marker 0x00).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * param {number} segment The segment number.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromSegment = function(segment)
+{
+  return Name.Component.fromNumberWithMarker(segment, 0x00);
+};
+
+/**
+ * Create a component with the encoded segment byte offset according to NDN
+ * naming conventions for segment "Byte offset" (marker 0xFB).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * param {number} segmentOffset The segment byte offset.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromSegmentOffset = function(segmentOffset)
+{
+  return Name.Component.fromNumberWithMarker(segmentOffset, 0xFB);
+};
+
+/**
+ * Create a component with the encoded version number according to NDN
+ * naming conventions for "Versioning" (marker 0xFD).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * Note that this encodes the exact value of version without converting from a
+ * time representation.
+ * param {number} version The version number.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromVersion = function(version)
+{
+  return Name.Component.fromNumberWithMarker(version, 0xFD);
+};
+
+/**
+ * Create a component with the encoded timestamp according to NDN naming
+ * conventions for "Timestamp" (marker 0xFC).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * param {number} timestamp The number of microseconds since the UNIX epoch (Thursday,
+ * 1 January 1970) not counting leap seconds.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromTimestamp = function(timestamp)
+{
+  return Name.Component.fromNumberWithMarker(timestamp, 0xFC);
+};
+
+/**
+ * Create a component with the encoded sequence number according to NDN naming
+ * conventions for "Sequencing" (marker 0xFE).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * param {number} sequenceNumber The sequence number.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromSequenceNumber = function(sequenceNumber)
+{
+  return Name.Component.fromNumberWithMarker(sequenceNumber, 0xFE);
+};
+
+/**
+ * Create a component of type ImplicitSha256DigestComponent, so that
+ * isImplicitSha256Digest() is true.
+ * @param {Blob|Buffer} digest The SHA-256 digest value.
+ * @return {Name.Component} The new Component.
+ * @throws DecodingException If the digest length is not 32 bytes.
+ */
+Name.Component.fromImplicitSha256Digest = function(digest)
+{
+  digestBlob = typeof digest === 'object' && digest instanceof Blob ?
+    digest : new Blob(digest, true);
+  if (digestBlob.size() !== 32)
+    throw new DecodingException
+      ("Name.Component.fromImplicitSha256Digest: The digest length must be 32 bytes");
+
+  var result = new Name.Component(digestBlob);
+  result.type_ = Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST;
+  return result;
+};
+
+/**
+ * Get the successor of this component, as described in Name.getSuccessor.
+ * @return {Name.Component} A new Name.Component which is the successor of this.
+ */
+Name.Component.prototype.getSuccessor = function()
+{
+  // Allocate an extra byte in case the result is larger.
+  var result = new Buffer(this.value_.size() + 1);
+
+  var carry = true;
+  for (var i = this.value_.size() - 1; i >= 0; --i) {
+    if (carry) {
+      result[i] = (this.value_.buf()[i] + 1) & 0xff;
+      carry = (result[i] === 0);
+    }
+    else
+      result[i] = this.value_.buf()[i];
+  }
+
+  if (carry)
+    // Assume all the bytes were set to zero (or the component was empty). In
+    // NDN ordering, carry does not mean to prepend a 1, but to make a component
+    // one byte longer of all zeros.
+    result[result.length - 1] = 0;
+  else
+    // We didn't need the extra byte.
+    result = result.slice(0, this.value_.size());
+
+  return new Name.Component(new Blob(result, false));
+};
+
+/**
+ * Check if this is the same component as other.
+ * @param {Name.Component} other The other Component to compare with.
+ * @return {Boolean} true if the components are equal, otherwise false.
+ */
+Name.Component.prototype.equals = function(other)
+{
+  return typeof other === 'object' && other instanceof Name.Component &&
+    this.value_.equals(other.value_) && this.type_ === other.type_;
+};
+
+/**
+ * Compare this to the other Component using NDN canonical ordering.
+ * @param {Name.Component} other The other Component to compare with.
+ * @return {number} 0 if they compare equal, -1 if this comes before other in
+ * the canonical ordering, or 1 if this comes after other in the canonical
+ * ordering.
+ *
+ * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
+ */
+Name.Component.prototype.compare = function(other)
+{
+  if (this.type_ < other.type_)
+    return -1;
+  if (this.type_ > other.type_)
+    return 1;
+
+  return Name.Component.compareBuffers(this.value_.buf(), other.value_.buf());
+};
+
+/**
+ * Do the work of Name.Component.compare to compare the component buffers.
+ * @param {Buffer} component1
+ * @param {Buffer} component2
+ * @return {number} 0 if they compare equal, -1 if component1 comes before
+ * component2 in the canonical ordering, or 1 if component1 comes after
+ * component2 in the canonical ordering.
+ */
+Name.Component.compareBuffers = function(component1, component2)
+{
+  if (component1.length < component2.length)
+    return -1;
+  if (component1.length > component2.length)
+    return 1;
+
+  for (var i = 0; i < component1.length; ++i) {
+    if (component1[i] < component2[i])
+      return -1;
+    if (component1[i] > component2[i])
+      return 1;
+  }
+
+  return 0;
+};
+
+/**
+ * @deprecated Use toUri.
+ */
+Name.prototype.getName = function()
+{
+  return this.toUri();
+};
+
+/** Parse uri as a URI and return an array of Buffer components.
+ */
+Name.createNameArray = function(uri)
+{
+  uri = uri.trim();
+  if (uri.length <= 0)
+    return [];
+
+  var iColon = uri.indexOf(':');
+  if (iColon >= 0) {
+    // Make sure the colon came before a '/'.
+    var iFirstSlash = uri.indexOf('/');
+    if (iFirstSlash < 0 || iColon < iFirstSlash)
+      // Omit the leading protocol such as ndn:
+      uri = uri.substr(iColon + 1, uri.length - iColon - 1).trim();
+  }
+
+  if (uri[0] == '/') {
+    if (uri.length >= 2 && uri[1] == '/') {
+      // Strip the authority following "//".
+      var iAfterAuthority = uri.indexOf('/', 2);
+      if (iAfterAuthority < 0)
+        // Unusual case: there was only an authority.
+        return [];
+      else
+        uri = uri.substr(iAfterAuthority + 1, uri.length - iAfterAuthority - 1).trim();
+    }
+    else
+      uri = uri.substr(1, uri.length - 1).trim();
+  }
+
+  var array = uri.split('/');
+
+  // Unescape the components.
+  var sha256digestPrefix = "sha256digest=";
+  for (var i = 0; i < array.length; ++i) {
+    var component;
+    if (array[i].substr(0, sha256digestPrefix.length) == sha256digestPrefix) {
+      var hexString = array[i].substr(sha256digestPrefix.length).trim();
+      component = Name.Component.fromImplicitSha256Digest
+        (new Blob(new Buffer(hexString, 'hex')), false);
+    }
+    else
+      component = new Name.Component(Name.fromEscapedString(array[i]));
+
+    if (component.getValue().isNull()) {
+      // Ignore the illegal componenent.  This also gets rid of a trailing '/'.
+      array.splice(i, 1);
+      --i;
+      continue;
+    }
+    else
+      array[i] = component;
+  }
+
+  return array;
+};
+
+/**
+ * Parse the uri according to the NDN URI Scheme and set the name with the
+ * components.
+ * @param {string} uri The URI string.
+ */
+Name.prototype.set = function(uri)
+{
+  this.components = Name.createNameArray(uri);
+  ++this.changeCount;
+};
+
+/**
+ * Convert the component to a Buffer and append a GENERIC component to this Name.
+ * Return this Name object to allow chaining calls to add.
+ * @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer|Name} component If a component is a string, encode as utf8 (but don't unescape).
+ * @return {Name}
+ */
+Name.prototype.append = function(component)
+{
+  if (typeof component == 'object' && component instanceof Name) {
+    var components;
+    if (component == this)
+      // special case, when we need to create a copy
+      components = this.components.slice(0, this.components.length);
+    else
+      components = component.components;
+
+    for (var i = 0; i < components.length; ++i)
+      this.components.push(new Name.Component(components[i]));
+  }
+  else if (typeof component === 'object' && component instanceof Name.Component)
+    // The Component is immutable, so use it as is.
+    this.components.push(component);
+  else
+    // Just use the Name.Component constructor.
+    this.components.push(new Name.Component(component));
+
+  ++this.changeCount;
+  return this;
+};
+
+/**
+ * @deprecated Use append.
+ */
+Name.prototype.add = function(component)
+{
+  return this.append(component);
+};
+
+/**
+ * Clear all the components.
+ */
+Name.prototype.clear = function()
+{
+  this.components = [];
+  ++this.changeCount;
+};
+
+/**
+ * Return the escaped name string according to NDN URI Scheme.
+ * @param {boolean} includeScheme (optional) If true, include the "ndn:" scheme
+ * in the URI, e.g. "ndn:/example/name". If false, just return the path, e.g.
+ * "/example/name". If ommitted, then just return the path which is the default
+ * case where toUri() is used for display.
+ * @return {String}
+ */
+Name.prototype.toUri = function(includeScheme)
+{
+  if (this.size() == 0)
+    return includeScheme ? "ndn:/" : "/";
+
+  var result = includeScheme ? "ndn:" : "";
+
+  for (var i = 0; i < this.size(); ++i)
+    result += "/"+ this.components[i].toEscapedString();
+
+  return result;
+};
+
+/**
+ * @deprecated Use toUri.
+ */
+Name.prototype.to_uri = function()
+{
+  return this.toUri();
+};
+
+Name.prototype.toString = function() { return this.toUri(); }
+
+/**
+ * Append a component with the encoded segment number according to NDN
+ * naming conventions for "Segment number" (marker 0x00).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @param {number} segment The segment number.
+ * @return {Name} This name so that you can chain calls to append.
+ */
+Name.prototype.appendSegment = function(segment)
+{
+  return this.append(Name.Component.fromSegment(segment));
+};
+
+/**
+ * Append a component with the encoded segment byte offset according to NDN
+ * naming conventions for segment "Byte offset" (marker 0xFB).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @param {number} segmentOffset The segment byte offset.
+ * @return {Name} This name so that you can chain calls to append.
+ */
+Name.prototype.appendSegmentOffset = function(segmentOffset)
+{
+  return this.append(Name.Component.fromSegmentOffset(segmentOffset));
+};
+
+/**
+ * Append a component with the encoded version number according to NDN
+ * naming conventions for "Versioning" (marker 0xFD).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * Note that this encodes the exact value of version without converting from a time representation.
+ * @param {number} version The version number.
+ * @return {Name} This name so that you can chain calls to append.
+ */
+Name.prototype.appendVersion = function(version)
+{
+  return this.append(Name.Component.fromVersion(version));
+};
+
+/**
+ * Append a component with the encoded timestamp according to NDN naming
+ * conventions for "Timestamp" (marker 0xFC).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @param {number} timestamp The number of microseconds since the UNIX epoch (Thursday,
+ * 1 January 1970) not counting leap seconds.
+ * @return This name so that you can chain calls to append.
+ */
+Name.prototype.appendTimestamp = function(timestamp)
+{
+  return this.append(Name.Component.fromTimestamp(timestamp));
+};
+
+/**
+ * Append a component with the encoded sequence number according to NDN naming
+ * conventions for "Sequencing" (marker 0xFE).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @param {number} sequenceNumber The sequence number.
+ * @return This name so that you can chain calls to append.
+ */
+Name.prototype.appendSequenceNumber = function(sequenceNumber)
+{
+  return this.append(Name.Component.fromSequenceNumber(sequenceNumber));
+};
+
+/**
+ * Append a component of type ImplicitSha256DigestComponent, so that
+ * isImplicitSha256Digest() is true.
+ * @param {Blob|Buffer} digest The SHA-256 digest value.
+ * @return This name so that you can chain calls to append.
+ * @throws DecodingException If the digest length is not 32 bytes.
+ */
+Name.prototype.appendImplicitSha256Digest = function(digest)
+{
+  return this.append(Name.Component.fromImplicitSha256Digest(digest));
+};
+
+/**
+ * @deprecated Use appendSegment.
+ */
+Name.prototype.addSegment = function(number)
+{
+  return this.appendSegment(number);
+};
+
+/**
+ * Get a new name, constructed as a subset of components.
+ * @param {number} iStartComponent The index if the first component to get. If
+ * iStartComponent is -N then return return components starting from
+ * name.size() - N.
+ * @param {number} (optional) nComponents The number of components starting at
+ * iStartComponent. If omitted or greater than the size of this name, get until
+ * the end of the name.
+ * @return {Name} A new name.
+ */
+Name.prototype.getSubName = function(iStartComponent, nComponents)
+{
+  if (iStartComponent < 0)
+    iStartComponent = this.components.length - (-iStartComponent);
+
+  if (nComponents == undefined)
+    nComponents = this.components.length - iStartComponent;
+
+  var result = new Name();
+
+  var iEnd = iStartComponent + nComponents;
+  for (var i = iStartComponent; i < iEnd && i < this.components.length; ++i)
+    result.components.push(this.components[i]);
+
+  return result;
+};
+
+/**
+ * Return a new Name with the first nComponents components of this Name.
+ * @param {number} nComponents The number of prefix components.  If nComponents is -N then return the prefix up
+ * to name.size() - N. For example getPrefix(-1) returns the name without the final component.
+ * @return {Name} A new name.
+ */
+Name.prototype.getPrefix = function(nComponents)
+{
+  if (nComponents < 0)
+    return this.getSubName(0, this.components.length + nComponents);
+  else
+    return this.getSubName(0, nComponents);
+};
+
+/**
+ * @deprecated Use getPrefix(-nComponents).
+ */
+Name.prototype.cut = function(nComponents)
+{
+  return new Name(this.components.slice(0, this.components.length - nComponents));
+};
+
+/**
+ * Return the number of name components.
+ * @return {number}
+ */
+Name.prototype.size = function()
+{
+  return this.components.length;
+};
+
+/**
+ * Get a Name Component by index number.
+ * @param {Number} i The index of the component, starting from 0.  However, if i is negative, return the component
+ * at size() - (-i).
+ * @return {Name.Component} The name component at the index. You must not
+ * change the returned Name.Component object.
+ */
+Name.prototype.get = function(i)
+{
+  if (i >= 0) {
+    if (i >= this.components.length)
+      throw new Error("Name.get: Index is out of bounds");
+
+    return this.components[i];
+  }
+  else {
+    // Negative index.
+    if (i < -this.components.length)
+      throw new Error("Name.get: Index is out of bounds");
+
+    return this.components[this.components.length - (-i)];
+  }
+};
+
+/**
+ * @deprecated Use size().
+ */
+Name.prototype.getComponentCount = function()
+{
+  return this.components.length;
+};
+
+/**
+ * @deprecated To get just the component value array, use get(i).getValue().buf().
+ */
+Name.prototype.getComponent = function(i)
+{
+  return new Buffer(this.components[i].getValue().buf());
+};
+
+/**
+ * The "file name" in a name is the last component that isn't blank and doesn't start with one of the
+ *   special marker octets (for version, etc.).  Return the index in this.components of
+ *   the file name, or -1 if not found.
+ */
+Name.prototype.indexOfFileName = function()
+{
+  for (var i = this.size() - 1; i >= 0; --i) {
+    var component = this.components[i].getValue().buf();
+    if (component.length <= 0)
+      continue;
+
+    if (component[0] == 0 || component[0] == 0xC0 || component[0] == 0xC1 ||
+        (component[0] >= 0xF5 && component[0] <= 0xFF))
+      continue;
+
+    return i;
+  }
+
+  return -1;
+};
+
+/**
+ * Encode this Name for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+Name.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeName(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this Name.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Name.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeName(this, input.buf(), false);
+  else
+    wireFormat.decodeName(this, input, true);
+};
+
+/**
+ * Compare this to the other Name using NDN canonical ordering.  If the first
+ * components of each name are not equal, this returns -1 if the first comes
+ * before the second using the NDN canonical ordering for name components, or 1
+ * if it comes after. If they are equal, this compares the second components of
+ * each name, etc.  If both names are the same up to the size of the shorter
+ * name, this returns -1 if the first name is shorter than the second or 1 if it
+ * is longer. For example, std::sort gives: /a/b/d /a/b/cc /c /c/a /bb .  This
+ * is intuitive because all names with the prefix /a are next to each other.
+ * But it may be also be counter-intuitive because /c comes before /bb according
+ * to NDN canonical ordering since it is shorter.
+ * The first form of compare is simply compare(other). The second form is
+ * compare(iStartComponent, nComponents, other [, iOtherStartComponent] [, nOtherComponents])
+ * which is equivalent to
+ * self.getSubName(iStartComponent, nComponents).compare
+ * (other.getSubName(iOtherStartComponent, nOtherComponents)) .
+ * @param {number} iStartComponent The index if the first component of this name
+ * to get. If iStartComponent is -N then compare components starting from
+ * name.size() - N.
+ * @param {number} nComponents The number of components starting at
+ * iStartComponent. If greater than the size of this name, compare until the end
+ * of the name.
+ * @param {Name} other The other Name to compare with.
+ * @param {number} iOtherStartComponent (optional) The index if the first
+ * component of the other name to compare. If iOtherStartComponent is -N then
+ * compare components starting from other.size() - N. If omitted, compare
+ * starting from index 0.
+ * @param {number} nOtherComponents (optional) The number of components
+ * starting at iOtherStartComponent. If omitted or greater than the size of this
+ * name, compare until the end of the name.
+ * @return {number} 0 If they compare equal, -1 if self comes before other in
+ * the canonical ordering, or 1 if self comes after other in the canonical
+ * ordering.
+ * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
+ */
+Name.prototype.compare = function
+  (iStartComponent, nComponents, other, iOtherStartComponent, nOtherComponents)
+{
+  if (iStartComponent instanceof Name) {
+    // compare(other)
+    other = iStartComponent;
+    iStartComponent = 0;
+    nComponents = this.size();
+  }
+
+  if (iOtherStartComponent == undefined)
+    iOtherStartComponent = 0;
+  if (nOtherComponents == undefined)
+    nOtherComponents = other.size();
+
+  if (iStartComponent < 0)
+    iStartComponent = this.size() - (-iStartComponent);
+  if (iOtherStartComponent < 0)
+    iOtherStartComponent = other.size() - (-iOtherStartComponent);
+
+  nComponents = Math.min(nComponents, this.size() - iStartComponent);
+  nOtherComponents = Math.min(nOtherComponents, other.size() - iOtherStartComponent);
+
+  var count = Math.min(nComponents, nOtherComponents);
+  for (var i = 0; i < count; ++i) {
+    var comparison = this.components[iStartComponent + i].compare
+      (other.components[iOtherStartComponent + i]);
+    if (comparison == 0)
+      // The components at this index are equal, so check the next components.
+      continue;
+
+    // Otherwise, the result is based on the components at this index.
+    return comparison;
+  }
+
+  // The components up to min(this.size(), other.size()) are equal, so the
+  // shorter name is less.
+  if (nComponents < nOtherComponents)
+    return -1;
+  else if (nComponents > nOtherComponents)
+    return 1;
+  else
+    return 0;
+};
+
+/**
+ * Return true if this Name has the same components as name.
+ */
+Name.prototype.equals = function(name)
+{
+  if (this.components.length != name.components.length)
+    return false;
+
+  // Start from the last component because they are more likely to differ.
+  for (var i = this.components.length - 1; i >= 0; --i) {
+    if (!this.components[i].equals(name.components[i]))
+      return false;
+  }
+
+  return true;
+};
+
+/**
+ * @deprecated Use equals.
+ */
+Name.prototype.equalsName = function(name)
+{
+  return this.equals(name);
+};
+
+/**
+ * Find the last component in name that has a ContentDigest and return the digest value as Buffer,
+ *   or null if not found.  See Name.getComponentContentDigestValue.
+ */
+Name.prototype.getContentDigestValue = function()
+{
+  for (var i = this.size() - 1; i >= 0; --i) {
+    var digestValue = Name.getComponentContentDigestValue(this.components[i]);
+    if (digestValue != null)
+      return digestValue;
+  }
+
+  return null;
+};
+
+/**
+ * If component is a ContentDigest, return the digest value as a Buffer slice (don't modify!).
+ * If not a ContentDigest, return null.
+ * A ContentDigest component is Name.ContentDigestPrefix + 32 bytes + Name.ContentDigestSuffix.
+ */
+Name.getComponentContentDigestValue = function(component)
+{
+  if (typeof component == 'object' && component instanceof Name.Component)
+    component = component.getValue().buf();
+
+  var digestComponentLength = Name.ContentDigestPrefix.length + 32 + Name.ContentDigestSuffix.length;
+  // Check for the correct length and equal ContentDigestPrefix and ContentDigestSuffix.
+  if (component.length == digestComponentLength &&
+      DataUtils.arraysEqual(component.slice(0, Name.ContentDigestPrefix.length),
+                            Name.ContentDigestPrefix) &&
+      DataUtils.arraysEqual(component.slice
+         (component.length - Name.ContentDigestSuffix.length, component.length),
+                            Name.ContentDigestSuffix))
+   return component.slice(Name.ContentDigestPrefix.length, Name.ContentDigestPrefix.length + 32);
+ else
+   return null;
+};
+
+// Meta GUID "%C1.M.G%C1" + ContentDigest with a 32 byte BLOB.
+Name.ContentDigestPrefix = new Buffer([0xc1, 0x2e, 0x4d, 0x2e, 0x47, 0xc1, 0x01, 0xaa, 0x02, 0x85]);
+Name.ContentDigestSuffix = new Buffer([0x00]);
+
+
+/**
+ * Return value as an escaped string according to NDN URI Scheme.
+ * We can't use encodeURIComponent because that doesn't encode all the 
+ * characters we want to.
+ * This does not add a type code prefix such as "sha256digest=".
+ * @param {Buffer|Name.Component} value The value or Name.Component to escape.
+ * @return {string} The escaped string.
+ */
+Name.toEscapedString = function(value)
+{
+  if (typeof value == 'object' && value instanceof Name.Component)
+    value = value.getValue().buf();
+  else if (typeof value === 'object' && value instanceof Blob)
+    value = value.buf();
+
+  var result = "";
+  var gotNonDot = false;
+  for (var i = 0; i < value.length; ++i) {
+    if (value[i] != 0x2e) {
+      gotNonDot = true;
+      break;
+    }
+  }
+  if (!gotNonDot) {
+    // Special case for component of zero or more periods.  Add 3 periods.
+    result = "...";
+    for (var i = 0; i < value.length; ++i)
+      result += ".";
+  }
+  else {
+    for (var i = 0; i < value.length; ++i) {
+      var x = value[i];
+      // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
+      if (x >= 0x30 && x <= 0x39 || x >= 0x41 && x <= 0x5a ||
+          x >= 0x61 && x <= 0x7a || x == 0x2b || x == 0x2d ||
+          x == 0x2e || x == 0x5f)
+        result += String.fromCharCode(x);
+      else
+        result += "%" + (x < 16 ? "0" : "") + x.toString(16).toUpperCase();
+    }
+  }
+  return result;
+};
+
+/**
+ * Make a blob value by decoding the escapedString according to NDN URI Scheme.
+ * If escapedString is "", "." or ".." then return null, which means to skip the 
+ * component in the name.
+ * This does not check for a type code prefix such as "sha256digest=".
+ * @param {string} escapedString The escaped string to decode.
+ * @return {Blob} The unescaped Blob value. If the escapedString is not a valid
+ * escaped component, then the Blob isNull().
+ */
+Name.fromEscapedString = function(escapedString)
+{
+  var value = unescape(escapedString.trim());
+
+  if (value.match(/[^.]/) == null) {
+    // Special case for value of only periods.
+    if (value.length <= 2)
+      // Zero, one or two periods is illegal.  Ignore this componenent to be
+      //   consistent with the C implementation.
+      return new Blob();
+    else
+      // Remove 3 periods.
+      return new Blob
+        (DataUtils.toNumbersFromString(value.substr(3, value.length - 3)), false);
+  }
+  else
+    return new Blob(DataUtils.toNumbersFromString(value), false);
+};
+
+/**
+ * @deprecated Use fromEscapedString. This method returns a Buffer which is the former
+ * behavior of fromEscapedString, and should only be used while updating your code.
+ */
+Name.fromEscapedStringAsBuffer = function(escapedString)
+{
+  return Name.fromEscapedString(escapedString).buf();
+};
+
+/**
+ * Get the successor of this name which is defined as follows.
+ *
+ *     N represents the set of NDN Names, and X,Y ∈ N.
+ *     Operator < is defined by the NDN canonical order on N.
+ *     Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
+ *
+ * In plain words, the successor of a name is the same name, but with its last
+ * component advanced to a next possible value.
+ *
+ * Examples:
+ *
+ * - The successor of / is /%00
+ * - The successor of /%00%01/%01%02 is /%00%01/%01%03
+ * - The successor of /%00%01/%01%FF is /%00%01/%02%00
+ * - The successor of /%00%01/%FF%FF is /%00%01/%00%00%00
+ *
+ * @return {Name} A new name which is the successor of this.
+ */
+Name.prototype.getSuccessor = function()
+{
+  if (this.size() == 0) {
+    // Return "/%00".
+    var result = new Name();
+    result.append(new Blob(new Buffer([0]), false));
+    return result;
+  }
+  else
+    return this.getPrefix(-1).append(this.get(-1).getSuccessor());
+};
+
+/**
+ * Return true if the N components of this name are the same as the first N
+ * components of the given name.
+ * @param {Name} name The name to check.
+ * @return {Boolean} true if this matches the given name. This always returns
+ * true if this name is empty.
+ */
+Name.prototype.match = function(name)
+{
+  var i_name = this.components;
+  var o_name = name.components;
+
+  // This 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. Check from last to
+  // first since the last components are more likely to differ.
+  for (var i = i_name.length - 1; i >= 0; --i) {
+    if (!i_name[i].equals(o_name[i]))
+      return false;
+  }
+
+  return true;
+};
+
+/**
+ * Return true if the N components of this name are the same as the first N
+ * components of the given name.
+ * @param {Name} name The name to check.
+ * @return {Boolean} true if this matches the given name. This always returns
+ * true if this name is empty.
+ */
+Name.prototype.isPrefixOf = function(name) { return this.match(name); }
+
+/**
+ * Get the change count, which is incremented each time this object is changed.
+ * @return {number} The change count.
+ */
+Name.prototype.getChangeCount = function()
+{
+  return this.changeCount;
+};
+
+// Put these requires at the bottom to avoid circular references.
+var TlvEncoder = require('./encoding/tlv/tlv-encoder.js').TlvEncoder;
+var WireFormat = require('./encoding/wire-format.js').WireFormat;
+/**
+ * This class represents an NDN KeyLocator object.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var Name = require('./name.js').Name;
+
+/**
+ * KeyLocator
+ */
+var KeyLocatorType = {
+  KEYNAME: 1,
+  KEY_LOCATOR_DIGEST: 2
+};
+
+exports.KeyLocatorType = KeyLocatorType;
+
+/**
+ * @constructor
+ */
+var KeyLocator = function KeyLocator(input, type)
+{
+  if (typeof input === 'object' && input instanceof KeyLocator) {
+    // Copy from the input KeyLocator.
+    this.type_ = input.type_;
+    this.keyName_ = new ChangeCounter(new Name(input.getKeyName()));
+    this.keyData_ = input.keyData_;
+  }
+  else {
+    this.type_ = type;
+    this.keyName_ = new ChangeCounter(new Name());
+    this.keyData_ = new Blob();
+
+    if (type == KeyLocatorType.KEYNAME)
+      this.keyName_.set(typeof input === 'object' && input instanceof Name ?
+        new Name(input) : new Name());
+    else if (type == KeyLocatorType.KEY_LOCATOR_DIGEST)
+      this.keyData_ = new Blob(input);
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.KeyLocator = KeyLocator;
+
+/**
+ * Get the key locator type. If KeyLocatorType.KEYNAME, you may also
+ * getKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also
+ * getKeyData() to get the digest.
+ * @return {number} The key locator type as a KeyLocatorType enum value,
+ * or null if not specified.
+ */
+KeyLocator.prototype.getType = function() { return this.type_; };
+
+/**
+ * Get the key name.  This is meaningful if getType() is KeyLocatorType.KEYNAME.
+ * @return {Name} The key name. If not specified, the Name is empty.
+ */
+KeyLocator.prototype.getKeyName = function()
+{
+  return this.keyName_.get();
+};
+
+/**
+ * Get the key data. If getType() is KeyLocatorType.KEY_LOCATOR_DIGEST, this is
+ * the digest bytes.
+ * @return {Blob} The key data, or an isNull Blob if not specified.
+ */
+KeyLocator.prototype.getKeyData = function()
+{
+  return this.keyData_;
+};
+
+/**
+ * @deprecated Use getKeyData. This method returns a Buffer which is the former
+ * behavior of getKeyData, and should only be used while updating your code.
+ */
+KeyLocator.prototype.getKeyDataAsBuffer = function()
+{
+  return this.getKeyData().buf();
+};
+
+/**
+ * Set the key locator type.  If KeyLocatorType.KEYNAME, you must also
+ * setKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also
+ * setKeyData() to the digest.
+ * @param {number} type The key locator type as a KeyLocatorType enum value.  If
+ * null, the type is unspecified.
+ */
+KeyLocator.prototype.setType = function(type)
+{
+  this.type_ = type;
+  ++this.changeCount_;
+};
+
+/**
+ * Set key name to a copy of the given Name.  This is the name if getType()
+ * is KeyLocatorType.KEYNAME.
+ * @param {Name} name The key name which is copied.
+ */
+KeyLocator.prototype.setKeyName = function(name)
+{
+  this.keyName_.set(typeof name === 'object' && name instanceof Name ?
+    new Name(name) : new Name());
+  ++this.changeCount_;
+};
+
+/**
+ * Set the key data to the given value. This is the digest bytes if getType() is
+ * KeyLocatorType.KEY_LOCATOR_DIGEST.
+ * @param {Blob} keyData A Blob with the key data bytes.
+ */
+KeyLocator.prototype.setKeyData = function(keyData)
+{
+  this.keyData_ = typeof keyData === 'object' && keyData instanceof Blob ?
+    keyData : new Blob(keyData);
+  ++this.changeCount_;
+};
+
+/**
+ * Clear the keyData and set the type to not specified.
+ */
+KeyLocator.prototype.clear = function()
+{
+  this.type_ = null;
+  this.keyName_.set(new Name());
+  this.keyData_ = new Blob();
+  ++this.changeCount_;
+};
+
+/**
+ * Check if this key locator has the same values as the given key locator.
+ * @param {KeyLocator} other The other key locator to check.
+ * @return {boolean} true if the key locators are equal, otherwise false.
+ */
+KeyLocator.prototype.equals = function(other)
+{
+    if (this.type_ != other.type_)
+      return false;
+
+    if (this.type_ == KeyLocatorType.KEYNAME) {
+      if (!this.getKeyName().equals(other.getKeyName()))
+        return false;
+    }
+    else if (this.type_ == KeyLocatorType.KEY_LOCATOR_DIGEST) {
+      if (!this.getKeyData().equals(other.getKeyData()))
         return false;
     }
 
     return true;
 };
 
-NDN.supported = NDN.getSupported();
-
-NDN.ndndIdFetcher = new Name('/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY');
-
-NDN.prototype.createRoute = function(host, port) {
-	this.host=host;
-	this.port=port;
-};
-
-
-NDN.KeyStore = new Array();
-
-var KeyStoreEntry = function KeyStoreEntry(name, rsa, time) {
-	this.keyName = name;  // KeyName
-	this.rsaKey = rsa;    // RSA key
-	this.timeStamp = time;  // Time Stamp
-};
-
-NDN.addKeyEntry = function(/* KeyStoreEntry */ keyEntry) {
-	var result = NDN.getKeyByName(keyEntry.keyName);
-	if (result == null)
-		NDN.KeyStore.push(keyEntry);
-	else
-		result = keyEntry;
-};
-
-NDN.getKeyByName = function(/* KeyName */ name) {
-	var result = null;
-
-	for (var i = 0; i < NDN.KeyStore.length; i++) {
-		if (NDN.KeyStore[i].keyName.contentName.match(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();
-
-var PITEntry = function PITEntry(interest, closure) {
-	this.interest = interest;  // Interest
-	this.closure = closure;    // Closure
-	this.timerID = -1;  // Timer ID
-};
-
-/*
- * Return the entry from NDN.PITTable where the name conforms to the interest selectors, and
- * the interest name is the longest that matches name.
+/**
+ * If the signature is a type that has a KeyLocator (so that,
+ * getFromSignature will succeed), return true.
+ * Note: This is a static method of KeyLocator instead of a method of
+ * Signature so that the Signature base class does not need to be overloaded
+ * with all the different kinds of information that various signature
+ * algorithms may use.
+ * @param {Signature} signature An object of a subclass of Signature.
+ * @return {boolean} True if the signature is a type that has a KeyLocator,
+ * otherwise false.
  */
-NDN.getEntryForExpressedInterest = function(/*Name*/ name) {
-    var result = null;
-
-	for (var i = 0; i < NDN.PITTable.length; i++) {
-		if (NDN.PITTable[i].interest.matches_name(name)) {
-            if (result == null ||
-                NDN.PITTable[i].interest.name.components.length > result.interest.name.components.length)
-                result = NDN.PITTable[i];
-        }
-	}
-
-	return result;
-};
-
-// For publishing data
-NDN.CSTable = new Array();
-
-var CSEntry = function CSEntry(name, closure) {
-	this.name = name;        // String
-	this.closure = closure;  // Closure
-};
-
-function getEntryForRegisteredPrefix(name) {
-	for (var i = 0; i < NDN.CSTable.length; i++) {
-		if (NDN.CSTable[i].name.match(name) != null)
-			return NDN.CSTable[i];
-	}
-	return null;
+KeyLocator.canGetFromSignature = function(signature)
+{
+  return signature instanceof Sha256WithRsaSignature ||
+         signature instanceof Sha256WithEcdsaSignature ||
+         signature instanceof HmacWithSha256Signature;
 }
 
-/*
- * Return a function that selects a host at random from hostList and returns { host: host, port: port }.
- * If no more hosts remain, return null.
+/**
+ * If the signature is a type that has a KeyLocator, then return it. Otherwise
+ * throw an error.
+ * @param {Signature} signature An object of a subclass of Signature.
+ * @return {KeyLocator} The signature's KeyLocator. It is an error if signature
+ * doesn't have a KeyLocator.
  */
-NDN.makeShuffledGetHostAndPort = function(hostList, port) {
-    // Make a copy.
-    hostList = hostList.slice(0, hostList.length);
-    DataUtils.shuffle(hostList);
+KeyLocator.getFromSignature = function(signature)
+{
+  if (signature instanceof Sha256WithRsaSignature ||
+      signature instanceof Sha256WithEcdsaSignature ||
+      signature instanceof HmacWithSha256Signature)
+    return signature.getKeyLocator();
+  else
+    throw new Error
+      ("KeyLocator.getFromSignature: Signature type does not have a KeyLocator");
+}
 
-    return function() {
-        if (hostList.length == 0)
-            return null;
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+KeyLocator.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.keyName_.checkChanged();
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
 
-        return { host: hostList.splice(0, 1)[0], port: port };
-    };
+  return this.changeCount_;
 };
 
-/** Encode name as an Interest. If template is not null, use its attributes.
- *  Send the interest to host:port, read the entire response and call
- *  closure.upcall(Closure.UPCALL_CONTENT (or Closure.UPCALL_CONTENT_UNVERIFIED),
- *                 new UpcallInfo(this, interest, 0, contentObject)).
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(KeyLocator.prototype, "type",
+  { get: function() { return this.getType(); },
+    set: function(val) { this.setType(val); } });
+/**
+ * @@deprecated Use getKeyData and setKeyData.
  */
-NDN.prototype.expressInterest = function(
-        // Name
-        name,
-        // Closure
-        closure,
-        // Interest
-        template) {
-	var interest = new Interest(name);
-    if (template != null) {
-		interest.minSuffixComponents = template.minSuffixComponents;
-		interest.maxSuffixComponents = template.maxSuffixComponents;
-		interest.publisherPublicKeyDigest = template.publisherPublicKeyDigest;
-		interest.exclude = template.exclude;
-		interest.childSelector = template.childSelector;
-		interest.answerOriginKind = template.answerOriginKind;
-		interest.scope = template.scope;
-		interest.interestLifetime = template.interestLifetime;
+Object.defineProperty(KeyLocator.prototype, "keyData",
+  { get: function() { return this.getKeyDataAsBuffer(); },
+    set: function(val) { this.setKeyData(val); } });
+
+// Put this last to avoid a require loop.
+var Sha256WithRsaSignature = require('./sha256-with-rsa-signature.js').Sha256WithRsaSignature;
+var Sha256WithEcdsaSignature = require('./sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature;
+var HmacWithSha256Signature = require('./hmac-with-sha256-signature.js').HmacWithSha256Signature;
+/**
+ * This class represents an NDN Data MetaInfo object.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('./name.js').Name;
+
+/**
+ * A ContentType specifies the content type in a MetaInfo object. If the
+ * content type in the packet is not a recognized enum value, then we use
+ * ContentType.OTHER_CODE and you can call MetaInfo.getOtherTypeCode(). We do
+ * this to keep the recognized content type values independent of packet
+ * encoding formats.
+ */
+var ContentType = {
+  BLOB:0,
+  LINK:1,
+  KEY: 2,
+  NACK:3,
+  OTHER_CODE: 0x7fff
+};
+
+exports.ContentType = ContentType;
+
+/**
+ * Create a new MetaInfo with the optional values.
+ * @constructor
+ */
+var MetaInfo = function MetaInfo(publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockId)
+{
+  if (timestamp)
+    throw new Error
+      ("MetaInfo constructor: timestamp support has been removed.");
+  if (locator)
+    throw new Error
+      ("MetaInfo constructor: locator support has been removed.");
+
+  if (typeof publisherOrMetaInfo === 'object' &&
+      publisherOrMetaInfo instanceof MetaInfo) {
+    // Copy values.
+    var metaInfo = publisherOrMetaInfo;
+    this.publisher_ = metaInfo.publisher_;
+    this.type_ = metaInfo.type_;
+    this.otherTypeCode_ = metaInfo.otherTypeCode_;
+    this.freshnessPeriod_ = metaInfo.freshnessPeriod_;
+    this.finalBlockId_ = metaInfo.finalBlockId_;
+  }
+  else {
+    if (publisherOrMetaInfo)
+      throw new Error
+        ("MetaInfo constructor: publisher support has been removed.");
+
+    this.type = type == null || type < 0 ? ContentType.BLOB : type;
+    this.otherTypeCode_ = -1;
+    this.freshnessSeconds = freshnessSeconds; // deprecated
+    this.finalBlockID = finalBlockId; // byte array // deprecated
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.MetaInfo = MetaInfo;
+
+/**
+ * Get the content type.
+ * @return {number} The content type as an int from ContentType. If this is
+ * ContentType.OTHER_CODE, then call getOtherTypeCode() to get the unrecognized
+ * content type code.
+ */
+MetaInfo.prototype.getType = function()
+{
+  return this.type_;
+};
+
+/**
+ * Get the content type code from the packet which is other than a recognized
+ * ContentType enum value. This is only meaningful if getType() is
+ * ContentType.OTHER_CODE.
+ * @return {number} The type code.
+ */
+MetaInfo.prototype.getOtherTypeCode = function()
+{
+  return this.otherTypeCode_;
+};
+
+/**
+ * Get the freshness period.
+ * @return {number} The freshness period in milliseconds, or null if not
+ * specified.
+ */
+MetaInfo.prototype.getFreshnessPeriod = function()
+{
+  return this.freshnessPeriod_;
+};
+
+/**
+ * Get the final block ID.
+ * @return {Name.Component} The final block ID as a Name.Component. If the
+ * Name.Component getValue().size() is 0, then the final block ID is not specified.
+ */
+MetaInfo.prototype.getFinalBlockId = function()
+{
+  return this.finalBlockId_;
+};
+
+/**
+ * @deprecated Use getFinalBlockId.
+ */
+MetaInfo.prototype.getFinalBlockID = function()
+{
+  return this.getFinalBlockId();
+};
+
+/**
+ * @deprecated Use getFinalBlockId. This method returns a Buffer which is the former
+ * behavior of getFinalBlockId, and should only be used while updating your code.
+ */
+MetaInfo.prototype.getFinalBlockIDAsBuffer = function()
+{
+  return this.finalBlockId_.getValue().buf();
+};
+
+/**
+ * Set the content type.
+ * @param {number} type The content type as an int from ContentType. If null,
+ * this uses ContentType.BLOB. If the packet's content type is not a recognized
+ * ContentType enum value, use ContentType.OTHER_CODE and call setOtherTypeCode().
+ */
+MetaInfo.prototype.setType = function(type)
+{
+  this.type_ = type == null || type < 0 ? ContentType.BLOB : type;
+  ++this.changeCount_;
+};
+
+/**
+ * Set the packet’s content type code to use when the content type enum is
+ * ContentType.OTHER_CODE. If the packet’s content type code is a recognized
+ * enum value, just call setType().
+ * @param {number} otherTypeCode The packet’s unrecognized content type code,
+ * which must be non-negative.
+ */
+MetaInfo.prototype.setOtherTypeCode = function(otherTypeCode)
+{
+  if (otherTypeCode < 0)
+    throw new Error("MetaInfo other type code must be non-negative");
+
+  this.otherTypeCode_ = otherTypeCode;
+  ++this.changeCount_;
+};
+
+/**
+ * Set the freshness period.
+ * @param {number} freshnessPeriod The freshness period in milliseconds, or null
+ * for not specified.
+ */
+MetaInfo.prototype.setFreshnessPeriod = function(freshnessPeriod)
+{
+  if (freshnessPeriod == null || freshnessPeriod < 0)
+    this.freshnessPeriod_ = null;
+  else
+    this.freshnessPeriod_ = freshnessPeriod;
+  ++this.changeCount_;
+};
+
+/**
+ * Set the final block ID.
+ * @param {Name.Component} finalBlockId The final block ID as a Name.Component.
+ * If not specified, set to a new default Name.Component(), or to a
+ * Name.Component where getValue().size() is 0.
+ */
+MetaInfo.prototype.setFinalBlockId = function(finalBlockId)
+{
+  this.finalBlockId_ = typeof finalBlockId === 'object' &&
+                       finalBlockId instanceof Name.Component ?
+    finalBlockId : new Name.Component(finalBlockId);
+  ++this.changeCount_;
+};
+
+/**
+ * @deprecated Use setFinalBlockId.
+ */
+MetaInfo.prototype.setFinalBlockID = function(finalBlockId)
+{
+  this.setFinalBlockId(finalBlockId);
+};
+
+/**
+ * Get the change count, which is incremented each time this object is changed.
+ * @return {number} The change count.
+ */
+MetaInfo.prototype.getChangeCount = function()
+{
+  return this.changeCount_;
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(MetaInfo.prototype, "type",
+  { get: function() { return this.getType(); },
+    set: function(val) { this.setType(val); } });
+/**
+ * @deprecated Use getFreshnessPeriod and setFreshnessPeriod.
+ */
+Object.defineProperty(MetaInfo.prototype, "freshnessSeconds",
+  { get: function() {
+      if (this.freshnessPeriod_ == null || this.freshnessPeriod_ < 0)
+        return null;
+      else
+        // Convert from milliseconds.
+        return this.freshnessPeriod_ / 1000.0;
+    },
+    set: function(val) {
+      if (val == null || val < 0)
+        this.freshnessPeriod_ = null;
+      else
+        // Convert to milliseconds.
+        this.freshnessPeriod_ = val * 1000.0;
+      ++this.changeCount_;
+    } });
+/**
+ * @deprecated Use getFinalBlockId and setFinalBlockId.
+ */
+Object.defineProperty(MetaInfo.prototype, "finalBlockID",
+  { get: function() { return this.getFinalBlockIDAsBuffer(); },
+    set: function(val) { this.setFinalBlockId(val); } });
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var KeyLocator = require('./key-locator.js').KeyLocator;
+
+/**
+ * Create a new Sha256WithEcdsaSignature object, possibly copying values from
+ * another object.
+ *
+ * @param {Sha256WithEcdsaSignature} value (optional) If value is a
+ * Sha256WithEcdsaSignature, copy its values.  If value is omitted, the 
+ * keyLocator is the default with unspecified values and the signature is
+ * unspecified.
+ * @constructor
+ */
+var Sha256WithEcdsaSignature = function Sha256WithEcdsaSignature(value)
+{
+  if (typeof value === 'object' && value instanceof Sha256WithEcdsaSignature) {
+    // Copy the values.
+    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
+    this.signature_ = value.signature_;
+  }
+  else {
+    this.keyLocator_ = new ChangeCounter(new KeyLocator());
+    this.signature_ = new Blob();
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.Sha256WithEcdsaSignature = Sha256WithEcdsaSignature;
+
+/**
+ * Create a new Sha256WithEcdsaSignature which is a copy of this object.
+ * @return {Sha256WithEcdsaSignature} A new object which is a copy of this
+ * object.
+ */
+Sha256WithEcdsaSignature.prototype.clone = function()
+{
+  return new Sha256WithEcdsaSignature(this);
+};
+
+/**
+ * Get the key locator.
+ * @return {KeyLocator} The key locator.
+ */
+Sha256WithEcdsaSignature.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_.get();
+};
+
+/**
+ * Get the data packet's signature bytes.
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+Sha256WithEcdsaSignature.prototype.getSignature = function()
+{
+  return this.signature_;
+};
+
+/**
+ * Set the key locator to a copy of the given keyLocator.
+ * @param {KeyLocator} keyLocator The KeyLocator to copy.
+ */
+Sha256WithEcdsaSignature.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_.set(typeof keyLocator === 'object' &&
+                       keyLocator instanceof KeyLocator ?
+    new KeyLocator(keyLocator) : new KeyLocator());
+  ++this.changeCount_;
+};
+
+/**
+ * Set the data packet's signature bytes.
+ * @param {Blob} signature
+ */
+Sha256WithEcdsaSignature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+Sha256WithEcdsaSignature.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.keyLocator_.checkChanged();
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var KeyLocator = require('./key-locator.js').KeyLocator;
+
+/**
+ * Create a new Sha256WithRsaSignature object, possibly copying values from
+ * another object.
+ *
+ * @param {Sha256WithRsaSignature} value (optional) If value is a
+ * Sha256WithRsaSignature, copy its values.  If value is omitted, the keyLocator
+ * is the default with unspecified values and the signature is unspecified.
+ * @constructor
+ */
+var Sha256WithRsaSignature = function Sha256WithRsaSignature(value)
+{
+  if (typeof value === 'object' && value instanceof Sha256WithRsaSignature) {
+    // Copy the values.
+    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
+    this.signature_ = value.signature_;
+  }
+  else {
+    this.keyLocator_ = new ChangeCounter(new KeyLocator());
+    this.signature_ = new Blob();
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.Sha256WithRsaSignature = Sha256WithRsaSignature;
+
+/**
+ * Create a new Sha256WithRsaSignature which is a copy of this object.
+ * @return {Sha256WithRsaSignature} A new object which is a copy of this object.
+ */
+Sha256WithRsaSignature.prototype.clone = function()
+{
+  return new Sha256WithRsaSignature(this);
+};
+
+/**
+ * Get the key locator.
+ * @return {KeyLocator} The key locator.
+ */
+Sha256WithRsaSignature.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_.get();
+};
+
+/**
+ * Get the data packet's signature bytes.
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+Sha256WithRsaSignature.prototype.getSignature = function()
+{
+  return this.signature_;
+};
+
+/**
+ * @deprecated Use getSignature. This method returns a Buffer which is the former
+ * behavior of getSignature, and should only be used while updating your code.
+ */
+Sha256WithRsaSignature.prototype.getSignatureAsBuffer = function()
+{
+  return this.signature_.buf();
+};
+
+/**
+ * Set the key locator to a copy of the given keyLocator.
+ * @param {KeyLocator} keyLocator The KeyLocator to copy.
+ */
+Sha256WithRsaSignature.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_.set(typeof keyLocator === 'object' &&
+                       keyLocator instanceof KeyLocator ?
+    new KeyLocator(keyLocator) : new KeyLocator());
+  ++this.changeCount_;
+};
+
+/**
+ * Set the data packet's signature bytes.
+ * @param {Blob} signature
+ */
+Sha256WithRsaSignature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+Sha256WithRsaSignature.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.keyLocator_.checkChanged();
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(Sha256WithRsaSignature.prototype, "keyLocator",
+  { get: function() { return this.getKeyLocator(); },
+    set: function(val) { this.setKeyLocator(val); } });
+/**
+ * @@deprecated Use getSignature and setSignature.
+ */
+Object.defineProperty(Sha256WithRsaSignature.prototype, "signature",
+  { get: function() { return this.getSignatureAsBuffer(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * A GenericSignature extends Signature and holds the encoding bytes of the
+ * SignatureInfo so that the application can process experimental signature
+ * types. When decoding a packet, if the type of SignatureInfo is not
+ * recognized, the library creates a GenericSignature.
+ * Create a new GenericSignature object, possibly copying values from another
+ * object.
+ *
+ * @param {GenericSignature} value (optional) If value is a GenericSignature,
+ * copy its values.
+ * @constructor
+ */
+var GenericSignature = function GenericSignature(value)
+{
+  if (typeof value === 'object' && value instanceof GenericSignature) {
+    // Copy the values.
+    this.signature_ = value.signature_;
+    this.signatureInfoEncoding_ = value.signatureInfoEncoding_;
+    this.typeCode_ = value.typeCode_;
+  }
+  else {
+    this.signature_ = new Blob();
+    this.signatureInfoEncoding_ = new Blob();
+    this.typeCode_ = null;
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.GenericSignature = GenericSignature;
+
+/**
+ * Create a new GenericSignature which is a copy of this object.
+ * @return {GenericSignature} A new object which is a copy of this object.
+ */
+GenericSignature.prototype.clone = function()
+{
+  return new GenericSignature(this);
+};
+
+/**
+ * Get the data packet's signature bytes.
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+GenericSignature.prototype.getSignature = function()
+{ 
+  return this.signature_;
+};
+
+/**
+ * @deprecated Use getSignature. This method returns a Buffer which is the former
+ * behavior of getSignature, and should only be used while updating your code.
+ */
+GenericSignature.prototype.getSignatureAsBuffer = function()
+{
+  return this.signature_.buf();
+};
+
+/**
+ * Get the bytes of the entire signature info encoding (including the type
+ * code).
+ * @return {Blob} The encoding bytes. If not specified, the value isNull().
+ */
+GenericSignature.prototype.getSignatureInfoEncoding = function()
+{
+  return this.signatureInfoEncoding_;
+};
+
+/**
+ * Get the type code of the signature type. When wire decode calls
+ * setSignatureInfoEncoding, it sets the type code. Note that the type code
+ * is ignored during wire encode, which simply uses getSignatureInfoEncoding()
+ * where the encoding already has the type code.
+ * @return {number} The type code, or null if not known.
+ */
+GenericSignature.prototype.getTypeCode = function() { return this.typeCode_; };
+
+/**
+ * Set the data packet's signature bytes.
+ * @param {Blob} signature
+ */
+GenericSignature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Set the bytes of the entire signature info encoding (including the type
+ * code).
+ * @param {Blob} signatureInfoEncoding A Blob with the encoding bytes.
+ * @param {number} (optional) The type code of the signature type, or null if
+ * not known. (When a GenericSignature is created by wire decoding, it sets
+ * the typeCode.)
+ */
+GenericSignature.prototype.setSignatureInfoEncoding = function
+  (signatureInfoEncoding, typeCode)
+{
+  this.signatureInfoEncoding_ =
+    typeof signatureInfoEncoding === 'object' && signatureInfoEncoding instanceof Blob ?
+      signatureInfoEncoding : new Blob(signatureInfoEncoding);
+  this.typeCode_ = typeCode;
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+GenericSignature.prototype.getChangeCount = function()
+{
+  return this.changeCount_;
+};
+
+/**
+ * @@deprecated Use getSignature and setSignature.
+ */
+Object.defineProperty(GenericSignature.prototype, "signature",
+  { get: function() { return this.getSignatureAsBuffer(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var KeyLocator = require('./key-locator.js').KeyLocator;
+
+/**
+ * An HmacWithSha256Signature holds the signature bits and other info
+ * representing an HmacWithSha256 signature in a packet.
+ * Create a new HmacWithSha256Signature object, possibly copying values from
+ * another object.
+ *
+ * @param {HmacWithSha256Signature} value (optional) If value is a
+ * HmacWithSha256Signature, copy its values.  If value is omitted, the keyLocator
+ * is the default with unspecified values and the signature is unspecified.
+ * @constructor
+ */
+var HmacWithSha256Signature = function HmacWithSha256Signature(value)
+{
+  if (typeof value === 'object' && value instanceof HmacWithSha256Signature) {
+    // Copy the values.
+    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
+    this.signature_ = value.signature_;
+  }
+  else {
+    this.keyLocator_ = new ChangeCounter(new KeyLocator());
+    this.signature_ = new Blob();
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.HmacWithSha256Signature = HmacWithSha256Signature;
+
+/**
+ * Create a new HmacWithSha256Signature which is a copy of this object.
+ * @return {HmacWithSha256Signature} A new object which is a copy of this object.
+ */
+HmacWithSha256Signature.prototype.clone = function()
+{
+  return new HmacWithSha256Signature(this);
+};
+
+/**
+ * Get the key locator.
+ * @return {KeyLocator} The key locator.
+ */
+HmacWithSha256Signature.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_.get();
+};
+
+/**
+ * Get the data packet's signature bytes.
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+HmacWithSha256Signature.prototype.getSignature = function()
+{
+  return this.signature_;
+};
+
+/**
+ * @deprecated Use getSignature. This method returns a Buffer which is the former
+ * behavior of getSignature, and should only be used while updating your code.
+ */
+HmacWithSha256Signature.prototype.getSignatureAsBuffer = function()
+{
+  return this.signature_.buf();
+};
+
+/**
+ * Set the key locator to a copy of the given keyLocator.
+ * @param {KeyLocator} keyLocator The KeyLocator to copy.
+ */
+HmacWithSha256Signature.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_.set(typeof keyLocator === 'object' &&
+                       keyLocator instanceof KeyLocator ?
+    new KeyLocator(keyLocator) : new KeyLocator());
+  ++this.changeCount_;
+};
+
+/**
+ * Set the data packet's signature bytes.
+ * @param {Blob} signature
+ */
+HmacWithSha256Signature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+HmacWithSha256Signature.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.keyLocator_.checkChanged();
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(HmacWithSha256Signature.prototype, "keyLocator",
+  { get: function() { return this.getKeyLocator(); },
+    set: function(val) { this.setKeyLocator(val); } });
+/**
+ * @@deprecated Use getSignature and setSignature.
+ */
+Object.defineProperty(HmacWithSha256Signature.prototype, "signature",
+  { get: function() { return this.getSignatureAsBuffer(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * A DigestSha256Signature extends Signature and holds the signature bits (which
+ * are only the SHA256 digest) and an empty SignatureInfo for a data packet or
+ * signed interest.
+ *
+ * Create a new DigestSha256Signature object, possibly copying values from
+ * another object.
+ *
+ * @param {DigestSha256Signature} value (optional) If value is a
+ * DigestSha256Signature, copy its values.  If value is omitted, the signature
+ * is unspecified.
+ * @constructor
+ */
+var DigestSha256Signature = function DigestSha256Signature(value)
+{
+  if (typeof value === 'object' && value instanceof DigestSha256Signature)
+    // Copy the values.
+    this.signature_ = value.signature_;
+  else
+    this.signature_ = new Blob();
+
+  this.changeCount_ = 0;
+};
+
+exports.DigestSha256Signature = DigestSha256Signature;
+
+/**
+ * Create a new DigestSha256Signature which is a copy of this object.
+ * @return {DigestSha256Signature} A new object which is a copy of this object.
+ */
+DigestSha256Signature.prototype.clone = function()
+{
+  return new DigestSha256Signature(this);
+};
+
+/**
+ * Get the signature bytes (which are only the digest).
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+DigestSha256Signature.prototype.getSignature = function()
+{
+  return this.signature_;
+};
+
+/**
+ * Set the signature bytes to the given value.
+ * @param {Blob} signature
+ */
+DigestSha256Signature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object is changed.
+ * @return {number} The change count.
+ */
+DigestSha256Signature.prototype.getChangeCount = function()
+{
+  return this.changeCount_;
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+/**
+ * @@deprecated Use getSignature and setSignature.
+ */
+Object.defineProperty(DigestSha256Signature.prototype, "signature",
+  { get: function() { return this.getSignature(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * This class represents an NDN Data object.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var SignedBlob = require('./util/signed-blob.js').SignedBlob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var Sha256WithRsaSignature = require('./sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var MetaInfo = require('./meta-info.js').MetaInfo; /** @ignore */
+var IncomingFaceId = require('./lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var Crypto = require('./crypto.js');
+
+/**
+ * Create a new Data with the optional values.  There are 2 forms of constructor:
+ * new Data([name] [, content]);
+ * new Data(name, metaInfo [, content]);
+ *
+ * @constructor
+ * @param {Name} name
+ * @param {MetaInfo} metaInfo
+ * @param {Buffer} content
+ */
+var Data = function Data(nameOrData, metaInfoOrContent, arg3)
+{
+  if (nameOrData instanceof Data) {
+    // The copy constructor.
+    var data = nameOrData;
+
+    // Copy the Data object.
+    this.name_ = new ChangeCounter(new Name(data.getName()));
+    this.metaInfo_ = new ChangeCounter(new MetaInfo(data.getMetaInfo()));
+    this.signature_ = new ChangeCounter(data.getSignature().clone());
+    this.content_ = data.content_;
+    this.defaultWireEncoding_ = data.getDefaultWireEncoding();
+    this.defaultFullName_ = data.defaultFullName_;
+    this.defaultWireEncodingFormat_ = data.defaultWireEncodingFormat_;
+  }
+  else {
+    var name = nameOrData;
+    if (typeof name === 'string')
+      this.name_ = new ChangeCounter(new Name(name));
+    else
+      this.name_ = new ChangeCounter(typeof name === 'object' && name instanceof Name ?
+         new Name(name) : new Name());
+
+    var metaInfo;
+    var content;
+    if (typeof metaInfoOrContent === 'object' &&
+        metaInfoOrContent instanceof MetaInfo) {
+      metaInfo = metaInfoOrContent;
+      content = arg3;
+    }
+    else {
+      metaInfo = null;
+      content = metaInfoOrContent;
+    }
+
+    this.metaInfo_ = new ChangeCounter(typeof metaInfo === 'object' && metaInfo instanceof MetaInfo ?
+      new MetaInfo(metaInfo) : new MetaInfo());
+
+    this.content_ = typeof content === 'object' && content instanceof Blob ?
+      content : new Blob(content, true);
+
+    this.signature_ = new ChangeCounter(new Sha256WithRsaSignature());
+    this.defaultWireEncoding_ = new SignedBlob();
+    this.defaultFullName_ = new Name();
+    this.defaultWireEncodingFormat_ = null;
+  }
+
+  this.getDefaultWireEncodingChangeCount_ = 0;
+  this.changeCount_ = 0;
+  this.lpPacket_ = null;
+};
+
+exports.Data = Data;
+
+/**
+ * Get the data packet's name.
+ * @return {Name} The name. If not specified, the name size() is 0.
+ */
+Data.prototype.getName = function()
+{
+  return this.name_.get();
+};
+
+/**
+ * Get the data packet's meta info.
+ * @return {MetaInfo} The meta info.
+ */
+Data.prototype.getMetaInfo = function()
+{
+  return this.metaInfo_.get();
+};
+
+/**
+ * Get the data packet's signature object.
+ * @return {Signature} The signature object.
+ */
+Data.prototype.getSignature = function()
+{
+  return this.signature_.get();
+};
+
+/**
+ * Get the data packet's content.
+ * @return {Blob} The content as a Blob, which isNull() if unspecified.
+ */
+Data.prototype.getContent = function()
+{
+  return this.content_;
+};
+
+/**
+ * @deprecated Use getContent. This method returns a Buffer which is the former
+ * behavior of getContent, and should only be used while updating your code.
+ */
+Data.prototype.getContentAsBuffer = function()
+{
+  return this.content_.buf();
+};
+
+/**
+ * Return the default wire encoding, which was encoded with
+ * getDefaultWireEncodingFormat().
+ * @return {SignedBlob} The default wire encoding, whose isNull() may be true
+ * if there is no default wire encoding.
+ */
+Data.prototype.getDefaultWireEncoding = function()
+{
+  if (this.getDefaultWireEncodingChangeCount_ != this.getChangeCount()) {
+    // The values have changed, so the default wire encoding is invalidated.
+    this.defaultWireEncoding_ = new SignedBlob();
+    this.defaultWireEncodingFormat_ = null;
+    this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
+  }
+
+  return this.defaultWireEncoding_;
+};
+
+/**
+ * Get the WireFormat which is used by getDefaultWireEncoding().
+ * @return {WireFormat} The WireFormat, which is only meaningful if the
+ * getDefaultWireEncoding() is not isNull().
+ */
+Data.prototype.getDefaultWireEncodingFormat = function()
+{
+  return this.defaultWireEncodingFormat_;
+};
+
+/**
+ * Get the incoming face ID according to the incoming packet header.
+ * @return {number} The incoming face ID. If not specified, return null.
+ */
+Data.prototype.getIncomingFaceId = function()
+{
+  var field =
+    this.lpPacket_ === null ? null : IncomingFaceId.getFirstHeader(this.lpPacket_);
+  return field === null ? null : field.getFaceId();
+};
+
+/**
+ * Get the Data packet's full name, which includes the final
+ * ImplicitSha256Digest component based on the wire encoding for a particular
+ * wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Name} The full name. You must not change the Name object - if you
+ * need to change it then make a copy.
+ */
+Data.prototype.getFullName = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  // The default full name depends on the default wire encoding.
+  if (!this.getDefaultWireEncoding().isNull() &&
+      this.defaultFullName_.size() > 0 &&
+      this.getDefaultWireEncodingFormat() == wireFormat)
+    // We already have a full name. A non-null default wire encoding means
+    // that the Data packet fields have not changed.
+    return this.defaultFullName_;
+
+  var fullName = new Name(this.getName());
+  var hash = Crypto.createHash('sha256');
+  // wireEncode will use the cached encoding if possible.
+  hash.update(this.wireEncode(wireFormat).buf());
+  fullName.appendImplicitSha256Digest(new Blob(hash.digest(), false));
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // wireEncode has already set defaultWireEncodingFormat_.
+    this.defaultFullName_ = fullName;
+
+  return fullName;
+};
+
+/**
+ * Set name to a copy of the given Name.
+ * @param {Name} name The Name which is copied.
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+Data.prototype.setName = function(name)
+{
+  this.name_.set(typeof name === 'object' && name instanceof Name ?
+    new Name(name) : new Name());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set metaInfo to a copy of the given MetaInfo.
+ * @param {MetaInfo} metaInfo The MetaInfo which is copied.
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+Data.prototype.setMetaInfo = function(metaInfo)
+{
+  this.metaInfo_.set(typeof metaInfo === 'object' && metaInfo instanceof MetaInfo ?
+    new MetaInfo(metaInfo) : new MetaInfo());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the signature to a copy of the given signature.
+ * @param {Signature} signature The signature object which is cloned.
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+Data.prototype.setSignature = function(signature)
+{
+  this.signature_.set(signature == null ?
+    new Sha256WithRsaSignature() : signature.clone());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the content to the given value.
+ * @param {Blob|Buffer} content The content bytes. If content is not a Blob,
+ * then create a new Blob to copy the bytes (otherwise take another pointer to
+ * the same Blob).
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+Data.prototype.setContent = function(content)
+{
+  this.content_ = typeof content === 'object' && content instanceof Blob ?
+    content : new Blob(content, true);
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Encode this Data for a particular wire format. If wireFormat is the default
+ * wire format, also set the defaultWireEncoding field to the encoded result.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {SignedBlob} The encoded buffer in a SignedBlob object.
+ */
+Data.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (!this.getDefaultWireEncoding().isNull() &&
+      this.getDefaultWireEncodingFormat() == wireFormat)
+    // We already have an encoding in the desired format.
+    return this.getDefaultWireEncoding();
+
+  var result = wireFormat.encodeData(this);
+  var wireEncoding = new SignedBlob
+    (result.encoding, result.signedPortionBeginOffset,
+     result.signedPortionEndOffset);
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // This is the default wire encoding.
+    this.setDefaultWireEncoding
+      (wireEncoding, WireFormat.getDefaultWireFormat());
+  return wireEncoding;
+};
+
+/**
+ * Decode the input using a particular wire format and update this Data. If
+ * wireFormat is the default wire format, also set the defaultWireEncoding to
+ * another pointer to the input.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Data.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var result;
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    result = wireFormat.decodeData(this, input.buf(), false);
+  else
+    result = wireFormat.decodeData(this, input, true);
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // This is the default wire encoding.  In the Blob constructor, set copy
+    // true, but if input is already a Blob, it won't copy.
+    this.setDefaultWireEncoding(new SignedBlob
+      (new Blob(input, true), result.signedPortionBeginOffset,
+       result.signedPortionEndOffset),
+      WireFormat.getDefaultWireFormat());
+  else
+    this.setDefaultWireEncoding(new SignedBlob(), null);
+};
+
+/**
+ * An internal library method to set the LpPacket for an incoming packet. The
+ * application should not call this.
+ * @param {LpPacket} lpPacket The LpPacket. This does not make a copy.
+ * @return {Data} This Data so that you can chain calls to update values.
+ * @note This is an experimental feature. This API may change in the future.
+ */
+Data.prototype.setLpPacket = function(lpPacket)
+{
+  this.lpPacket_ = lpPacket;
+  // Don't update changeCount_ since this doesn't affect the wire encoding.
+  return this;
+}
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+Data.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.name_.checkChanged();
+  changed = this.metaInfo_.checkChanged() || changed;
+  changed = this.signature_.checkChanged() || changed;
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+
+Data.prototype.setDefaultWireEncoding = function
+  (defaultWireEncoding, defaultWireEncodingFormat)
+{
+  this.defaultWireEncoding_ = defaultWireEncoding;
+  this.defaultWireEncodingFormat_ = defaultWireEncodingFormat;
+  // Set getDefaultWireEncodingChangeCount_ so that the next call to
+  // getDefaultWireEncoding() won't clear _defaultWireEncoding.
+  this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(Data.prototype, "name",
+  { get: function() { return this.getName(); },
+    set: function(val) { this.setName(val); } });
+Object.defineProperty(Data.prototype, "metaInfo",
+  { get: function() { return this.getMetaInfo(); },
+    set: function(val) { this.setMetaInfo(val); } });
+Object.defineProperty(Data.prototype, "signature",
+  { get: function() { return this.getSignature(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * @deprecated Use getContent and setContent.
+ */
+Object.defineProperty(Data.prototype, "content",
+  { get: function() { return this.getContentAsBuffer(); },
+    set: function(val) { this.setContent(val); } });
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a new SecurityException to report an exception from the security
+ * library, wrapping the given error object.
+ * Call with: throw new SecurityException(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+function SecurityException(error)
+{
+  if (error) {
+    error.__proto__ = SecurityException.prototype;
+    return error;
+  }
+}
+
+SecurityException.prototype = new Error();
+SecurityException.prototype.name = "SecurityException";
+
+exports.SecurityException = SecurityException;
+
+function UnrecognizedKeyFormatException(error)
+{
+  // Call the base constructor.
+  SecurityException.call(this, error);
+}
+UnrecognizedKeyFormatException.prototype = new SecurityException();
+UnrecognizedKeyFormatException.prototype.name = "UnrecognizedKeyFormatException";
+
+exports.UnrecognizedKeyFormatException = UnrecognizedKeyFormatException;
+
+function UnrecognizedDigestAlgorithmException(error)
+{
+  // Call the base constructor.
+  SecurityException.call(this, error);
+}
+UnrecognizedDigestAlgorithmException.prototype = new SecurityException();
+UnrecognizedDigestAlgorithmException.prototype.name = "UnrecognizedDigestAlgorithmException";
+
+exports.UnrecognizedDigestAlgorithmException = UnrecognizedDigestAlgorithmException;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * This module defines constants used by the security library.
+ */
+
+/**
+ * The KeyType integer is used by the Sqlite key storage, so don't change them.
+ * Make these the same as ndn-cxx in case the storage file is shared.
+ * @constructor
+ */
+var KeyType = function KeyType()
+{
+}
+
+exports.KeyType = KeyType;
+
+KeyType.RSA = 0;
+KeyType.ECDSA = 1;
+KeyType.AES = 128;
+
+var KeyClass = function KeyClass()
+{
+};
+
+exports.KeyClass = KeyClass;
+
+KeyClass.PUBLIC = 1;
+KeyClass.PRIVATE = 2;
+KeyClass.SYMMETRIC = 3;
+
+var DigestAlgorithm = function DigestAlgorithm()
+{
+};
+
+exports.DigestAlgorithm = DigestAlgorithm;
+
+DigestAlgorithm.SHA256 = 1;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var KeyType = require('./security-types.js').KeyType;
+
+/**
+ * KeyParams is a base class for key parameters. Its subclasses are used to
+ * store parameters for key generation. You should create one of the subclasses,
+ * for example RsaKeyParams.
+ * @constructor
+ */
+var KeyParams = function KeyParams(keyType)
+{
+  this.keyType = keyType;
+};
+
+exports.KeyParams = KeyParams;
+
+KeyParams.prototype.getKeyType = function()
+{
+  return this.keyType;
+};
+
+var RsaKeyParams = function RsaKeyParams(size)
+{
+  // Call the base constructor.
+  KeyParams.call(this, RsaKeyParams.getType());
+
+  if (size == null)
+    size = RsaKeyParams.getDefaultSize();
+  this.size = size;
+};
+
+RsaKeyParams.prototype = new KeyParams();
+RsaKeyParams.prototype.name = "RsaKeyParams";
+
+exports.RsaKeyParams = RsaKeyParams;
+
+RsaKeyParams.prototype.getKeySize = function()
+{
+  return this.size;
+};
+
+RsaKeyParams.getDefaultSize = function() { return 2048; };
+
+RsaKeyParams.getType = function() { return KeyType.RSA; };
+
+var EcdsaKeyParams = function EcdsaKeyParams(size)
+{
+  // Call the base constructor.
+  KeyParams.call(this, EcdsaKeyParams.getType());
+
+  if (size == null)
+    size = EcdsaKeyParams.getDefaultSize();
+  this.size = size;
+};
+
+EcdsaKeyParams.prototype = new KeyParams();
+EcdsaKeyParams.prototype.name = "EcdsaKeyParams";
+
+exports.EcdsaKeyParams = EcdsaKeyParams;
+
+EcdsaKeyParams.prototype.getKeySize = function()
+{
+  return this.size;
+};
+
+EcdsaKeyParams.getDefaultSize = function() { return 256; };
+
+EcdsaKeyParams.getType = function() { return KeyType.ECDSA; };
+
+var AesKeyParams = function AesKeyParams(size)
+{
+  // Call the base constructor.
+  KeyParams.call(this, AesKeyParams.getType());
+
+  if (size == null)
+    size = AesKeyParams.getDefaultSize();
+  this.size = size;
+};
+
+AesKeyParams.prototype = new KeyParams();
+AesKeyParams.prototype.name = "AesKeyParams";
+
+exports.AesKeyParams = AesKeyParams;
+
+AesKeyParams.prototype.getKeySize = function()
+{
+  return this.size;
+};
+
+AesKeyParams.getDefaultSize = function() { return 64; };
+
+AesKeyParams.getType = function() { return KeyType.AES; };
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DerDecodingException = require('../../encoding/der/der-decoding-exception.js').DerDecodingException; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var UnrecognizedKeyFormatException = require('../security-exception.js').UnrecognizedKeyFormatException; /** @ignore */
+var KeyType = require('../security-types.js').KeyType; /** @ignore */
+var DigestAlgorithm = require('../security-types.js').DigestAlgorithm;
+
+/**
+ * Create a new PublicKey by decoding the keyDer. Set the key type from the
+ * decoding.
+ * @param {Blob} keyDer The blob of the SubjectPublicKeyInfo DER.
+ * @throws UnrecognizedKeyFormatException if can't decode the key DER.
+ * @constructor
+ */
+var PublicKey = function PublicKey(keyDer)
+{
+  if (!keyDer) {
+    this.keyDer = new Blob();
+    this.keyType = null;
+    return;
+  }
+
+  this.keyDer = keyDer;
+
+  // Get the public key OID.
+  var oidString = null;
+  try {
+    var parsedNode = DerNode.parse(keyDer.buf(), 0);
+    var rootChildren = parsedNode.getChildren();
+    var algorithmIdChildren = DerNode.getSequence(rootChildren, 0).getChildren();
+    oidString = algorithmIdChildren[0].toVal();
+  }
+  catch (ex) {
+    throw new UnrecognizedKeyFormatException(new Error
+      ("PublicKey.decodeKeyType: Error decoding the public key: " + ex.message));
+  }
+
+  // Verify that the we can decode.
+  if (oidString == PublicKey.RSA_ENCRYPTION_OID) {
+    this.keyType = KeyType.RSA;
+    // TODO: Check RSA decoding.
+  }
+  else if (oidString == PublicKey.EC_ENCRYPTION_OID) {
+    this.keyType = KeyType.ECDSA;
+    // TODO: Check EC decoding.
+  }
+};
+
+exports.PublicKey = PublicKey;
+
+/**
+ * Encode the public key into DER.
+ * @return {DerNode} The encoded DER syntax tree.
+ */
+PublicKey.prototype.toDer = function()
+{
+  return DerNode.parse(this.keyDer.buf());
+};
+
+/**
+ * Get the key type.
+ * @return {number} The key type as an int from KeyType.
+ */
+PublicKey.prototype.getKeyType = function()
+{
+  return this.keyType;
+};
+
+/**
+ * Get the digest of the public key.
+ * @param {number} digestAlgorithm (optional) The integer from DigestAlgorithm,
+ * such as DigestAlgorithm.SHA256. If omitted, use DigestAlgorithm.SHA256 .
+ * @return {Blob} The digest value.
+ */
+PublicKey.prototype.getDigest = function(digestAlgorithm)
+{
+  if (digestAlgorithm == undefined)
+    digestAlgorithm = DigestAlgorithm.SHA256;
+
+  if (digestAlgorithm == DigestAlgorithm.SHA256) {
+    var hash = Crypto.createHash('sha256');
+    hash.update(this.keyDer.buf());
+    return new Blob(hash.digest(), false);
+  }
+  else
+    throw new SecurityException(new Error("Wrong format!"));
+};
+
+/**
+ * Get the raw bytes of the public key in DER format.
+ * @return {Blob} The public key DER.
+ */
+PublicKey.prototype.getKeyDer = function()
+{
+  return this.keyDer;
+};
+
+PublicKey.RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1";
+PublicKey.EC_ENCRYPTION_OID = "1.2.840.10045.2.1";
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var OID = require('../../encoding/oid.js').OID;
+
+/**
+ * A CertificateExtension represents the Extension entry in a certificate.
+ * Create a new CertificateExtension.
+ * @param {string|OID} oid The oid of subject description entry.
+ * @param {boolean} isCritical If true, the extension must be handled.
+ * @param {Blob} value The extension value.
+ * @constructor
+ */
+var CertificateExtension = function CertificateExtension(oid, isCritical, value)
+{
+  if (typeof oid === 'string')
+    this.extensionId = new OID(oid);
+  else
+    // Assume oid is already an OID.
+    this.extensionId = oid;
+
+  this.isCritical = isCritical;
+  this.extensionValue = value;
+};
+
+exports.CertificateExtension = CertificateExtension;
+
+/**
+ * Encode the object into a DER syntax tree.
+ * @return {DerNode} The encoded DER syntax tree.
+ */
+CertificateExtension.prototype.toDer = function()
+{
+  var root = new DerNode.DerSequence();
+
+  var extensionId = new DerNode.DerOid(this.extensionId);
+  var isCritical = new DerNode.DerBoolean(this.isCritical);
+  var extensionValue = new DerNode.DerOctetString(this.extensionValue.buf());
+
+  root.addChild(extensionId);
+  root.addChild(isCritical);
+  root.addChild(extensionValue);
+
+  root.getSize();
+
+  return root;
+};
+
+CertificateExtension.prototype.toDerBlob = function()
+{
+  return this.toDer().encode();
+};
+
+CertificateExtension.prototype.getOid = function()
+{
+  return this.extensionId;
+};
+
+CertificateExtension.prototype.getIsCritical = function()
+{
+  return this.isCritical;
+};
+
+CertificateExtension.prototype.getValue = function()
+{
+  return this.extensionValue;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var OID = require('../../encoding/oid.js').OID; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode;
+
+/**
+ * A CertificateSubjectDescription represents the SubjectDescription entry in a
+ * Certificate.
+ * Create a new CertificateSubjectDescription.
+ * @param {string|OID} oid The oid of the subject description entry.
+ * @param {string} value The value of the subject description entry.
+ * @constructor
+ */
+var CertificateSubjectDescription = function CertificateSubjectDescription
+  (oid, value)
+{
+  if (typeof oid === 'string')
+    this.oid = new OID(oid);
+  else
+    // Assume oid is already an OID.
+    this.oid = oid;
+
+  this.value = value;
+};
+
+exports.CertificateSubjectDescription = CertificateSubjectDescription;
+
+/**
+ * Encode the object into a DER syntax tree.
+ * @return {DerNode} The encoded DER syntax tree.
+ */
+CertificateSubjectDescription.prototype.toDer = function()
+{
+  var root = new DerNode.DerSequence();
+
+  var oid = new DerNode.DerOid(this.oid);
+  // Use Blob to convert the String to a ByteBuffer.
+  var value = new DerNode.DerPrintableString(new Blob(this.value).buf());
+
+  root.addChild(oid);
+  root.addChild(value);
+
+  return root;
+};
+
+CertificateSubjectDescription.prototype.getOidString = function()
+{
+  return this.oid.toString();
+};
+
+CertificateSubjectDescription.prototype.getValue = function()
+{
+  return this.value;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var ContentType = require('../../meta-info.js').ContentType; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var KeyType = require('../../security/security-types.js').KeyType; /** @ignore */
+var PublicKey = require('./public-key.js').PublicKey; /** @ignore */
+var CertificateSubjectDescription = require('./certificate-subject-description.js').CertificateSubjectDescription; /** @ignore */
+var CertificateExtension = require('./certificate-extension.js').CertificateExtension;
+
+/**
+ * Create a Certificate from the content in the data packet (if not omitted).
+ * @param {Data} data (optional) The data packet with the content to decode.
+ * If omitted, create a Certificate with default values and the Data content
+ * is empty.
+ * @constructor
+ */
+var Certificate = function Certificate(data)
+{
+  // Call the base constructor.
+  if (data != undefined)
+    Data.call(this, data);
+  else
+    Data.call(this);
+
+  this.subjectDescriptionList = [];  // of CertificateSubjectDescription
+  this.extensionList = [];           // of CertificateExtension
+  this.notBefore = Number.MAX_VALUE; // MillisecondsSince1970
+  this.notAfter = -Number.MAX_VALUE; // MillisecondsSince1970
+  this.key = new PublicKey();
+
+  if (data != undefined)
+    this.decode();
+};
+Certificate.prototype = new Data();
+Certificate.prototype.name = "Certificate";
+
+exports.Certificate = Certificate;
+
+/**
+ * Encode the contents of the certificate in DER format and set the Content
+ * and MetaInfo fields.
+ */
+Certificate.prototype.encode = function()
+{
+  var root = this.toDer();
+  this.setContent(root.encode());
+  this.getMetaInfo().setType(ContentType.KEY);
+};
+
+/**
+ * Add a subject description.
+ * @param {CertificateSubjectDescription} description The description to be added.
+ */
+Certificate.prototype.addSubjectDescription = function(description)
+{
+  this.subjectDescriptionList.push(description);
+};
+
+/**
+ * Get the subject description list.
+ * @return {Array<CertificateSubjectDescription>} The subject description list.
+ */
+Certificate.prototype.getSubjectDescriptionList = function()
+{
+  return this.subjectDescriptionList;
+};
+
+/**
+ * Add a certificate extension.
+ * @param {CertificateSubjectDescription} extension The extension to be added.
+ */
+Certificate.prototype.addExtension = function(extension)
+{
+  this.extensionList.push(extension);
+};
+
+/**
+ * Get the certificate extension list.
+ * @return {Array<CertificateExtension>} The extension list.
+ */
+Certificate.prototype.getExtensionList = function()
+{
+  return this.extensionList;
+};
+
+Certificate.prototype.setNotBefore = function(notBefore)
+{
+  this.notBefore = notBefore;
+};
+
+Certificate.prototype.getNotBefore = function()
+{
+  return this.notBefore;
+};
+
+Certificate.prototype.setNotAfter = function(notAfter)
+{
+  this.notAfter = notAfter;
+};
+
+Certificate.prototype.getNotAfter = function()
+{
+  return this.notAfter;
+};
+
+Certificate.prototype.setPublicKeyInfo = function(key)
+{
+  this.key = key;
+};
+
+Certificate.prototype.getPublicKeyInfo = function()
+{
+  return this.key;
+};
+
+/**
+ * Check if the certificate is valid.
+ * @return {Boolean} True if the current time is earlier than notBefore.
+ */
+Certificate.prototype.isTooEarly = function()
+{
+  var now = new Date().getTime();
+  return now < this.notBefore;
+};
+
+/**
+ * Check if the certificate is valid.
+ * @return {Boolean} True if the current time is later than notAfter.
+ */
+Certificate.prototype.isTooLate = function()
+{
+  var now = new Date().getTime();
+  return now > this.notAfter;
+};
+
+/**
+ * Encode the certificate fields in DER format.
+ * @return {DerSequence} The DER encoded contents of the certificate.
+ */
+Certificate.prototype.toDer = function()
+{
+  var root = new DerNode.DerSequence();
+  var validity = new DerNode.DerSequence();
+  var notBefore = new DerNode.DerGeneralizedTime(this.notBefore);
+  var notAfter = new DerNode.DerGeneralizedTime(this.notAfter);
+
+  validity.addChild(notBefore);
+  validity.addChild(notAfter);
+
+  root.addChild(validity);
+
+  var subjectList = new DerNode.DerSequence();
+  for (var i = 0; i < this.subjectDescriptionList.length; ++i)
+    subjectList.addChild(this.subjectDescriptionList[i].toDer());
+
+  root.addChild(subjectList);
+  root.addChild(this.key.toDer());
+
+  if (this.extensionList.length > 0) {
+    var extensionList = new DerNode.DerSequence();
+    for (var i = 0; i < this.extensionList.length; ++i)
+      extensionList.addChild(this.extensionList[i].toDer());
+    root.addChild(extensionList);
+  }
+
+  return root;
+};
+
+/**
+ * Populate the fields by the decoding DER data from the Content.
+ */
+Certificate.prototype.decode = function()
+{
+  var root = DerNode.parse(this.getContent().buf());
+
+  // We need to ensure that there are:
+  //   validity (notBefore, notAfter)
+  //   subject list
+  //   public key
+  //   (optional) extension list
+
+  var rootChildren = root.getChildren();
+  // 1st: validity info
+  var validityChildren = DerNode.getSequence(rootChildren, 0).getChildren();
+  this.notBefore = validityChildren[0].toVal();
+  this.notAfter = validityChildren[1].toVal();
+
+  // 2nd: subjectList
+  var subjectChildren = DerNode.getSequence(rootChildren, 1).getChildren();
+  for (var i = 0; i < subjectChildren.length; ++i) {
+    var sd = DerNode.getSequence(subjectChildren, i);
+    var descriptionChildren = sd.getChildren();
+    var oidStr = descriptionChildren[0].toVal();
+    var value = descriptionChildren[1].toVal().buf().toString('binary');
+
+    this.addSubjectDescription(new CertificateSubjectDescription(oidStr, value));
+  }
+
+  // 3rd: public key
+  var publicKeyInfo = rootChildren[2].encode();
+  this.key =  new PublicKey(publicKeyInfo);
+
+  if (rootChildren.length > 3) {
+    var extensionChildren = DerNode.getSequence(rootChildren, 3).getChildren();
+    for (var i = 0; i < extensionChildren.length; ++i) {
+      var extInfo = DerNode.getSequence(extensionChildren, i);
+
+      var children = extInfo.getChildren();
+      var oidStr = children[0].toVal();
+      var isCritical = children[1].toVal();
+      var value = children[2].toVal();
+      this.addExtension(new CertificateExtension(oidStr, isCritical, value));
+    }
+  }
+};
+
+/**
+ * Override to call the base class wireDecode then populate the certificate
+ * fields.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Certificate.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  Data.prototype.wireDecode.call(this, input, wireFormat);
+  this.decode();
+};
+
+Certificate.prototype.toString = function()
+{
+  var s = "Certificate name:\n";
+  s += "  " + this.getName().toUri() + "\n";
+  s += "Validity:\n";
+
+  var notBeforeStr = Certificate.toIsoString(Math.round(this.notBefore));
+  var notAfterStr = Certificate.toIsoString(Math.round(this.notAfter));
+
+  s += "  NotBefore: " + notBeforeStr + "\n";
+  s += "  NotAfter: " + notAfterStr + "\n";
+  for (var i = 0; i < this.subjectDescriptionList.length; ++i) {
+    var sd = this.subjectDescriptionList[i];
+    s += "Subject Description:\n";
+    s += "  " + sd.getOidString() + ": " + sd.getValue() + "\n";
+  }
+
+  s += "Public key bits:\n";
+  var keyDer = this.key.getKeyDer();
+  var encodedKey = keyDer.buf().toString('base64');
+  for (var i = 0; i < encodedKey.length; i += 64)
+    s += encodedKey.substring(i, Math.min(i + 64, encodedKey.length)) + "\n";
+
+  if (this.extensionList.length > 0) {
+    s += "Extensions:\n";
+    for (var i = 0; i < this.extensionList.length; ++i) {
+      var ext = this.extensionList[i];
+      s += "  OID: " + ext.getOid() + "\n";
+      s += "  Is critical: " + (ext.getIsCritical() ? 'Y' : 'N') + "\n";
+
+      s += "  Value: " + ext.getValue().toHex() + "\n" ;
+    }
+  }
+
+  return s;
+};
+
+/**
+ * Convert a UNIX timestamp to ISO time representation with the "T" in the middle.
+ * @param {type} msSince1970 Timestamp as milliseconds since Jan 1, 1970.
+ * @return {string} The string representation.
+ */
+Certificate.toIsoString = function(msSince1970)
+{
+  var utcTime = new Date(Math.round(msSince1970));
+  return utcTime.getUTCFullYear() +
+         Certificate.to2DigitString(utcTime.getUTCMonth() + 1) +
+         Certificate.to2DigitString(utcTime.getUTCDate()) +
+         "T" +
+         Certificate.to2DigitString(utcTime.getUTCHours()) +
+         Certificate.to2DigitString(utcTime.getUTCMinutes()) +
+         Certificate.to2DigitString(utcTime.getUTCSeconds());
+};
+
+/**
+ * A private method to zero pad an integer to 2 digits.
+ * @param {number} x The number to pad.  Assume it is a non-negative integer.
+ * @return {string} The padded string.
+ */
+Certificate.to2DigitString = function(x)
+{
+  var result = x.toString();
+  return result.length === 1 ? "0" + result : result;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var SecurityException = require('../../security//security-exception.js').SecurityException; /** @ignore */
+var Certificate = require('./certificate.js').Certificate; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat;
+
+/**
+ * @constructor
+ */
+var IdentityCertificate = function IdentityCertificate(data)
+{
+  // Call the base constructor.
+  if (data != undefined)
+    // This works if data is Data or IdentityCertificate.
+    Certificate.call(this, data);
+  else
+    Certificate.call(this);
+
+  this.publicKeyName = new Name();
+
+  if (data instanceof IdentityCertificate) {
+    // The copy constructor.
+    this.publicKeyName = new Name(data.publicKeyName);
+  }
+  else if (data instanceof Data) {
+    if (!IdentityCertificate.isCorrectName(data.getName()))
+      throw new SecurityException(new Error("Wrong Identity Certificate Name!"));
+
+    this.setPublicKeyName();
+  }
+};
+IdentityCertificate.prototype = new Certificate();
+IdentityCertificate.prototype.name = "IdentityCertificate";
+
+exports.IdentityCertificate = IdentityCertificate;
+
+/**
+ * Override the base class method to check that the name is a valid identity
+ * certificate name.
+ * @param {Name} name The identity certificate name which is copied.
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+IdentityCertificate.prototype.setName = function(name)
+{
+  if (!IdentityCertificate.isCorrectName(name))
+    throw new SecurityException(new Error("Wrong Identity Certificate Name!"));
+
+  // Call the super class method.
+  Certificate.prototype.setName.call(this, name);
+  this.setPublicKeyName();
+  return this;
+};
+
+/**
+ * Override to call the base class wireDecode then update the public key name.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+IdentityCertificate.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  Certificate.prototype.wireDecode.call(this, input, wireFormat);
+  this.setPublicKeyName();
+};
+
+IdentityCertificate.prototype.getPublicKeyName = function()
+{
+  return this.publicKeyName;
+};
+
+IdentityCertificate.isIdentityCertificate = function(certificate)
+{
+  return IdentityCertificate.isCorrectName(certificate.getName());
+};
+
+/**
+ * Get the public key name from the full certificate name.
+ * @param {Name} certificateName The full certificate name.
+ * @return {Name} The related public key name.
+ */
+IdentityCertificate.certificateNameToPublicKeyName = function(certificateName)
+{
+  var idString = "ID-CERT";
+  var foundIdString = false;
+  var idCertComponentIndex = certificateName.size() - 1;
+  for (; idCertComponentIndex + 1 > 0; --idCertComponentIndex) {
+    if (certificateName.get(idCertComponentIndex).toEscapedString() == idString) {
+      foundIdString = true;
+      break;
+    }
+  }
+
+  if (!foundIdString)
+    throw new Error
+      ("Incorrect identity certificate name " + certificateName.toUri());
+
+  var tempName = certificateName.getSubName(0, idCertComponentIndex);
+  var keyString = "KEY";
+  var foundKeyString = false;
+  var keyComponentIndex = 0;
+  for (; keyComponentIndex < tempName.size(); keyComponentIndex++) {
+    if (tempName.get(keyComponentIndex).toEscapedString() == keyString) {
+      foundKeyString = true;
+      break;
+    }
+  }
+
+  if (!foundKeyString)
+    throw new Error
+      ("Incorrect identity certificate name " + certificateName.toUri());
+
+  return tempName
+    .getSubName(0, keyComponentIndex)
+    .append(tempName.getSubName
+            (keyComponentIndex + 1, tempName.size() - keyComponentIndex - 1));
+};
+
+IdentityCertificate.isCorrectName = function(name)
+{
+  var i = name.size() - 1;
+
+  var idString = "ID-CERT";
+  for (; i >= 0; i--) {
+    if (name.get(i).toEscapedString() == idString)
+      break;
+  }
+
+  if (i < 0)
+    return false;
+
+  var keyIdx = 0;
+  var keyString = "KEY";
+  for (; keyIdx < name.size(); keyIdx++) {
+    if(name.get(keyIdx).toEscapedString() == keyString)
+      break;
+  }
+
+  if (keyIdx >= name.size())
+    return false;
+
+  return true;
+};
+
+IdentityCertificate.prototype.setPublicKeyName = function()
+{
+  this.publicKeyName = IdentityCertificate.certificateNameToPublicKeyName
+    (this.getName());
+};
+
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise;
+
+/**
+ * IdentityStorage is a base class for the storage of identity, public keys and
+ * certificates. Private keys are stored in PrivateKeyStorage.
+ * This is an abstract base class.  A subclass must implement the methods.
+ * @constructor
+ */
+var IdentityStorage = function IdentityStorage()
+{
+};
+
+exports.IdentityStorage = IdentityStorage;
+
+/**
+ * Check if the specified identity already exists.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns true if the identity
+ * exists.
+ */
+IdentityStorage.prototype.doesIdentityExistPromise = function
+  (identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.doesIdentityExistPromise is not implemented"));
+};
+
+/**
+ * Check if the specified identity already exists.
+ * @param {Name} identityName The identity name.
+ * @return {boolean} true if the identity exists, otherwise false.
+ * @throws Error If doesIdentityExistPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.doesIdentityExist = function(identityName)
+{
+  return SyncPromise.getValue(this.doesIdentityExistPromise(identityName, true));
+};
+
+/**
+ * Add a new identity. Do nothing if the identity already exists.
+ * @param {Name} identityName The identity name to be added.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the identity is
+ * added.
+ */
+IdentityStorage.prototype.addIdentityPromise = function(identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.addIdentityPromise is not implemented"));
+};
+
+/**
+ * Add a new identity. Do nothing if the identity already exists.
+ * @param {Name} identityName The identity name to be added.
+ * @throws Error If addIdentityPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.addIdentity = function(identityName)
+{
+  return SyncPromise.getValue(this.addIdentityPromise(identityName, true));
+};
+
+/**
+ * Revoke the identity.
+ * @return {boolean} true if the identity was revoked, false if not.
+ */
+IdentityStorage.prototype.revokeIdentity = function()
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.revokeIdentity is not implemented"));
+};
+
+/**
+ * Generate a name for a new key belonging to the identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useKsk If true, generate a KSK name, otherwise a DSK name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the generated key Name.
+ */
+IdentityStorage.prototype.getNewKeyNamePromise = function
+  (identityName, useKsk, useSync)
+{
+  var timestamp = Math.floor(new Date().getTime() / 1000.0);
+  while (timestamp <= IdentityStorage.lastTimestamp)
+    // Make the timestamp unique.
+    timestamp += 1;
+  IdentityStorage.lastTimestamp = timestamp;
+
+  // Get the number of seconds as a string.
+  var seconds = "" + timestamp;
+
+  var keyIdStr;
+  if (useKsk)
+    keyIdStr = "ksk-" + seconds;
+  else
+    keyIdStr = "dsk-" + seconds;
+
+  var keyName = new Name(identityName).append(keyIdStr);
+
+  return this.doesKeyExistPromise(keyName, useSync)
+  .then(function(exists) {
+    if (exists)
+      throw new SecurityException(new Error("Key name already exists"));
+
+    return SyncPromise.resolve(keyName);
+  });
+};
+
+/**
+ * Generate a name for a new key belonging to the identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useKsk If true, generate a KSK name, otherwise a DSK name.
+ * @return {Name} The generated key name.
+ * @throws Error If getNewKeyNamePromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.getNewKeyName = function(identityName, useKsk)
+{
+  return SyncPromise.getValue
+    (this.getNewKeyNamePromise(identityName, useKsk, true));
+};
+
+/**
+ * Check if the specified key already exists.
+ * @param {Name} keyName The name of the key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns true if the key exists.
+ */
+IdentityStorage.prototype.doesKeyExistPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.doesKeyExistPromise is not implemented"));
+};
+
+/**
+ * Check if the specified key already exists.
+ * @param {Name} keyName The name of the key.
+ * @return {boolean} true if the key exists, otherwise false.
+ * @throws Error If doesKeyExistPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.doesKeyExist = function(keyName)
+{
+  return SyncPromise.getValue(this.doesKeyExistPromise(keyName, true));
+};
+
+/**
+ * Add a public key to the identity storage. Also call addIdentity to ensure
+ * that the identityName for the key exists. However, if the key already
+ * exists, do nothing.
+ * @param {Name} keyName The name of the public key to be added.
+ * @param {number} keyType Type of the public key to be added from KeyType, such
+ * as KeyType.RSA..
+ * @param {Blob} publicKeyDer A blob of the public key DER to be added.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when complete.
+ */
+IdentityStorage.prototype.addKeyPromise = function
+  (keyName, keyType, publicKeyDer, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.addKeyPromise is not implemented"));
+};
+
+/**
+ * Add a public key to the identity storage. Also call addIdentity to ensure
+ * that the identityName for the key exists.
+ * @param {Name} keyName The name of the public key to be added.
+ * @param {number} keyType Type of the public key to be added from KeyType, such
+ * as KeyType.RSA..
+ * @param {Blob} publicKeyDer A blob of the public key DER to be added.
+ * @throws SecurityException if a key with the keyName already exists.
+ * @throws Error If addKeyPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.addKey = function(keyName, keyType, publicKeyDer)
+{
+  return SyncPromise.getValue
+    (this.addKeyPromise(keyName, keyType, publicKeyDer, true));
+};
+
+/**
+ * Get the public key DER blob from the identity storage.
+ * @param {Name} keyName The name of the requested public key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the DER Blob, or a
+ * promise rejected with SecurityException if the key doesn't exist.
+ */
+IdentityStorage.prototype.getKeyPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getKeyPromise is not implemented"));
+};
+
+/**
+ * Get the public key DER blob from the identity storage.
+ * @param {Name} keyName The name of the requested public key.
+ * @return {Blob} The DER Blob.
+ * @throws SecurityException if the key doesn't exist.
+ * @throws Error If getKeyPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.getKey = function(keyName)
+{
+  return SyncPromise.getValue(this.getKeyPromise(keyName, true));
+};
+
+/**
+ * Activate a key.  If a key is marked as inactive, its private part will not be
+ * used in packet signing.
+ * @param {Name} keyName name of the key
+ */
+IdentityStorage.prototype.activateKey = function(keyName)
+{
+  throw new Error("IdentityStorage.activateKey is not implemented");
+};
+
+/**
+ * Deactivate a key. If a key is marked as inactive, its private part will not
+ * be used in packet signing.
+ * @param {Name} keyName name of the key
+ */
+IdentityStorage.prototype.deactivateKey = function(keyName)
+{
+  throw new Error("IdentityStorage.deactivateKey is not implemented");
+};
+
+/**
+ * Check if the specified certificate already exists.
+ * @param {Name} certificateName The name of the certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns true if the certificate
+ * exists.
+ */
+IdentityStorage.prototype.doesCertificateExistPromise = function
+  (certificateName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.doesCertificateExistPromise is not implemented"));
+};
+
+/**
+ * Check if the specified certificate already exists.
+ * @param {Name} certificateName The name of the certificate.
+ * @return {boolean} true if the certificate exists, otherwise false.
+ * @throws Error If doesCertificateExistPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.doesCertificateExist = function(certificateName)
+{
+  return SyncPromise.getValue
+    (this.doesCertificateExistPromise(certificateName, true));
+};
+
+/**
+ * Add a certificate to the identity storage. Also call addKey to ensure that
+ * the certificate key exists. If the certificate is already installed, don't
+ * replace it.
+ * @param {IdentityCertificate} certificate The certificate to be added.  This
+ * makes a copy of the certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when finished.
+ */
+IdentityStorage.prototype.addCertificatePromise = function(certificate, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.addCertificatePromise is not implemented"));
+};
+
+/**
+ * Add a certificate to the identity storage.
+ * @param {IdentityCertificate} certificate The certificate to be added.  This
+ * makes a copy of the certificate.
+ * @throws SecurityException if the certificate is already installed.
+ * @throws Error If addCertificatePromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.addCertificate = function(certificate)
+{
+  return SyncPromise.getValue(this.addCertificatePromise(certificate, true));
+};
+
+/**
+ * Get a certificate from the identity storage.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the requested
+ * IdentityCertificate, or a promise rejected with SecurityException if the
+ * certificate doesn't exist.
+ */
+IdentityStorage.prototype.getCertificatePromise = function
+  (certificateName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getCertificatePromise is not implemented"));
+};
+
+/**
+ * Get a certificate from the identity storage.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @return {IdentityCertificate} The requested certificate.
+ * @throws SecurityException if the certificate doesn't exist.
+ * @throws Error If getCertificatePromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.getCertificate = function(certificateName)
+{
+  return SyncPromise.getValue(this.getValuePromise(certificateName, true));
+};
+
+/**
+ * Get the TPM locator associated with this storage.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise|SyncPromise} A promise which returns the TPM locator, or a
+ * promise rejected with SecurityException if the TPM locator doesn't exist.
+ */
+IdentityStorage.prototype.getTpmLocatorPromise = function(useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getTpmLocatorPromise is not implemented"));
+};
+
+/**
+ * Get the TPM locator associated with this storage.
+ * @return {string} The TPM locator.
+ * @throws SecurityException if the TPM locator doesn't exist.
+ * @throws Error If getTpmLocatorPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+IdentityStorage.prototype.getTpmLocator = function()
+{
+  return SyncPromise.getValue(this.getTpmLocatorPromise(true));
+};
+
+/*****************************************
+ *           Get/Set Default             *
+ *****************************************/
+
+/**
+ * Get the default identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the Name of default
+ * identity, or a promise rejected with SecurityException if the default
+ * identity is not set.
+ */
+IdentityStorage.prototype.getDefaultIdentityPromise = function(useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getDefaultIdentityPromise is not implemented"));
+};
+
+/**
+ * Get the default identity.
+ * @return {Name} The name of default identity.
+ * @throws SecurityException if the default identity is not set.
+ * @throws Error If getDefaultIdentityPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultIdentity = function()
+{
+  return SyncPromise.getValue
+    (this.getDefaultIdentityPromise(true));
+};
+
+/**
+ * Get the default key name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the default key Name,
+ * or a promise rejected with SecurityException if the default key name for the
+ * identity is not set.
+ */
+IdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
+  (identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getDefaultKeyNameForIdentityPromise is not implemented"));
+};
+
+/**
+ * Get the default key name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @return {Name} The default key name.
+ * @throws SecurityException if the default key name for the identity is not set.
+ * @throws Error If getDefaultKeyNameForIdentityPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultKeyNameForIdentity = function(identityName)
+{
+  return SyncPromise.getValue
+    (this.getDefaultKeyNameForIdentityPromise(identityName, true));
+};
+
+/**
+ * Get the default certificate name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the default certificate
+ * Name, or a promise rejected with SecurityException if the default key name
+ * for the identity is not set or the default certificate name for the key name
+ * is not set.
+ */
+IdentityStorage.prototype.getDefaultCertificateNameForIdentityPromise = function
+  (identityName, useSync)
+{
+  var thisStorage = this;
+  return this.getDefaultKeyNameForIdentityPromise(identityName)
+  .then(function(keyName) {
+    return thisStorage.getDefaultCertificateNameForKeyPromise(keyName);
+  });
+};
+
+/**
+ * Get the default certificate name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @return {Name} The default certificate name.
+ * @throws SecurityException if the default key name for the identity is not
+ * set or the default certificate name for the key name is not set.
+ * @throws Error If getDefaultCertificateNameForIdentityPromise doesn't return
+ * a SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultCertificateNameForIdentity = function
+  (identityName)
+{
+  return SyncPromise.getValue
+    (this.getDefaultCertificateNameForIdentityPromise(identityName, true));
+};
+
+/**
+ * Get the default certificate name for the specified key.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the default certificate
+ * Name, or a promise rejected with SecurityException if the default certificate
+ * name for the key name is not set.
+ */
+IdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
+  (keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getDefaultCertificateNameForKeyPromise is not implemented"));
+};
+
+/**
+ * Get the default certificate name for the specified key.
+ * @param {Name} keyName The key name.
+ * @return {Name} The default certificate name.
+ * @throws SecurityException if the default certificate name for the key name
+ * is not set.
+ * @throws Error If getDefaultCertificateNameForKeyPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultCertificateNameForKey = function(keyName)
+{
+  return SyncPromise.getValue
+    (this.getDefaultCertificateNameForKeyPromise(keyName, true));
+};
+
+/**
+ * Append all the identity names to the nameList.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default identity name. If
+ * false, add only the non-default identity names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IdentityStorage.prototype.getAllIdentitiesPromise = function
+  (nameList, isDefault, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getAllIdentitiesPromise is not implemented"));
+};
+
+/**
+ * Append all the key names of a particular identity to the nameList.
+ * @param {Name} identityName The identity name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default key name. If false,
+ * add only the non-default key names.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the names are
+ * added to nameList.
+ */
+IdentityStorage.prototype.getAllKeyNamesOfIdentityPromise = function
+  (identityName, nameList, isDefault, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getAllKeyNamesOfIdentityPromise is not implemented"));
+};
+
+/**
+ * Append all the certificate names of a particular key name to the nameList.
+ * @param {Name} keyName The key name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default certificate name.
+ * If false, add only the non-default certificate names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IdentityStorage.prototype.getAllCertificateNamesOfKeyPromise = function
+  (keyName, nameList, isDefault, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getAllCertificateNamesOfKeyPromise is not implemented"));
+};
+
+/**
+ * Append all the key names of a particular identity to the nameList.
+ * @param {Name} identityName The identity name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default key name. If false,
+ * add only the non-default key names.
+ * @throws Error If getAllKeyNamesOfIdentityPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.getAllKeyNamesOfIdentity = function
+  (identityName, nameList, isDefault)
+{
+  return SyncPromise.getValue
+    (this.getAllKeyNamesOfIdentityPromise(identityName, nameList, isDefault, true));
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default
+ * identity is set.
+ */
+IdentityStorage.prototype.setDefaultIdentityPromise = function
+  (identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.setDefaultIdentityPromise is not implemented"));
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @throws Error If setDefaultIdentityPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.setDefaultIdentity = function(identityName)
+{
+  return SyncPromise.getValue
+    (this.setDefaultIdentityPromise(identityName, true));
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default key
+ * name is set.
+ */
+IdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
+  (keyName, identityNameCheck, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.setDefaultKeyNameForIdentityPromise is not implemented"));
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @throws Error If setDefaultKeyNameForIdentityPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.setDefaultKeyNameForIdentity = function
+  (keyName, identityNameCheck)
+{
+  return SyncPromise.getValue
+    (this.setDefaultKeyNameForIdentityPromise(keyName, identityNameCheck, true));
+};
+
+/**
+ * Set the default key name for the specified identity.
+ * @param {Name} keyName The key name.
+ * @param {Name} certificateName The certificate name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default
+ * certificate name is set.
+ */
+IdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
+  (keyName, certificateName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.setDefaultCertificateNameForKeyPromise is not implemented"));
+};
+
+/**
+ * Set the default key name for the specified identity.
+ * @param {Name} keyName The key name.
+ * @param {Name} certificateName The certificate name.
+ * @throws Error If setDefaultCertificateNameForKeyPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.setDefaultCertificateNameForKey = function
+  (keyName, certificateName)
+{
+  return SyncPromise.getValue
+    (this.setDefaultCertificateNameForKeyPromise(keyName, certificateName, true));
+};
+
+/**
+ * Get the certificate of the default identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the requested
+ * IdentityCertificate or null if not found.
+ */
+IdentityStorage.prototype.getDefaultCertificatePromise = function(useSync)
+{
+  var thisStorage = this;
+  return this.getDefaultIdentityPromise(useSync)
+  .then(function(identityName) {
+    return thisStorage.getDefaultCertificateNameForIdentityPromise
+      (identityName, useSync);
+  }, function(ex) {
+    // The default is not defined.
+    return SyncPromise.resolve(null);
+  })
+  .then(function(certName) {
+    if (certName == null)
+      return SyncPromise.resolve(null);
+
+    return thisStorage.getCertificatePromise(certName, useSync);
+  });
+};
+
+/**
+ * Get the certificate of the default identity.
+ * @return {IdentityCertificate} The requested certificate.  If not found,
+ * return null.
+ * @throws Error If getDefaultCertificatePromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultCertificate = function()
+{
+  return SyncPromise.getValue
+    (this.getDefaultCertificatePromise(true));
+};
+
+/*****************************************
+ *            Delete Methods             *
+ *****************************************/
+
+/**
+ * Delete a certificate.
+ * @param {Name} certificateName The certificate name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the certificate
+ * info is deleted.
+ */
+IdentityStorage.prototype.deleteCertificateInfoPromise = function
+  (certificateName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.deleteCertificateInfoPromise is not implemented"));
+};
+
+/**
+ * Delete a certificate.
+ * @param {Name} certificateName The certificate name.
+ * @throws Error If deleteCertificateInfoPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.deleteCertificateInfo = function(certificateName)
+{
+  return SyncPromise.getValue
+    (this.deleteCertificateInfoPromise(certificateName, true));
+};
+
+/**
+ * Delete a public key and related certificates.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the public key
+ * info is deleted.
+ */
+IdentityStorage.prototype.deletePublicKeyInfoPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject
+    (new Error("IdentityStorage.deletePublicKeyInfoPromise is not implemented"));
+};
+
+/**
+ * Delete a public key and related certificates.
+ * @param {Name} keyName The key name.
+ * @throws Error If deletePublicKeyInfoPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.deletePublicKeyInfo = function(keyName)
+{
+  return SyncPromise.getValue
+    (this.deletePublicKeyInfoPromise(keyName, true));
+};
+
+/**
+ * Delete an identity and related public keys and certificates.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the identity info
+ * is deleted.
+ */
+IdentityStorage.prototype.deleteIdentityInfoPromise = function
+  (identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.deleteIdentityInfoPromise is not implemented"));
+};
+
+/**
+ * Delete an identity and related public keys and certificates.
+ * @param {Name} identityName The identity name.
+ * @throws Error If deleteIdentityInfoPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.deleteIdentityInfo = function(identityName)
+{
+  return SyncPromise.getValue
+    (this.deleteIdentityInfoPromise(identityName, true));
+};
+
+// Track the lastTimestamp so that each timestamp is unique.
+IdentityStorage.lastTimestamp = Math.floor(new Date().getTime() / 1000.0);
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Don't require modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbIdentityStorage extends IdentityStorage and implements its methods
+ * to store identity, public key and certificate objects using the browser's
+ * IndexedDB service.
+ * @constructor
+ */
+var IndexedDbIdentityStorage = function IndexedDbIdentityStorage()
+{
+  IdentityStorage.call(this);
+
+  this.database = new Dexie("ndnsec-public-info");
+  // The database schema imitates MemoryIdentityStorage.
+  this.database.version(1).stores({
+    // A table for global values. It currently only has the defaultIdentityUri.
+    // "key" is the key like "defaultIdentityUri" // string
+    // "value" is the value. For "defaultIdentityUri" the value is the
+    //         default identity name URI, or absent if not defined. // string
+    globals: "key",
+
+    // "identityNameUri" is the identity name URI          // string
+    // "defaultKeyUri" is the default key name URI or null // string
+    identity: "identityNameUri",
+
+    // "keyNameUri" is the key name URI                             // string
+    // "keyType" is the type of the public key            // number from KeyType
+    // "keyDer" is the public key DER                               // Uint8Array
+    // "defaultCertificateUri" is the default cert name URI or null // string
+    publicKey: "keyNameUri",
+
+    // "certificateNameUri" is the certificate name URI // string
+    // "encoding" is the certificate wire encoding      // Uint8Array
+    certificate: "certificateNameUri"
+  });
+  this.database.open();
+};
+
+IndexedDbIdentityStorage.prototype = new IdentityStorage();
+IndexedDbIdentityStorage.prototype.name = "IndexedDbIdentityStorage";
+
+/**
+ * Check if the specified identity already exists.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns true if the identity exists.
+ */
+IndexedDbIdentityStorage.prototype.doesIdentityExistPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.doesIdentityExistPromise is only supported for async")));
+
+  return this.database.identity.where("identityNameUri").equals
+    (identityName.toUri())
+  .count()
+  .then(function(count) {
+    return Promise.resolve(count > 0);
+  });
+};
+
+/**
+ * Add a new identity. Do nothing if the identity already exists.
+ * @param {Name} identityName The identity name to be added.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the identity is added.
+ */
+IndexedDbIdentityStorage.prototype.addIdentityPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.addIdentityPromise is only supported for async")));
+
+  var thisStorage = this;
+  return this.doesIdentityExistPromise(identityName)
+  .then(function(exists) {
+    if (exists)
+      // Do nothing.
+      return Promise.resolve();
+
+    return thisStorage.database.identity.put
+      ({ identityNameUri: identityName.toUri(), defaultKeyUri: null });
+  });
+};
+
+/**
+ * Check if the specified key already exists.
+ * @param {Name} keyName The name of the key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns true if the key exists.
+ */
+IndexedDbIdentityStorage.prototype.doesKeyExistPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.doesKeyExistPromise is only supported for async")));
+
+  return this.database.publicKey.where("keyNameUri").equals(keyName.toUri())
+  .count()
+  .then(function(count) {
+    return Promise.resolve(count > 0);
+  });
+};
+
+/**
+ * Add a public key to the identity storage. Also call addIdentity to ensure
+ * that the identityName for the key exists. However, if the key already
+   * exists, do nothing.
+ * @param {Name} keyName The name of the public key to be added.
+ * @param {number} keyType Type of the public key to be added from KeyType, such
+ * as KeyType.RSA..
+ * @param {Blob} publicKeyDer A blob of the public key DER to be added.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when complete.
+ */
+IndexedDbIdentityStorage.prototype.addKeyPromise = function
+  (keyName, keyType, publicKeyDer, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.addKeyPromise is only supported for async")));
+
+  if (keyName.size() === 0)
+    return Promise.resolve();
+
+  var thisStorage = this;
+  return this.doesKeyExistPromise(keyName)
+  .then(function(exists) {
+    if (exists)
+      return Promise.resolve();
+
+    var identityName = keyName.getPrefix(-1);
+    return thisStorage.addIdentityPromise(identityName)
+    .then(function() {
+      return thisStorage.database.publicKey.put
+        ({ keyNameUri: keyName.toUri(), keyType: keyType,
+           keyDer: new Blob(publicKeyDer, true).buf(),
+           defaultCertificate: null });
+    });
+  });
+};
+
+/**
+ * Get the public key DER blob from the identity storage.
+ * @param {Name} keyName The name of the requested public key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the DER Blob, or a promise rejected
+ * with SecurityException if the key doesn't exist.
+ */
+IndexedDbIdentityStorage.prototype.getKeyPromise = function(keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getKeyPromise is only supported for async")));
+
+  if (keyName.size() === 0)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage::getKeyPromise: Empty keyName")));
+
+  return this.database.publicKey.get(keyName.toUri())
+  .then(function(publicKeyEntry) {
+    if (publicKeyEntry)
+      return Promise.resolve(new Blob(publicKeyEntry.keyDer));
+    else
+      return Promise.reject(new SecurityException(new Error
+        ("IndexedDbIdentityStorage::getKeyPromise: The key does not exist")));
+  });
+};
+
+/**
+ * Check if the specified certificate already exists.
+ * @param {Name} certificateName The name of the certificate.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns true if the certificate exists.
+ */
+IndexedDbIdentityStorage.prototype.doesCertificateExistPromise = function
+  (certificateName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.doesCertificateExistPromise is only supported for async")));
+
+  return this.database.certificate.where("certificateNameUri").equals
+    (certificateName.toUri())
+  .count()
+  .then(function(count) {
+    return Promise.resolve(count > 0);
+  });
+};
+
+/**
+ * Add a certificate to the identity storage. Also call addKey to ensure that
+ * the certificate key exists. If the certificate is already installed, don't
+ * replace it.
+ * @param {IdentityCertificate} certificate The certificate to be added.  This
+ * makes a copy of the certificate.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when finished.
+ */
+IndexedDbIdentityStorage.prototype.addCertificatePromise = function
+  (certificate, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.addCertificatePromise is only supported for async")));
+
+  var certificateName = certificate.getName();
+  var keyName = certificate.getPublicKeyName();
+
+  var thisStorage = this;
+  return this.addKeyPromise
+    (keyName, certificate.getPublicKeyInfo().getKeyType(),
+     certificate.getPublicKeyInfo().getKeyDer(), useSync)
+  .then(function() {
+    return thisStorage.doesCertificateExistPromise(certificateName);
+  })
+  .then(function(exists) {
+    if (exists)
+      return Promise.resolve();
+
+    // Insert the certificate.
+    // wireEncode returns the cached encoding if available.
+    return thisStorage.database.certificate.put
+      ({ certificateNameUri: certificateName.toUri(),
+         encoding: certificate.wireEncode().buf() });
+  });
+};
+
+/**
+ * Get a certificate from the identity storage.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the requested
+ * IdentityCertificate, or a promise rejected with SecurityException if the
+ * certificate doesn't exist.
+ */
+IndexedDbIdentityStorage.prototype.getCertificatePromise = function
+  (certificateName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getCertificatePromise is only supported for async")));
+
+  return this.database.certificate.get(certificateName.toUri())
+  .then(function(certificateEntry) {
+    if (certificateEntry) {
+      var certificate = new IdentityCertificate();
+      try {
+        certificate.wireDecode(certificateEntry.encoding);
+      } catch (ex) {
+        return Promise.reject(new SecurityException(new Error
+          ("IndexedDbIdentityStorage::getCertificatePromise: The certificate cannot be decoded")));
+      }
+      return Promise.resolve(certificate);
     }
     else
-        interest.interestLifetime = 4000;   // default interest timeout value in milliseconds.
+      return Promise.reject(new SecurityException(new Error
+        ("IndexedDbIdentityStorage::getCertificatePromise: The certificate does not exist")));
+  });
+};
 
-	if (this.host == null || this.port == null) {
-        if (this.getHostAndPort == null)
-            console.log('ERROR: host OR port NOT SET');
-        else {
-            var thisNDN = this;
-            this.connectAndExecute
-                (function() { thisNDN.reconnectAndExpressInterest(interest, closure); });
+/*****************************************
+ *           Get/Set Default             *
+ *****************************************/
+
+/**
+ * Get the default identity.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the Name of default identity,
+ * or a promise rejected with SecurityException if the default identity is not
+ * set.
+ */
+IndexedDbIdentityStorage.prototype.getDefaultIdentityPromise = function(useSync)
+{
+  return this.database.globals.get("defaultIdentityUri")
+  .then(function(defaultIdentityEntry) {
+    if (defaultIdentityEntry)
+      return Promise.resolve(new Name(defaultIdentityEntry.value));
+    else
+      throw new SecurityException(new Error
+        ("IndexedDbIdentityStorage.getDefaultIdentity: The default identity is not defined"));
+  });
+};
+
+/**
+ * Get the default key name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the default key Name, or a
+ * promise rejected with SecurityException if the default key name for the
+ * identity is not set.
+ */
+IndexedDbIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getDefaultKeyNameForIdentityPromise is only supported for async")));
+
+  return this.database.identity.get(identityName.toUri())
+  .then(function(identityEntry) {
+    if (identityEntry) {
+      if (identityEntry.defaultKeyUri != null)
+        return Promise.resolve(new Name(identityEntry.defaultKeyUri));
+      else
+        throw new SecurityException(new Error("No default key set."));
+    }
+    else
+      throw new SecurityException(new Error("Identity not found."));
+  });
+};
+
+/**
+ * Get the default certificate name for the specified key.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the default certificate Name,
+ * or a promise rejected with SecurityException if the default certificate name
+ * for the key name is not set.
+ */
+IndexedDbIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getDefaultCertificateNameForKeyPromise is only supported for async")));
+
+  return this.database.publicKey.get(keyName.toUri())
+  .then(function(publicKeyEntry) {
+    if (publicKeyEntry) {
+      if (publicKeyEntry.defaultCertificateUri != null)
+        return Promise.resolve(new Name(publicKeyEntry.defaultCertificateUri));
+      else
+        throw new SecurityException(new Error("No default certificate set."));
+    }
+    else
+      throw new SecurityException(new Error("Key not found."));
+  });
+};
+
+/**
+ * Append all the identity names to the nameList.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default identity name. If
+ * false, add only the non-default identity names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IndexedDbIdentityStorage.prototype.getAllIdentitiesPromise = function
+  (nameList, isDefault, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getAllIdentitiesPromise is only supported for async")));
+
+  var defaultIdentityName = null;
+  var thisStorage = this;
+  return this.getDefaultIdentityPromise()
+  .then(function(localDefaultIdentityName) {
+    defaultIdentityName = localDefaultIdentityName;
+    return SyncPromise.resolve();
+  }, function(err) {
+    // The default identity name was not found.
+    return SyncPromise.resolve();
+  })
+  .then(function() {
+    return thisStorage.database.identity.each(function(identityEntry) {
+      var identityName = new Name(identityEntry.identityNameUri);
+      var identityNameIsDefault =
+        (defaultIdentityName !== null && identityName.equals(defaultIdentityName));
+      if (isDefault && identityNameIsDefault)
+        nameList.push(identityName);
+      else if (!isDefault && !identityNameIsDefault)
+        nameList.push(identityName);
+    });
+  });
+};
+
+/**
+ * Append all the key names of a particular identity to the nameList.
+ * @param {Name} identityName The identity name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default key name. If false,
+ * add only the non-default key names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IndexedDbIdentityStorage.prototype.getAllKeyNamesOfIdentityPromise = function
+  (identityName, nameList, isDefault, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getAllKeyNamesOfIdentityPromise is only supported for async")));
+
+  var defaultKeyName = null;
+  var thisStorage = this;
+  return this.getDefaultKeyNameForIdentityPromise(identityName)
+  .then(function(localDefaultKeyName) {
+    defaultKeyName = localDefaultKeyName;
+    return SyncPromise.resolve();
+  }, function(err) {
+    // The default key name was not found.
+    return SyncPromise.resolve();
+  })
+  .then(function() {
+    // Iterate through each publicKey a to find ones that match identityName.
+    // This is a little inefficient, but we don't expect the in-browser
+    // database to be very big, we don't expect to use this function often (for
+    // deleting an identity), and this is simpler than complicating the database
+    // schema to store the identityName with each publicKey.
+    return thisStorage.database.publicKey.each(function(publicKeyEntry) {
+      var keyName = new Name(publicKeyEntry.keyNameUri);
+      var keyIdentityName = keyName.getPrefix(-1);
+
+      if (keyIdentityName.equals(identityName)) {
+        var keyNameIsDefault =
+          (defaultKeyName !== null && keyName.equals(defaultKeyName));
+        if (isDefault && keyNameIsDefault)
+          nameList.push(keyName);
+        else if (!isDefault && !keyNameIsDefault)
+          nameList.push(keyName);
+      }
+    });
+  });
+};
+
+/**
+ * Append all the certificate names of a particular key name to the nameList.
+ * @param {Name} keyName The key name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default certificate name.
+ * If false, add only the non-default certificate names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IndexedDbIdentityStorage.prototype.getAllCertificateNamesOfKeyPromise = function
+  (keyName, nameList, isDefault, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getAllCertificateNamesOfKeyPromise is only supported for async")));
+
+  var defaultCertificateName = null;
+  var thisStorage = this;
+  return this.getDefaultCertificateNameForKeyPromise(keyName)
+  .then(function(localDefaultCertificateName) {
+    defaultCertificateName = localDefaultCertificateName;
+    return SyncPromise.resolve();
+  }, function(err) {
+    // The default certificate name was not found.
+    return SyncPromise.resolve();
+  })
+  .then(function() {
+    // Iterate through each certificate record a to find ones that match keyName.
+    // This is a little inefficient, but we don't expect the in-browser
+    // database to be very big, we don't expect to use this function often (for
+    // deleting an identity), and this is simpler than complicating the database
+    // schema to store the keyName with each certificate record.
+    return thisStorage.database.certificate.each(function(certificateEntry) {
+      var certificateName = new Name(certificateEntry.certificateNameUri);
+      var certificateKeyName = IdentityCertificate.certificateNameToPublicKeyName
+        (certificateName);
+
+      if (certificateKeyName.equals(keyName)) {
+        var certificateNameIsDefault =
+          (defaultCertificateName !== null &&
+           certificateName.equals(defaultCertificateName));
+        if (isDefault && certificateNameIsDefault)
+          nameList.push(certificateName);
+        else if (!isDefault && !certificateNameIsDefault)
+          nameList.push(certificateName);
+      }
+    });
+  });
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the default identity is set.
+ */
+IndexedDbIdentityStorage.prototype.setDefaultIdentityPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.setDefaultIdentityPromise is only supported for async")));
+
+  var thisStorage = this;
+  return this.doesIdentityExistPromise(identityName)
+  .then(function(exists) {
+    if (exists)
+      return thisStorage.database.globals.put
+        ({ key: "defaultIdentityUri", value: identityName.toUri() });
+    else
+      // The identity doesn't exist, so clear the default.
+      return thisStorage.database.globals.delete("defaultIdentityUri");
+  });
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the default key name is
+ * set.
+ */
+IndexedDbIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
+  (keyName, identityNameCheck, useSync)
+{
+  useSync = (typeof identityNameCheck === "boolean") ? identityNameCheck : useSync;
+  identityNameCheck = (identityNameCheck instanceof Name) ? identityNameCheck : null;
+
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.setDefaultKeyNameForIdentityPromise is only supported for async")));
+
+  var identityName = keyName.getPrefix(-1);
+
+  if (identityNameCheck != null && identityNameCheck.size() > 0 &&
+      !identityNameCheck.equals(identityName))
+    return Promise.reject(new SecurityException(new Error
+      ("The specified identity name does not match the key name")));
+
+  // update does nothing if the identityName doesn't exist.
+  return this.database.identity.update
+    (identityName.toUri(), { defaultKeyUri: keyName.toUri() });
+};
+
+/**
+ * Set the default key name for the specified identity.
+ * @param {Name} keyName The key name.
+ * @param {Name} certificateName The certificate name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the default certificate
+ * name is set.
+ */
+IndexedDbIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
+  (keyName, certificateName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.setDefaultCertificateNameForKeyPromise is only supported for async")));
+
+  // update does nothing if the keyName doesn't exist.
+  return this.database.publicKey.update
+    (keyName.toUri(), { defaultCertificateUri: certificateName.toUri() });
+};
+
+/*****************************************
+ *            Delete Methods             *
+ *****************************************/
+
+/**
+ * Delete a certificate.
+ * @param {Name} certificateName The certificate name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the certificate info is
+ * deleted.
+ */
+IndexedDbIdentityStorage.prototype.deleteCertificateInfoPromise = function
+  (certificateName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.deleteCertificateInfoPromise is only supported for async")));
+
+  if (certificateName.size() === 0)
+    return Promise.resolve();
+
+  return this.database.certificate.delete(certificateName.toUri());
+};
+
+/**
+ * Delete a public key and related certificates.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the public key info is
+ * deleted.
+ */
+IndexedDbIdentityStorage.prototype.deletePublicKeyInfoPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.deletePublicKeyInfoPromise is only supported for async")));
+
+  if (keyName.size() === 0)
+    return Promise.resolve();
+
+  var thisStorage = this;
+  return this.database.publicKey.delete(keyName.toUri())
+  .then(function() {
+    // Iterate through each certificate to find ones that match keyName. This is
+    // a little inefficient, but we don't expect the in-browswer database to be
+    // very big, we don't expect to delete often, and this is simpler than
+    // complicating the database schema to store the keyName with each certificate.
+    return thisStorage.database.certificate.each(function(certificateEntry) {
+      if (IdentityCertificate.certificateNameToPublicKeyName
+          (new Name(certificateEntry.certificateNameUri)).equals(keyName))
+        thisStorage.database.certificate.delete
+          (certificateEntry.certificateNameUri);
+    });
+  });
+};
+
+/**
+ * Delete an identity and related public keys and certificates.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the identity info is
+ * deleted.
+ */
+IndexedDbIdentityStorage.prototype.deleteIdentityInfoPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.deleteIdentityInfoPromise is only supported for async")));
+
+  var thisStorage = this;
+  return this.database.identity.delete(identityName.toUri())
+  // Iterate through each publicKey and certificate to find ones that match
+  // identityName. This is a little inefficient, but we don't expect the
+  // in-browswer database to be very big, we don't expect to delete often, and
+  // this is simpler than complicating the database schema to store the
+  // identityName with each publicKey and certificate.
+  .then(function() {
+    return thisStorage.database.publicKey.each(function(publicKeyEntry) {
+      var keyIdentityName = new Name(publicKeyEntry.keyNameUri).getPrefix(-1);
+      if (keyIdentityName.equals(identityName))
+        thisStorage.database.publicKey.delete(publicKeyEntry.keyNameUri);
+    });
+  })
+  .then(function() {
+    return thisStorage.database.certificate.each(function(certificateEntry) {
+      var certificateKeyName = IdentityCertificate.certificateNameToPublicKeyName
+        (new Name(certificateEntry.certificateNameUri));
+      var certificateIdentityName = certificateKeyName.getPrefix(-1);
+      if (certificateIdentityName.equals(identityName))
+        thisStorage.database.certificate.delete
+          (certificateEntry.certificateNameUri);
+    });
+  });
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var IdentityStorage = require('./identity-storage.js').IdentityStorage;
+
+/**
+ * MemoryIdentityStorage extends IdentityStorage and implements its methods to
+ * store identity, public key and certificate objects in memory. The application
+ * must get the objects through its own means and add the objects to the
+ * MemoryIdentityStorage object. To use permanent file-based storage, see
+ * BasicIdentityStorage.
+ * @constructor
+ */
+var MemoryIdentityStorage = function MemoryIdentityStorage()
+{
+  // Call the base constructor.
+  IdentityStorage.call(this);
+
+  // The map key is the identityName.toUri(). The value is the object
+  //   {defaultKey // Name
+  //   }.
+  this.identityStore = {};
+  // The default identity in identityStore, or "" if not defined.
+  this.defaultIdentity = "";
+  // The key is the keyName.toUri(). The value is the object
+  //  {keyType, // number from KeyType
+  //   keyDer   // Blob
+  //   defaultCertificate // Name
+  //  }.
+  this.keyStore = {};
+  // The key is the key is the certificateName.toUri(). The value is the
+  //   encoded certificate.
+  this.certificateStore = {};
+};
+
+MemoryIdentityStorage.prototype = new IdentityStorage();
+MemoryIdentityStorage.prototype.name = "MemoryIdentityStorage";
+
+exports.MemoryIdentityStorage = MemoryIdentityStorage;
+/**
+ * Check if the specified identity already exists.
+ * @param {Name} identityName The identity name.
+ * @return {SyncPromise} A promise which returns true if the identity exists.
+ */
+MemoryIdentityStorage.prototype.doesIdentityExistPromise = function(identityName)
+{
+  return SyncPromise.resolve
+    (this.identityStore[identityName.toUri()] !== undefined);
+};
+
+/**
+ * Add a new identity. Do nothing if the identity already exists.
+ * @param {Name} identityName The identity name to be added.
+ * @return {SyncPromise} A promise which fulfills when the identity is added.
+ */
+MemoryIdentityStorage.prototype.addIdentityPromise = function(identityName)
+{
+  var identityUri = identityName.toUri();
+  if (this.identityStore[identityUri] === undefined)
+    this.identityStore[identityUri] = { defaultKey: null };
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Check if the specified key already exists.
+ * @param {Name} keyName The name of the key.
+ * @return {SyncPromise} A promise which returns true if the key exists.
+ */
+MemoryIdentityStorage.prototype.doesKeyExistPromise = function(keyName)
+{
+  return SyncPromise.resolve(this.keyStore[keyName.toUri()] !== undefined);
+};
+
+/**
+ * Add a public key to the identity storage. Also call addIdentity to ensure
+ * that the identityName for the key exists. However, if the key already
+ * exists, do nothing.
+ * @param {Name} keyName The name of the public key to be added.
+ * @param {number} keyType Type of the public key to be added from KeyType, such
+ * as KeyType.RSA..
+ * @param {Blob} publicKeyDer A blob of the public key DER to be added.
+ * @return {SyncPromise} A promise which fulfills when complete.
+ */
+MemoryIdentityStorage.prototype.addKeyPromise = function
+  (keyName, keyType, publicKeyDer)
+{
+  if (keyName.size() === 0)
+    return SyncPromise.resolve();
+
+  if (this.doesKeyExist(keyName))
+    return SyncPromise.resolve();
+
+  var identityName = keyName.getSubName(0, keyName.size() - 1);
+
+  this.addIdentity(identityName);
+
+  this.keyStore[keyName.toUri()] =
+    { keyType: keyType, keyDer: new Blob(publicKeyDer), defaultCertificate: null };
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Get the public key DER blob from the identity storage.
+ * @param {Name} keyName The name of the requested public key.
+ * @return {SyncPromise} A promise which returns the DER Blob, or a promise
+ * rejected with SecurityException if the key doesn't exist.
+ */
+MemoryIdentityStorage.prototype.getKeyPromise = function(keyName)
+{
+  if (keyName.size() === 0)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage::getKeyPromise: Empty keyName")));
+
+  var keyNameUri = keyName.toUri();
+  var entry = this.keyStore[keyNameUri];
+  if (entry === undefined)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage::getKeyPromise: The key does not exist")));
+
+  return SyncPromise.resolve(entry.keyDer);
+};
+
+/**
+ * Check if the specified certificate already exists.
+ * @param {Name} certificateName The name of the certificate.
+ * @return {SyncPromise} A promise which returns true if the certificate exists.
+ */
+MemoryIdentityStorage.prototype.doesCertificateExistPromise = function
+  (certificateName)
+{
+  return SyncPromise.resolve
+    (this.certificateStore[certificateName.toUri()] !== undefined);
+};
+
+/**
+ * Add a certificate to the identity storage. Also call addKey to ensure that
+ * the certificate key exists. If the certificate is already installed, don't
+ * replace it.
+ * @param {IdentityCertificate} certificate The certificate to be added.  This
+ * makes a copy of the certificate.
+ * @return {SyncPromise} A promise which fulfills when finished.
+ */
+MemoryIdentityStorage.prototype.addCertificatePromise = function(certificate)
+{
+  var certificateName = certificate.getName();
+  var keyName = certificate.getPublicKeyName();
+
+  this.addKey(keyName, certificate.getPublicKeyInfo().getKeyType(),
+         certificate.getPublicKeyInfo().getKeyDer());
+
+  if (this.doesCertificateExist(certificateName))
+    return SyncPromise.resolve();
+
+  // Insert the certificate.
+  // wireEncode returns the cached encoding if available.
+  this.certificateStore[certificateName.toUri()] = certificate.wireEncode();
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Get a certificate from the identity storage.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @return {SyncPromise} A promise which returns the requested
+ * IdentityCertificate, or a promise rejected with SecurityException if the
+ * certificate doesn't exist.
+ */
+MemoryIdentityStorage.prototype.getCertificatePromise = function
+  (certificateName)
+{
+  var certificateNameUri = certificateName.toUri();
+  if (this.certificateStore[certificateNameUri] === undefined)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage::getCertificatePromise: The certificate does not exist")));
+
+  var certificate = new IdentityCertificate();
+  try {
+    certificate.wireDecode(this.certificateStore[certificateNameUri]);
+  } catch (ex) {
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage::getCertificatePromise: The certificate cannot be decoded")));
+  }
+  return SyncPromise.resolve(certificate);
+};
+
+/**
+ * Get the TPM locator associated with this storage.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise|SyncPromise} A promise which returns the TPM locator, or a
+ * promise rejected with SecurityException if the TPM locator doesn't exist.
+ */
+IdentityStorage.prototype.getTpmLocatorPromise = function(useSync)
+{
+  return SyncPromise.resolve("tpm-memory:");
+};
+
+/*****************************************
+ *           Get/Set Default             *
+ *****************************************/
+
+/**
+ * Get the default identity.
+ * @return {SyncPromise} A promise which returns the Name of default identity,
+ * or a promise rejected with SecurityException if the default identity is not
+ * set.
+ */
+MemoryIdentityStorage.prototype.getDefaultIdentityPromise = function()
+{
+  if (this.defaultIdentity.length === 0)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage.getDefaultIdentity: The default identity is not defined")));
+
+  return SyncPromise.resolve(new Name(this.defaultIdentity));
+};
+
+/**
+ * Get the default key name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @return {SyncPromise} A promise which returns the default key Name, or a
+ * promise rejected with SecurityException if the default key name for the
+ * identity is not set.
+ */
+MemoryIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
+  (identityName)
+{
+  var identityUri = identityName.toUri();
+  if (this.identityStore[identityUri] !== undefined) {
+    if (this.identityStore[identityUri].defaultKey != null)
+      return SyncPromise.resolve(this.identityStore[identityUri].defaultKey);
+    else
+      return SyncPromise.reject(new SecurityException(new Error
+        ("No default key set.")));
+  }
+  else
+    return SyncPromise.reject(new SecurityException(new Error("Identity not found.")));
+};
+
+/**
+ * Get the default certificate name for the specified key.
+ * @param {Name} keyName The key name.
+ * @return {SyncPromise} A promise which returns the default certificate Name,
+ * or a promise rejected with SecurityException if the default certificate name
+ * for the key name is not set.
+ */
+MemoryIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
+  (keyName)
+{
+  var keyUri = keyName.toUri();
+  if (this.keyStore[keyUri] !== undefined) {
+    if (this.keyStore[keyUri].defaultCertificate != null)
+      return SyncPromise.resolve(this.keyStore[keyUri].defaultCertificate);
+    else
+      return SyncPromise.reject(new SecurityException(new Error
+        ("No default certificate set.")));
+  }
+  else
+    return SyncPromise.reject(new SecurityException(new Error("Key not found.")));
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @return {SyncPromise} A promise which fulfills when the default identity is set.
+ */
+MemoryIdentityStorage.prototype.setDefaultIdentityPromise = function
+  (identityName)
+{
+  var identityUri = identityName.toUri();
+  if (this.identityStore[identityUri] !== undefined)
+    this.defaultIdentity = identityUri;
+  else
+    // The identity doesn't exist, so clear the default.
+    this.defaultIdentity = "";
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @return {SyncPromise} A promise which fulfills when the default key name is
+ * set.
+ */
+MemoryIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
+  (keyName, identityNameCheck)
+{
+  identityNameCheck = (identityNameCheck instanceof Name) ? identityNameCheck : null;
+
+  var identityName = keyName.getPrefix(-1);
+
+  if (identityNameCheck != null && identityNameCheck.size() > 0 &&
+      !identityNameCheck.equals(identityName))
+    return SyncPromise.reject(new SecurityException(new Error
+      ("The specified identity name does not match the key name")));
+
+  var identityUri = identityName.toUri();
+  if (this.identityStore[identityUri] !== undefined)
+    this.identityStore[identityUri].defaultKey = new Name(keyName);
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Set the default key name for the specified identity.
+ * @param {Name} keyName The key name.
+ * @param {Name} certificateName The certificate name.
+ * @return {SyncPromise} A promise which fulfills when the default certificate
+ * name is set.
+ */
+MemoryIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
+  (keyName, certificateName)
+{
+  var keyUri = keyName.toUri();
+  if (this.keyStore[keyUri] !== undefined)
+    this.keyStore[keyUri].defaultCertificate = new Name(certificateName);
+
+  return SyncPromise.resolve();
+};
+
+/*****************************************
+ *            Delete Methods             *
+ *****************************************/
+
+/**
+ * Delete a certificate.
+ * @param {Name} certificateName The certificate name.
+ * @return {SyncPromise} A promise which fulfills when the certificate
+ * info is deleted.
+ */
+MemoryIdentityStorage.prototype.deleteCertificateInfoPromise = function
+  (certificateName)
+{
+  return SyncPromise.reject(new Error
+    ("MemoryIdentityStorage.deleteCertificateInfoPromise is not implemented"));
+};
+
+/**
+ * Delete a public key and related certificates.
+ * @param {Name} keyName The key name.
+ * @return {SyncPromise} A promise which fulfills when the public key info is
+ * deleted.
+ */
+MemoryIdentityStorage.prototype.deletePublicKeyInfoPromise = function(keyName)
+{
+  return SyncPromise.reject(new Error
+    ("MemoryIdentityStorage.deletePublicKeyInfoPromise is not implemented"));
+};
+
+/**
+ * Delete an identity and related public keys and certificates.
+ * @param {Name} identity The identity name.
+ * @return {SyncPromise} A promise which fulfills when the identity info is
+ * deleted.
+ */
+MemoryIdentityStorage.prototype.deleteIdentityInfoPromise = function(identity)
+{
+  return SyncPromise.reject(new Error
+    ("MemoryIdentityStorage.deleteIdentityInfoPromise is not implemented"));
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode;
+
+/**
+ * PrivateKeyStorage is an abstract class which declares methods for working
+ * with a private key storage. You should use a subclass.
+ * @constructor
+ */
+var PrivateKeyStorage = function PrivateKeyStorage()
+{
+};
+
+exports.PrivateKeyStorage = PrivateKeyStorage;
+
+/**
+ * Generate a pair of asymmetric keys.
+ * @param {Name} keyName The name of the key pair.
+ * @param {KeyParams} params The parameters of the key.
+ * @param {boolean} (optional) useSync If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the pair is
+ * generated.
+ */
+PrivateKeyStorage.prototype.generateKeyPairPromise = function
+  (keyName, params, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("PrivateKeyStorage.generateKeyPairPromise is not implemented"));
+};
+
+/**
+ * Generate a pair of asymmetric keys.
+ * @param {Name} keyName The name of the key pair.
+ * @param {KeyParams} params The parameters of the key.
+ * @throws Error If generateKeyPairPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+PrivateKeyStorage.prototype.generateKeyPair = function(keyName, params)
+{
+  SyncPromise.getValue(this.generateKeyPairPromise(keyName, params, true));
+};
+
+/**
+ * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
+ * @param {Name} keyName The name of the key pair.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key pair is
+ * deleted.
+ */
+PrivateKeyStorage.prototype.deleteKeyPairPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("PrivateKeyStorage.deleteKeyPairPromise is not implemented"));
+};
+
+/**
+ * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
+ * @param {Name} keyName The name of the key pair.
+ * @throws Error If deleteKeyPairPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+PrivateKeyStorage.prototype.deleteKeyPair = function(keyName)
+{
+  SyncPromise.getValue(this.deleteKeyPairPromise(keyName, true));
+};
+
+/**
+ * Get the public key
+ * @param {Name} keyName The name of public key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the PublicKey.
+ */
+PrivateKeyStorage.prototype.getPublicKeyPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("PrivateKeyStorage.getPublicKeyPromise is not implemented"));
+};
+
+/**
+ * Get the public key
+ * @param {Name} keyName The name of public key.
+ * @return {PublicKey} The public key.
+ * @throws Error If getPublicKeyPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+PrivateKeyStorage.prototype.getPublicKey = function(keyName)
+{
+  return SyncPromise.getValue(this.getPublicKeyPromise(keyName, true));
+};
+
+/**
+ * Fetch the private key for keyName and sign the data to produce a signature Blob.
+ * @param {Buffer} data Pointer to the input byte array.
+ * @param {Name} keyName The name of the signing key.
+ * @param {number} digestAlgorithm (optional) The digest algorithm from
+ * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
+ * DigestAlgorithm.SHA256.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the signature Blob.
+ */
+PrivateKeyStorage.prototype.signPromise = function
+  (data, keyName, digestAlgorithm, useSync)
+{
+  return SyncPromise.reject(new Error("PrivateKeyStorage.sign is not implemented"));
+};
+
+/**
+ * Fetch the private key for keyName and sign the data to produce a signature Blob.
+ * @param {Buffer} data Pointer to the input byte array.
+ * @param {Name} keyName The name of the signing key.
+ * @param {number} digestAlgorithm (optional) The digest algorithm from
+ * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
+ * DigestAlgorithm.SHA256.
+ * @return {Blob} The signature Blob.
+ * @throws Error If signPromise doesn't return a SyncPromise which is already
+ * fulfilled.
+ */
+PrivateKeyStorage.prototype.sign = function(data, keyName, digestAlgorithm)
+{
+  return SyncPromise.getValue
+    (this.signPromise(data, keyName, digestAlgorithm, true));
+};
+
+/**
+ * Decrypt data.
+ * @param {Name} keyName The name of the decrypting key.
+ * @param {Buffer} data The byte to be decrypted.
+ * @param {boolean} isSymmetric (optional) If true symmetric encryption is used,
+ * otherwise asymmetric encryption is used. If omitted, use asymmetric
+ * encryption.
+ * @return {Blob} The decrypted data.
+ */
+PrivateKeyStorage.prototype.decrypt = function(keyName, data, isSymmetric)
+{
+  throw new Error("PrivateKeyStorage.decrypt is not implemented");
+};
+
+/**
+ * Encrypt data.
+ * @param {Name} keyName The name of the encrypting key.
+ * @param {Buffer} data The byte to be encrypted.
+ * @param {boolean} isSymmetric (optional) If true symmetric encryption is used,
+ * otherwise asymmetric encryption is used. If omitted, use asymmetric
+ * encryption.
+ * @return {Blob} The encrypted data.
+ */
+PrivateKeyStorage.prototype.encrypt = function(keyName, data, isSymmetric)
+{
+  throw new Error("PrivateKeyStorage.encrypt is not implemented");
+};
+
+/**
+ * @brief Generate a symmetric key.
+ * @param {Name} keyName The name of the key.
+ * @param {KeyParams} params The parameters of the key.
+ */
+PrivateKeyStorage.prototype.generateKey = function(keyName, params)
+{
+  throw new Error("PrivateKeyStorage.generateKey is not implemented");
+};
+
+/**
+ * Check if a particular key exists.
+ * @param {Name} keyName The name of the key.
+ * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
+ * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns true if the key exists.
+ */
+PrivateKeyStorage.prototype.doesKeyExistPromise = function
+  (keyName, keyClass, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("PrivateKeyStorage.doesKeyExist is not implemented"));
+};
+
+/**
+ * Check if a particular key exists.
+ * @param {Name} keyName The name of the key.
+ * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
+ * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
+ * @return {boolean} True if the key exists.
+ * @throws Error If doesKeyExistPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+PrivateKeyStorage.prototype.doesKeyExist = function(keyName, keyClass)
+{
+  return SyncPromise.getValue(this.doesKeyExistPromise(keyName, keyClass, true));
+};
+
+/**
+ * Encode the private key to a PKCS #8 private key. We do this explicitly here
+ * to avoid linking to extra OpenSSL libraries.
+ * @param {Buffer} privateKeyDer The input private key DER.
+ * @param {OID} oid The OID of the privateKey.
+ * @param {DerNode} parameters The DerNode of the parameters for the OID.
+ * @return {Blob} The PKCS #8 private key DER.
+ */
+PrivateKeyStorage.encodePkcs8PrivateKey = function
+  (privateKeyDer, oid, parameters)
+{
+  var algorithmIdentifier = new DerNode.DerSequence();
+  algorithmIdentifier.addChild(new DerNode.DerOid(oid));
+  algorithmIdentifier.addChild(parameters);
+
+  var result = new DerNode.DerSequence();
+  result.addChild(new DerNode.DerInteger(0));
+  result.addChild(algorithmIdentifier);
+  result.addChild(new DerNode.DerOctetString(privateKeyDer));
+
+  return result.encode();
+};
+
+/**
+ * Encode the RSAKey private key as a PKCS #1 private key.
+ * @param {RSAKey} rsaKey The RSAKey private key.
+ * @return {Blob} The PKCS #1 private key DER.
+ */
+PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey = function(rsaKey)
+{
+  // Imitate KJUR getEncryptedPKCS5PEMFromRSAKey.
+  var result = new DerNode.DerSequence();
+
+  result.addChild(new DerNode.DerInteger(0));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.n)));
+  result.addChild(new DerNode.DerInteger(rsaKey.e));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.d)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.p)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.q)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.dmp1)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.dmq1)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.coeff)));
+
+  return result.encode();
+};
+
+/**
+ * Encode the public key values in the RSAKey private key as a
+ * SubjectPublicKeyInfo.
+ * @param {RSAKey} rsaKey The RSAKey private key with the public key values.
+ * @return {Blob} The SubjectPublicKeyInfo DER.
+ */
+PrivateKeyStorage.encodePublicKeyFromRSAKey = function(rsaKey)
+{
+  var rsaPublicKey = new DerNode.DerSequence();
+
+  rsaPublicKey.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.n)));
+  rsaPublicKey.addChild(new DerNode.DerInteger(rsaKey.e));
+
+  var algorithmIdentifier = new DerNode.DerSequence();
+  algorithmIdentifier.addChild
+    (new DerNode.DerOid(new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID)));
+  algorithmIdentifier.addChild(new DerNode.DerNull());
+
+  var result = new DerNode.DerSequence();
+
+  result.addChild(algorithmIdentifier);
+  result.addChild(new DerNode.DerBitString(rsaPublicKey.encode().buf(), 0));
+
+  return result.encode();
+};
+
+/**
+ * Convert a BigInteger to a Buffer.
+ * @param {BigInteger} bigInteger The BigInteger.
+ * @return {Buffer} The Buffer.
+ */
+PrivateKeyStorage.bigIntegerToBuffer = function(bigInteger)
+{
+  // Imitate KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex.
+  var hex = bigInteger.toString(16);
+  if (hex.substr(0, 1) == "-")
+    throw new Error
+      ("PrivateKeyStorage.bigIntegerToBuffer: Negative integers are not currently supported");
+
+  if (hex.length % 2 == 1)
+    // Odd number of characters.
+    hex = "0" + hex;
+  else {
+    if (! hex.match(/^[0-7]/))
+      // The first byte is >= 0x80, so prepend a zero to keep it positive.
+      hex = "00" + hex;
+  }
+
+  return new Buffer(hex, 'hex');
+};
+
+PrivateKeyStorage.RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1";
+PrivateKeyStorage.EC_ENCRYPTION_OID = "1.2.840.10045.2.1";
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var PublicKey = require('../certificate/public-key.js').PublicKey; /** @ignore */
+var KeyClass = require('../security-types.js').KeyClass; /** @ignore */
+var KeyType = require('../security-types').KeyType; /** @ignore */
+var DigestAlgorithm = require('../security-types.js').DigestAlgorithm; /** @ignore */
+var DataUtils = require('../../encoding/data-utils.js').DataUtils; /** @ignore */
+var PrivateKeyStorage = require('./private-key-storage.js').PrivateKeyStorage; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var OID = require('../../encoding/oid.js').OID; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
+var rsaKeygen = null;
+try {
+  // This should be installed with: sudo npm install rsa-keygen
+  rsaKeygen = require('rsa-keygen');
+}
+catch (e) {}
+
+/**
+ * MemoryPrivateKeyStorage class extends PrivateKeyStorage to implement private
+ * key storage in memory.
+ * @constructor
+ */
+var MemoryPrivateKeyStorage = function MemoryPrivateKeyStorage()
+{
+  // Call the base constructor.
+  PrivateKeyStorage.call(this);
+
+  // The key is the keyName.toUri(). The value is security.certificate.PublicKey.
+  this.publicKeyStore = {};
+  // The key is the keyName.toUri(). The value is the object
+  //  {keyType,     // number from KeyType
+  //   privateKey   // The PEM-encoded private key.
+  //  }.
+  this.privateKeyStore = {};
+};
+
+MemoryPrivateKeyStorage.prototype = new PrivateKeyStorage();
+MemoryPrivateKeyStorage.prototype.name = "MemoryPrivateKeyStorage";
+
+exports.MemoryPrivateKeyStorage = MemoryPrivateKeyStorage;
+
+/**
+ * Set the public key for the keyName.
+ * @param {Name} keyName The key name.
+ * @param {number} keyType The KeyType, such as KeyType.RSA.
+ * @param {Buffer} publicKeyDer The public key DER byte array.
+ */
+MemoryPrivateKeyStorage.prototype.setPublicKeyForKeyName = function
+  (keyName, keyType, publicKeyDer)
+{
+  this.publicKeyStore[keyName.toUri()] = new PublicKey
+    (new Blob(publicKeyDer, true));
+};
+
+/**
+ * Set the private key for the keyName.
+ * @param {Name} keyName The key name.
+ * @param {number} keyType The KeyType, such as KeyType.RSA.
+ * @param {Buffer} privateKeyDer The private key DER byte array.
+ */
+MemoryPrivateKeyStorage.prototype.setPrivateKeyForKeyName = function
+  (keyName, keyType, privateKeyDer)
+{
+  // Encode the DER as PEM.
+  var keyBase64 = privateKeyDer.toString('base64');
+  var keyPem;
+  if (keyType === KeyType.RSA) {
+    keyPem = "-----BEGIN RSA PRIVATE KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END RSA PRIVATE KEY-----";
+  }
+  else if (keyType === KeyType.ECDSA) {
+    keyPem = "-----BEGIN EC PRIVATE KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END EC PRIVATE KEY-----";
+  }
+  else
+    throw new SecurityException(new Error
+      ("MemoryPrivateKeyStorage: KeyType is not supported"));
+
+  this.privateKeyStore[keyName.toUri()] =
+    { keyType: keyType, privateKey: keyPem };
+};
+
+/**
+ * Set the public and private key for the keyName.
+ * @param {Name} keyName The key name.
+ * @param {number} keyType The KeyType, such as KeyType.RSA.
+ * @param {Buffer} publicKeyDer The public key DER byte array.
+ * @param {Buffer} privateKeyDer The private key DER byte array.
+ */
+MemoryPrivateKeyStorage.prototype.setKeyPairForKeyName = function
+  (keyName, keyType, publicKeyDer, privateKeyDer)
+{
+  this.setPublicKeyForKeyName(keyName, keyType, publicKeyDer);
+  this.setPrivateKeyForKeyName(keyName, keyType, privateKeyDer);
+};
+
+/**
+ * Generate a pair of asymmetric keys.
+ * @param {Name} keyName The name of the key pair.
+ * @param {KeyParams} params The parameters of the key.
+ * @param {boolean} useSync (optional) If true then use blocking crypto and
+ * return a SyncPromise which is already fulfilled. If omitted or false, if
+ * possible use crypto.subtle and return an async Promise, otherwise use
+ * blocking crypto and return a SyncPromise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the pair is
+ * generated.
+ */
+MemoryPrivateKeyStorage.prototype.generateKeyPairPromise = function
+  (keyName, params, useSync)
+{
+  if (this.doesKeyExist(keyName, KeyClass.PUBLIC))
+    return SyncPromise.reject(new SecurityException(new Error
+      ("Public key already exists")));
+  if (this.doesKeyExist(keyName, KeyClass.PRIVATE))
+    return SyncPromise.reject(new SecurityException(new Error
+      ("Private key already exists")));
+
+  var thisStore = this;
+
+  if (UseSubtleCrypto() && !useSync) {
+    if (params.getKeyType() === KeyType.RSA) {
+      var privateKey = null;
+      var publicKeyDer = null;
+
+      return crypto.subtle.generateKey
+        ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
+           publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+           hash: {name: "SHA-256"} },
+         true, ["sign", "verify"])
+      .then(function(key) {
+        privateKey = key.privateKey;
+
+        // Export the public key to DER.
+        return crypto.subtle.exportKey("spki", key.publicKey);
+      })
+      .then(function(exportedPublicKey) {
+        publicKeyDer = new Blob(new Uint8Array(exportedPublicKey), false).buf();
+
+        // Export the private key to DER.
+        return crypto.subtle.exportKey("pkcs8", privateKey);
+      })
+      .then(function(pkcs8Der) {
+        // Crypto.subtle exports the private key as PKCS #8. Decode it to find
+        // the inner private key DER.
+        var parsedNode = DerNode.parse
+          (new Blob(new Uint8Array(pkcs8Der), false).buf());
+        // Get the value of the 3rd child which is the octet string.
+        var privateKeyDer = parsedNode.getChildren()[2].toVal();
+
+        // Save the key pair.
+        thisStore.setKeyPairForKeyName
+          (keyName, params.getKeyType(), publicKeyDer, privateKeyDer.buf());
+
+        // sign will use subtleKey directly.
+        thisStore.privateKeyStore[keyName.toUri()].subtleKey = privateKey;
+
+        return Promise.resolve();
+      });
+    }
+    else
+      return SyncPromise.reject(new SecurityException(new Error
+        ("Only RSA key generation currently supported")));
+  }
+  else {
+    return SyncPromise.resolve()
+    .then(function() {
+      if (typeof RSAKey !== 'undefined') {
+        // Assume we are in the browser.
+        if (params.getKeyType() === KeyType.RSA) {
+          var rsaKey = new RSAKey();
+          rsaKey.generate(params.getKeySize(), '010001');
+          thisStore.setKeyPairForKeyName
+            (keyName, params.getKeyType(),
+             PrivateKeyStorage.encodePublicKeyFromRSAKey(rsaKey).buf(),
+             PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey(rsaKey).buf());
         }
-    }
-    else
-        this.reconnectAndExpressInterest(interest, closure);
+        else
+          return SyncPromise.reject(new SecurityException(new Error
+            ("Only RSA key generation currently supported")));
+      }
+      else {
+        // Assume we are in Node.js.
+        var publicKeyDer;
+        var privateKeyPem;
+
+        if (params.getKeyType() === KeyType.RSA) {
+          if (!rsaKeygen)
+            return SyncPromise.reject(new SecurityException(new Error
+              ("Need to install rsa-keygen: sudo npm install rsa-keygen")));
+
+          var keyPair = rsaKeygen.generate(params.getKeySize());
+
+          // Get the public key DER from the PEM string.
+          var publicKeyBase64 = keyPair.public_key.toString().replace
+            ("-----BEGIN PUBLIC KEY-----", "").replace
+            ("-----END PUBLIC KEY-----", "");
+          publicKeyDer = new Buffer(publicKeyBase64, 'base64');
+
+          privateKeyPem = keyPair.private_key.toString();
+        }
+        else
+          return SyncPromise.reject(new SecurityException(new Error
+            ("Only RSA key generation currently supported")));
+
+        thisStore.setPublicKeyForKeyName(keyName, params.getKeyType(), publicKeyDer);
+        thisStore.privateKeyStore[keyName.toUri()] =
+          { keyType: params.getKeyType(), privateKey: privateKeyPem };
+      }
+
+      return SyncPromise.resolve();
+    });
+  }
 };
 
+/**
+ * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
+ * @param {Name} keyName The name of the key pair.
+ * @return {SyncPromise} A promise that fulfills when the key pair is deleted.
+ */
+MemoryPrivateKeyStorage.prototype.deleteKeyPairPromise = function(keyName)
+{
+  var keyUri = keyName.toUri();
+
+  delete this.publicKeyStore[keyUri];
+  delete this.privateKeyStore[keyUri];
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Get the public key
+ * @param {Name} keyName The name of public key.
+ * @return {SyncPromise} A promise that returns the PublicKey.
+ */
+MemoryPrivateKeyStorage.prototype.getPublicKeyPromise = function(keyName)
+{
+  var keyUri = keyName.toUri();
+  var publicKey = this.publicKeyStore[keyUri];
+  if (publicKey === undefined)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryPrivateKeyStorage: Cannot find public key " + keyName.toUri())));
+
+  return SyncPromise.resolve(publicKey);
+};
+
+/**
+ * Fetch the private key for keyName and sign the data to produce a signature Blob.
+ * @param {Buffer} data Pointer to the input byte array.
+ * @param {Name} keyName The name of the signing key.
+ * @param {number} digestAlgorithm (optional) The digest algorithm from
+ * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
+ * DigestAlgorithm.SHA256.
+ * @param {boolean} useSync (optional) If true then use blocking crypto and
+ * return a SyncPromise which is already fulfilled. If omitted or false, if
+ * possible use crypto.subtle and return an async Promise, otherwise use
+ * blocking crypto and return a SyncPromise.
+ * @return {Promise|SyncPromise} A promise that returns the signature Blob.
+ */
+MemoryPrivateKeyStorage.prototype.signPromise = function
+  (data, keyName, digestAlgorithm, useSync)
+{
+  useSync = (typeof digestAlgorithm === "boolean") ? digestAlgorithm : useSync;
+  digestAlgorithm = (typeof digestAlgorithm === "boolean" || !digestAlgorithm) ? DigestAlgorithm.SHA256 : digestAlgorithm;
+
+  if (digestAlgorithm != DigestAlgorithm.SHA256)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryPrivateKeyStorage.sign: Unsupported digest algorithm")));
+
+  // Find the private key.
+  var keyUri = keyName.toUri();
+  var privateKey = this.privateKeyStore[keyUri];
+  if (privateKey === undefined)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryPrivateKeyStorage: Cannot find private key " + keyUri)));
+
+  if (UseSubtleCrypto() && !useSync){
+    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};
+
+    if (!privateKey.subtleKey){
+      //this is the first time in the session that we're using crypto subtle with this key
+      //so we have to convert to pkcs8 and import it.
+      //assigning it to privateKey.subtleKey means we only have to do this once per session,
+      //giving us a small, but not insignificant, performance boost.
+      var privateDER = DataUtils.privateKeyPemToDer(privateKey.privateKey);
+      var pkcs8 = PrivateKeyStorage.encodePkcs8PrivateKey
+        (privateDER, new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),
+         new DerNode.DerNull()).buf();
+
+      var promise = crypto.subtle.importKey("pkcs8", pkcs8.buffer, algo, true, ["sign"]).then(function(subtleKey){
+        //cache the crypto.subtle key object
+        privateKey.subtleKey = subtleKey;
+        return crypto.subtle.sign(algo, subtleKey, data);
+      });
+    } else {
+      // The crypto.subtle key has been cached on a previous sign or from keygen.
+      var promise = crypto.subtle.sign(algo, privateKey.subtleKey, data);
+    }
+
+    return promise.then(function(signature){
+      var result = new Blob(new Uint8Array(signature), true);
+      return Promise.resolve(result);
+    });
+  } else {
+    var signer;
+    if (privateKey.keyType === KeyType.RSA)
+      signer = Crypto.createSign("RSA-SHA256");
+    else if (privateKey.keyType === KeyType.ECDSA)
+      // Just create a "sha256". The Crypto library will infer ECDSA from the key.
+      signer = Crypto.createSign("sha256");
+    else
+      // We don't expect this to happen since setPrivateKeyForKeyName already checked.
+      return SyncPromise.reject(new SecurityException(new Error
+        ("MemoryPrivateKeyStorage.sign: Unrecognized private key type")));
+
+    signer.update(data);
+    var signature = new Buffer
+      (DataUtils.toNumbersIfString(signer.sign(privateKey.privateKey)));
+    var result = new Blob(signature, false);
+
+    return SyncPromise.resolve(result);
+  }
+};
+
+/**
+ * Check if a particular key exists.
+ * @param {Name} keyName The name of the key.
+ * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
+ * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
+ * @return {SyncPromise} A promise which returns true if the key exists.
+ */
+MemoryPrivateKeyStorage.prototype.doesKeyExistPromise = function
+  (keyName, keyClass)
+{
+  var keyUri = keyName.toUri();
+  var result = false;
+  if (keyClass == KeyClass.PUBLIC)
+    result = this.publicKeyStore[keyUri] !== undefined;
+  else if (keyClass == KeyClass.PRIVATE)
+    result = this.privateKeyStore[keyUri] !== undefined;
+
+  return SyncPromise.resolve(result);
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+var Crypto = require('../../crypto.js');
+// Don't require other modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbPrivateKeyStorage extends PrivateKeyStorage to implement private key
+ * storage using the browser's IndexedDB service.
+ * @constructor
+ */
+var IndexedDbPrivateKeyStorage = function IndexedDbPrivateKeyStorage()
+{
+  PrivateKeyStorage.call(this);
+
+  this.database = new Dexie("ndnsec-tpm");
+  this.database.version(1).stores({
+    // "nameHash" is transformName(keyName) // string
+    // "encoding" is the public key DER     // Uint8Array
+    publicKey: "nameHash",
+
+    // "nameHash" is transformName(keyName)     // string
+    // "encoding" is the PKCS 8 private key DER // Uint8Array
+    privateKey: "nameHash"
+  });
+  this.database.open();
+};
+
+IndexedDbPrivateKeyStorage.prototype = new PrivateKeyStorage();
+IndexedDbPrivateKeyStorage.prototype.name = "IndexedDbPrivateKeyStorage";
+
+/**
+ * Generate a pair of asymmetric keys.
+ * @param {Name} keyName The name of the key pair.
+ * @param {KeyParams} params The parameters of the key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the pair is generated.
+ */
+IndexedDbPrivateKeyStorage.prototype.generateKeyPairPromise = function
+  (keyName, params, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.generateKeyPairPromise is only supported for async")));
+
+  var thisStorage = this;
+
+  return thisStorage.doesKeyExistPromise(keyName, KeyClass.PUBLIC)
+  .then(function(exists) {
+    if (exists)
+      throw new Error("Public key already exists");
+
+    return thisStorage.doesKeyExistPromise(keyName, KeyClass.PRIVATE);
+  })
+  .then(function(exists) {
+    if (exists)
+      throw new Error("Private key already exists");
+
+    if (params.getKeyType() === KeyType.RSA) {
+      var privateKey = null;
+      var publicKeyDer = null;
+
+      return crypto.subtle.generateKey
+        ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
+           publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+           hash: {name: "SHA-256"} },
+         true, ["sign", "verify"])
+      .then(function(key) {
+        privateKey = key.privateKey;
+
+        // Export the public key to DER.
+        return crypto.subtle.exportKey("spki", key.publicKey);
+      })
+      .then(function(exportedPublicKey) {
+        publicKeyDer = new Uint8Array(exportedPublicKey);
+
+        // Export the private key to DER.
+        return crypto.subtle.exportKey("pkcs8", privateKey);
+      })
+      .then(function(pkcs8Der) {
+        // Save the key pair
+        return thisStorage.database.transaction
+          ("rw", thisStorage.database.privateKey, thisStorage.database.publicKey, function () {
+            thisStorage.database.publicKey.put
+              ({nameHash: IndexedDbPrivateKeyStorage.transformName(keyName),
+                encoding: publicKeyDer});
+            thisStorage.database.privateKey.put
+              ({nameHash: IndexedDbPrivateKeyStorage.transformName(keyName),
+                encoding: new Uint8Array(pkcs8Der)});
+          });
+      });
+    }
+    else
+      throw new Error("Only RSA key generation currently supported");
+  });
+};
+
+
+/**
+ * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
+ * @param {Name} keyName The name of the key pair.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key pair is deleted.
+ */
+IndexedDbPrivateKeyStorage.prototype.deleteKeyPairPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.deleteKeyPairPromise is only supported for async")));
+
+  var thisStorage = this;
+  // delete does nothing if the key doesn't exist.
+  return this.database.publicKey.delete
+    (IndexedDbPrivateKeyStorage.transformName(keyName))
+  .then(function() {
+    return thisStorage.database.privateKey.delete
+      (IndexedDbPrivateKeyStorage.transformName(keyName));
+  });
+};
+
+/**
+ * Get the public key
+ * @param {Name} keyName The name of public key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns the PublicKey.
+ */
+IndexedDbPrivateKeyStorage.prototype.getPublicKeyPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.getPublicKeyPromise is only supported for async")));
+
+  return this.database.publicKey.get
+    (IndexedDbPrivateKeyStorage.transformName(keyName))
+  .then(function(publicKeyEntry) {
+    return Promise.resolve(new PublicKey(new Blob(publicKeyEntry.encoding)));
+  });
+};
+
+/**
+ * Fetch the private key for keyName and sign the data to produce a signature Blob.
+ * @param {Buffer} data Pointer to the input byte array.
+ * @param {Name} keyName The name of the signing key.
+ * @param {number} digestAlgorithm (optional) The digest algorithm from
+ * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
+ * DigestAlgorithm.SHA256.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns the signature Blob.
+ */
+IndexedDbPrivateKeyStorage.prototype.signPromise = function
+  (data, keyName, digestAlgorithm, useSync)
+{
+  useSync = (typeof digestAlgorithm === "boolean") ? digestAlgorithm : useSync;
+  digestAlgorithm = (typeof digestAlgorithm === "boolean" || !digestAlgorithm) ? DigestAlgorithm.SHA256 : digestAlgorithm;
+
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.signPromise is only supported for async")));
+
+  if (digestAlgorithm != DigestAlgorithm.SHA256)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.sign: Unsupported digest algorithm")));
+
+  // TODO: Support non-RSA keys.
+  var algo = { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256" }};
+
+  // Find the private key.
+  return this.database.privateKey.get
+    (IndexedDbPrivateKeyStorage.transformName(keyName))
+  .then(function(privateKeyEntry) {
+    return crypto.subtle.importKey
+      ("pkcs8", new Blob(privateKeyEntry.encoding).buf(), algo, true, ["sign"]);
+  })
+  .then(function(privateKey) {
+    return crypto.subtle.sign(algo, privateKey, data);
+  })
+  .then(function(signature) {
+    return Promise.resolve(new Blob(new Uint8Array(signature), true));
+  });
+};
+
+/**
+ * Check if a particular key exists.
+ * @param {Name} keyName The name of the key.
+ * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
+ * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns true if the key exists.
+ */
+IndexedDbPrivateKeyStorage.prototype.doesKeyExistPromise = function
+  (keyName, keyClass, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.doesKeyExistPromise is only supported for async")));
+
+  var table = null;
+  if (keyClass == KeyClass.PUBLIC)
+    table = this.database.publicKey;
+  else if (keyClass == KeyClass.PRIVATE)
+    table = this.database.privateKey;
+  else
+    // Silently say that anything else doesn't exist.
+    return Promise.resolve(false);
+
+  return table.where("nameHash").equals
+    (IndexedDbPrivateKeyStorage.transformName(keyName))
+  .count()
+  .then(function(count) {
+    return Promise.resolve(count > 0);
+  });
+};
+
+/**
+ * Transform the key name into the base64 encoding of the hash (the same as in
+ * FilePrivateKeyStorage without the file name extension).
+ */
+IndexedDbPrivateKeyStorage.transformName = function(keyName)
+{
+  var hash = Crypto.createHash('sha256');
+  hash.update(new Buffer(keyName.toUri()));
+  var fileName = hash.digest('base64');
+  return fileName.replace(/\//g, '%');
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var ConfigFile = require('../../util/config-file.js').ConfigFile; /** @ignore */
+var DigestSha256Signature = require('../../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
+var Sha256WithRsaSignature = require('../../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var Sha256WithEcdsaSignature = require('../../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
+var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var DigestAlgorithm = require('../security-types.js').DigestAlgorithm; /** @ignore */
+var KeyType = require('../security-types.js').KeyType; /** @ignore */
+var RsaKeyParams = require('../key-params.js').RsaKeyParams; /** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var PublicKey = require('../certificate/public-key.js').PublicKey; /** @ignore */
+var CertificateSubjectDescription = require('../certificate/certificate-subject-description.js').CertificateSubjectDescription; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var BasicIdentityStorage = require('./basic-identity-storage.js').BasicIdentityStorage; /** @ignore */
+var FilePrivateKeyStorage = require('./file-private-key-storage.js').FilePrivateKeyStorage;
+
+/**
+ * An IdentityManager is the interface of operations related to identity, keys,
+ * and certificates.
+ *
+ * Create a new IdentityManager to use the IdentityStorage and
+ * PrivateKeyStorage.
+ * @param {IdentityStorage} identityStorage An object of a subclass of
+ * IdentityStorage. In Node.js, if this is omitted then use BasicIdentityStorage.
+ * @param {PrivateKeyStorage} privateKeyStorage An object of a subclass of
+ * PrivateKeyStorage. In Node.js, if this is omitted then use the default
+ * PrivateKeyStorage for your system, which is FilePrivateKeyStorage for any
+ * system other than OS X. (OS X key chain storage is not yet implemented, so
+ * you must supply a different PrivateKeyStorage.)
+ * @throws SecurityException if this is not in Node.js and identityStorage or
+ * privateKeyStorage is omitted.
+ * @constructor
+ */
+var IdentityManager = function IdentityManager
+  (identityStorage, privateKeyStorage)
+{
+  if (privateKeyStorage) {
+    // Don't call checkTpm() when using a custom PrivateKeyStorage.
+    if (!identityStorage)
+        // We don't expect this to happen.
+        throw new Error
+          ("IdentityManager: A custom privateKeyStorage is supplied with a null identityStorage")
+
+    this.identityStorage = identityStorage;
+    this.privateKeyStorage = privateKeyStorage;
+  }
+  else {
+    if (!ConfigFile)
+      // Assume we are in the browser.
+      throw new SecurityException(new Error
+        ("IdentityManager: If not in Node.js then you must supply identityStorage and privateKeyStorage."));
+    var config = new ConfigFile();
+
+    var canonicalTpmLocator = [null];
+    var thisStorage = this;
+    // Make the function that BasicIdentityStorage will call the first time it
+    // is used. It has to be an async promise becuase getTpmLocatorPromise is async.
+    function initialCheckPromise() 
+    {
+      return thisStorage.checkTpmPromise_(canonicalTpmLocator[0]);
+    }
+
+    this.identityStorage = identityStorage ? identityStorage
+      : IdentityManager.getDefaultIdentityStorage_(config, initialCheckPromise);
+    this.privateKeyStorage = IdentityManager.getDefaultPrivateKeyStorage_
+      (config, canonicalTpmLocator);
+  }
+};
+
+exports.IdentityManager = IdentityManager;
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @param {Name} identityName The name of the identity.
+ * @params {KeyParams} params The key parameters if a key needs to be generated
+ * for the identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the name of the default
+ * certificate of the identity.
+ */
+IdentityManager.prototype.createIdentityAndCertificatePromise = function
+  (identityName, params, useSync)
+{
+  var thisManager = this;
+  var generateKey = true;
+  var keyName = null;
+
+  return this.identityStorage.addIdentityPromise(identityName, useSync)
+  .then(function() {
+    return thisManager.identityStorage.getDefaultKeyNameForIdentityPromise
+      (identityName, useSync)
+    .then(function(localKeyName) {
+      keyName = localKeyName;
+
+      // Set generateKey.
+      return thisManager.identityStorage.getKeyPromise(keyName, useSync)
+      .then(function(publicKeyDer) {
+        var key = new PublicKey(publicKeyDer);
+        if (key.getKeyType() == params.getKeyType())
+          // The key exists and has the same type, so don't need to generate one.
+          generateKey = false;
+        return SyncPromise.resolve();
+      });
+    }, function(err) {
+      if (!(err instanceof SecurityException))
+        throw err;
+
+      // The key doesn't exist, so leave generateKey true.
+      return SyncPromise.resolve();
+    });
+  })
+  .then(function() {
+    if (generateKey)
+      return thisManager.generateKeyPairPromise(identityName, true, params, useSync)
+      .then(function(localKeyName) {
+        keyName = localKeyName;
+        return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
+          (keyName, useSync);
+      });
+    else
+      // Don't generate a key pair. Use the existing keyName.
+      return SyncPromise.resolve();
+  })
+  .then(function() {
+    return thisManager.identityStorage.getDefaultCertificateNameForKeyPromise
+      (keyName, useSync)
+    .then(function(certName) {
+      // The cert exists, so don't need to make it.
+      return SyncPromise.resolve(certName);
+    }, function(err) {
+      if (!(err instanceof SecurityException))
+        throw err;
+
+      // The cert doesn't exist, so make one.
+      var certName;
+      return thisManager.selfSignPromise(keyName, useSync)
+      .then(function(selfCert) {
+        certName = selfCert.getName();
+        return thisManager.addCertificateAsIdentityDefaultPromise(selfCert, useSync);
+      })
+      .then(function() {
+        return SyncPromise.resolve(certName);
+      });
+    });
+  });
+};
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @param {Name} identityName The name of the identity.
+ * @params {KeyParams} params The key parameters if a key needs to be generated
+ * for the identity.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with the name of the default certificate of the identity. If omitted, the
+ * return value is described below. (Some crypto libraries only use a callback,
+ * so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some crypto libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the name of the default
+ * certificate of the identity. Otherwise, if onComplete is supplied then return
+ * undefined and use onComplete as described above.
+ */
+IdentityManager.prototype.createIdentityAndCertificate = function
+  (identityName, params, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.createIdentityAndCertificatePromise(identityName, params, !onComplete));
+};
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @deprecated Use createIdentityAndCertificate which returns the
+ * certificate name instead of the key name. You can use
+ * IdentityCertificate.certificateNameToPublicKeyName to convert the
+ * certificate name to the key name.
+ * @param {Name} identityName The name of the identity.
+ * @params {KeyParams} params The key parameters if a key needs to be generated
+ * for the identity.
+ * @return {Name} The key name of the auto-generated KSK of the identity.
+ */
+IdentityManager.prototype.createIdentity = function(identityName, params)
+{
+  return IdentityCertificate.certificateNameToPublicKeyName
+    (this.createIdentityAndCertificate(identityName, params));
+};
+
+/**
+ * Delete the identity from the public and private key storage. If the
+ * identity to be deleted is the current default system default, this will not
+ * delete the identity and will return immediately.
+ * @param {Name} identityName The name of the identity.
+ * @param {function} onComplete (optional) This calls onComplete() when the
+ * operation is complete. If omitted, do not use it. (Some database libraries
+ * only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.deleteIdentity = function
+  (identityName, onComplete, onError)
+{
+  var useSync = !onComplete;
+  var thisManager = this;
+
+  var doDelete = true;
+
+  var mainPromise = this.identityStorage.getDefaultIdentityPromise(useSync)
+  .then(function(defaultIdentityName) {
+    if (defaultIdentityName.equals(identityName))
+      // Don't delete the default identity!
+      doDelete = false;
+
+    return SyncPromise.resolve();
+  }, function(err) {
+    // There is no default identity to check.
+    return SyncPromise.resolve();
+  })
+  .then(function() {
+    if (!doDelete)
+      return SyncPromise.resolve();
+
+    var keysToDelete = [];
+    return thisManager.identityStorage.getAllKeyNamesOfIdentityPromise
+      (identityName, keysToDelete, true)
+    .then(function() {
+      return thisManager.identityStorage.getAllKeyNamesOfIdentityPromise
+        (identityName, keysToDelete, false);
+    })
+    .then(function() {
+      return thisManager.identityStorage.deleteIdentityInfoPromise(identityName);
+    })
+    .then(function() {
+      // Recursively loop through keysToDelete, calling deleteKeyPairPromise.
+      function deleteKeyLoop(i) {
+        if (i >= keysToDelete.length)
+          return SyncPromise.resolve();
+
+        return thisManager.privateKeyStorage.deleteKeyPairPromise(keysToDelete[i])
+        .then(function() {
+          return deleteKeyLoop(i + 1);
+        });
+      }
+
+      return deleteKeyLoop(0);
+    });
+  });
+
+  return SyncPromise.complete(onComplete, onError, mainPromise);
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default
+ * identity is set.
+ */
+IdentityManager.prototype.setDefaultIdentityPromise = function
+  (identityName, useSync)
+{
+  return this.identityStorage.setDefaultIdentityPromise(identityName, useSync);
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.setDefaultIdentity = function
+  (identityName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.setDefaultIdentityPromise(identityName, !onComplete));
+};
+
+/**
+ * Get the default identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the Name of default
+ * identity, or a promise rejected with SecurityException if the default
+ * identity is not set.
+ */
+IdentityManager.prototype.getDefaultIdentityPromise = function(useSync)
+{
+  return this.identityStorage.getDefaultIdentityPromise(useSync);
+};
+
+/**
+ * Get the default identity.
+ * @param {function} onComplete (optional) This calls onComplete(identityName)
+ * with name of the default identity. If omitted, the return value is described
+ * below. (Some database libraries only use a callback, so onComplete is required
+ * to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the name of the default
+ * identity. Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * @throws SecurityException if the default identity is not set. However, if
+ * onComplete and onError are defined, then if there is an exception return
+ * undefined and call onError(exception).
+ */
+IdentityManager.prototype.getDefaultIdentity = function(onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getDefaultIdentityPromise(!onComplete));
+};
+
+/**
+ * Get the certificate of the default identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the requested
+ * IdentityCertificate or null if not found.
+ */
+IdentityManager.prototype.getDefaultCertificatePromise = function(useSync)
+{
+  return this.identityStorage.getDefaultCertificatePromise(useSync);
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
+ * a Data-Signing-Key (DSK).
+ * @param {number} keySize The size of the key.
+ * @return {Name} The generated key name.
+ */
+IdentityManager.prototype.generateRSAKeyPair = function
+  (identityName, isKsk, keySize)
+{
+  // For now, require sync. This method may be removed from the API.
+  return SyncPromise.getValue
+    (this.generateKeyPairPromise
+     (identityName, isKsk, new RsaKeyParams(keySize), true));
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.setDefaultKeyForIdentity = function
+  (keyName, identityNameCheck, onComplete, onError)
+{
+  onError = (typeof identityNameCheck === "function") ? onComplete : onError;
+  onComplete = (typeof identityNameCheck === "function") ?
+    identityNameCheck : onComplete;
+  identityNameCheck = (typeof identityNameCheck === "function" || !identityNameCheck) ?
+    new Name() : identityNameCheck;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.setDefaultKeyNameForIdentityPromise
+      (keyName, identityNameCheck, !onComplete));
+};
+
+/**
+ * Get the default key for an identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {function} onComplete (optional) This calls onComplete(keyName)
+ * with name of the default key. If omitted, the return value is described
+ * below. (Some database libraries only use a callback, so onComplete is required
+ * to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the default key name.
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete
+ * as described above.
+ * @throws SecurityException if the default key name for the identity is not set.
+ * However, if onComplete and onError are defined, then if there is an exception
+ * return undefined and call onError(exception).
+ */
+IdentityManager.prototype.getDefaultKeyNameForIdentity = function
+  (identityName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getDefaultKeyNameForIdentityPromise
+      (identityName, !onComplete));
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity and set it as default
+ * key for the identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
+ * a Data-Signing-Key (DSK).
+ * @param {number} keySize The size of the key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which returns the generated key name.
+ */
+IdentityManager.prototype.generateRSAKeyPairAsDefaultPromise = function
+  (identityName, isKsk, keySize, useSync)
+{
+  var newKeyName;
+  var thisManager = this;
+  return this.generateKeyPairPromise(identityName, isKsk, new RsaKeyParams(keySize))
+  .then(function(localKeyName) {
+    newKeyName = localKeyName;
+
+    return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
+      (newKeyName);
+  })
+  .then(function() {
+    return SyncPromise.resolve(newKeyName);
+  });
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity and set it as default
+ * key for the identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
+ * a Data-Signing-Key (DSK).
+ * @param {number} keySize The size of the key.
+ * @return {Name} The generated key name.
+ */
+IdentityManager.prototype.generateRSAKeyPairAsDefault = function
+  (identityName, isKsk, keySize)
+{
+  return SyncPromise.getValue
+    (this.generateRSAKeyPairAsDefaultPromise(identityName, isKsk, keySize, true));
+};
+
+/**
+ * Get the public key with the specified name.
+ * @param {Name} keyName The name of the key.
+ * @param {function} onComplete (optional) This calls onComplete(publicKey)
+ * with PublicKey. If omitted, the return value is described below. (Some database
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {PublicKey} If onComplete is omitted, return the public key.
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete
+ * as described above.
+ */
+IdentityManager.prototype.getPublicKey = function(keyName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getKeyPromise(keyName, !onComplete)
+    .then(function(keyDer) {
+      return SyncPromise.resolve(new PublicKey(keyDer));
+    }));
+};
+
+// TODO: Add two versions of createIdentityCertificate.
+
+/**
+ * Prepare an unsigned identity certificate.
+ * @param {Name} keyName The key name, e.g., `/{identity_name}/ksk-123456`.
+ * @param {PublicKey} publicKey (optional) The public key to sign. If ommited,
+ * use the keyName to get the public key from the identity storage.
+ * @param {Name} signingIdentity The signing identity.
+ * @param {number} notBefore See IdentityCertificate.
+ * @param {number} notAfter See IdentityCertificate.
+ * @param {Array<CertificateSubjectDescription>} subjectDescription A list of
+ * CertificateSubjectDescription. See IdentityCertificate. If null or empty,
+ * this adds a an ATTRIBUTE_NAME based on the keyName.
+ * @param {Name} certPrefix (optional) The prefix before the `KEY` component. If
+ * null or omitted, this infers the certificate name according to the relation
+ * between the signingIdentity and the subject identity. If the signingIdentity
+ * is a prefix of the subject identity, `KEY` will be inserted after the
+ * signingIdentity, otherwise `KEY` is inserted after subject identity (i.e.,
+ * before `ksk-...`).
+ * @param {function} onComplete (optional) This calls onComplete(certificate)
+ * with the unsigned IdentityCertificate, or null if the inputs are invalid. If
+ * omitted, the return value is described below. (Some database libraries only
+ * use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {IdentityCertificate} If onComplete is omitted, return the the
+ * unsigned IdentityCertificate, or null if the inputs are invalid. Otherwise,
+ * if onComplete is supplied then return undefined and use onComplete as
+ * described above.
+ */
+IdentityManager.prototype.prepareUnsignedIdentityCertificate = function
+  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
+   certPrefix, onComplete, onError)
+{
+  if (!(publicKey instanceof PublicKey)) {
+    // The publicKey was omitted. Shift arguments.
+    onError = onComplete;
+    onComplete = certPrefix;
+    certPrefix = subjectDescription;
+    subjectDescription = notAfter;
+    notAfter = notBefore;
+    notBefore = signingIdentity;
+    signingIdentity = publicKey;
+    publicKey = null;
+  }
+
+  // certPrefix may be omitted or null, so check for it and the following args.
+  var arg7 = certPrefix;
+  var arg8 = onComplete;
+  var arg9 = onError;
+  if (arg7 instanceof Name)
+    certPrefix = arg7;
+  else
+    certPrefix = null;
+
+  if (typeof arg7 === 'function') {
+    onComplete = arg7;
+    onError = arg8;
+  }
+  else if (typeof arg8 === 'function') {
+    onComplete = arg8;
+    onError = arg9;
+  }
+  else {
+    onComplete = null;
+    onError = null;
+  }
+
+  var promise;
+  if (publicKey == null)
+    promise =  this.prepareUnsignedIdentityCertificatePromise
+      (keyName, signingIdentity, notBefore, notAfter, subjectDescription,
+       certPrefix, !onComplete);
+  else
+    promise =  this.prepareUnsignedIdentityCertificatePromise
+      (keyName, publicKey, signingIdentity, notBefore, notAfter,
+       subjectDescription, certPrefix, !onComplete);
+  return SyncPromise.complete(onComplete, onError, promise);
+};
+
+/**
+ * Prepare an unsigned identity certificate.
+ * @param {Name} keyName The key name, e.g., `/{identity_name}/ksk-123456`.
+ * @param {PublicKey} publicKey (optional) The public key to sign. If ommited,
+ * use the keyName to get the public key from the identity storage.
+ * @param {Name} signingIdentity The signing identity.
+ * @param {number} notBefore See IdentityCertificate.
+ * @param {number} notAfter See IdentityCertificate.
+ * @param {Array<CertificateSubjectDescription>} subjectDescription A list of
+ * CertificateSubjectDescription. See IdentityCertificate. If null or empty,
+ * this adds a an ATTRIBUTE_NAME based on the keyName.
+ * @param {Name} certPrefix (optional) The prefix before the `KEY` component. If
+ * null or omitted, this infers the certificate name according to the relation
+ * between the signingIdentity and the subject identity. If the signingIdentity
+ * is a prefix of the subject identity, `KEY` will be inserted after the
+ * signingIdentity, otherwise `KEY` is inserted after subject identity (i.e.,
+ * before `ksk-...`).
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the unsigned
+ * IdentityCertificate, or that returns null if the inputs are invalid.
+ */
+IdentityManager.prototype.prepareUnsignedIdentityCertificatePromise = function
+  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
+   certPrefix, useSync)
+{
+  if (!(publicKey instanceof PublicKey)) {
+    // The publicKey was omitted. Shift arguments.
+    useSync = certPrefix;
+    certPrefix = subjectDescription;
+    subjectDescription = notAfter;
+    notAfter = notBefore;
+    notBefore = signingIdentity;
+    signingIdentity = publicKey;
+    publicKey = null;
+  }
+
+  // certPrefix may be omitted or null, so check for it and the following arg.
+  var arg7 = certPrefix;
+  var arg8 = useSync;
+  if (arg7 instanceof Name)
+    certPrefix = arg7;
+  else
+    certPrefix = null;
+
+  if (typeof arg7 === 'boolean')
+    useSync = arg7;
+  else if (typeof arg8 === 'boolean')
+    useSync = arg8;
+  else
+    useSync = false;
+
+  var promise;
+  if (publicKey == null) {
+    promise = this.identityStorage.getKeyPromise(keyName, useSync)
+    .then(function(keyDer) {
+      publicKey = new PublicKey(keyDer);
+      return SyncPromise.resolve();
+    });
+  }
+  else
+    promise = SyncPromise.resolve();
+
+  return promise
+  .then(function() {
+    return SyncPromise.resolve
+      (IdentityManager.prepareUnsignedIdentityCertificateHelper_
+       (keyName, publicKey, signingIdentity, notBefore, notAfter,
+        subjectDescription, certPrefix));
+  });
+};
+
+/**
+ * A helper for prepareUnsignedIdentityCertificatePromise where the publicKey
+ * is known.
+ */
+IdentityManager.prepareUnsignedIdentityCertificateHelper_ = function
+  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
+   certPrefix)
+{
+  if (keyName.size() < 1)
+    return null;
+
+  var tempKeyIdPrefix = keyName.get(-1).toEscapedString();
+  if (tempKeyIdPrefix.length < 4)
+    return null;
+  keyIdPrefix = tempKeyIdPrefix.substr(0, 4);
+  if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
+    return null;
+
+  var certificate = new IdentityCertificate();
+  var certName = new Name();
+
+  if (certPrefix == null) {
+    // No certificate prefix hint, so infer the prefix.
+    if (signingIdentity.match(keyName))
+      certName.append(signingIdentity)
+        .append("KEY")
+        .append(keyName.getSubName(signingIdentity.size()))
+        .append("ID-CERT")
+        .appendVersion(new Date().getTime());
+    else
+      certName.append(keyName.getPrefix(-1))
+        .append("KEY")
+        .append(keyName.get(-1))
+        .append("ID-CERT")
+        .appendVersion(new Date().getTime());
+  }
+  else {
+    // A cert prefix hint is supplied, so determine the cert name.
+    if (certPrefix.match(keyName) && !certPrefix.equals(keyName))
+      certName.append(certPrefix)
+        .append("KEY")
+        .append(keyName.getSubName(certPrefix.size()))
+        .append("ID-CERT")
+        .appendVersion(new Date().getTime());
+    else
+      return null;
+  }
+
+  certificate.setName(certName);
+  certificate.setNotBefore(notBefore);
+  certificate.setNotAfter(notAfter);
+  certificate.setPublicKeyInfo(publicKey);
+
+  if (subjectDescription == null || subjectDescription.length === 0)
+    certificate.addSubjectDescription(new CertificateSubjectDescription
+      ("2.5.4.41", keyName.getPrefix(-1).toUri()));
+  else {
+    for (var i = 0; i < subjectDescription.length; ++i)
+      certificate.addSubjectDescription(subjectDescription[i]);
+  }
+
+  try {
+    certificate.encode();
+  } catch (ex) {
+    throw SecurityException(new Error("DerEncodingException: " + ex));
+  }
+
+  return certificate;
+};
+
+/**
+ * Add a certificate into the public key identity storage.
+ * @param {IdentityCertificate} certificate The certificate to to added. This
+ * makes a copy of the certificate.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.addCertificate = function
+  (certificate, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.addCertificatePromise(certificate, !onComplete));
+};
+
+/**
+ * Set the certificate as the default for its corresponding key.
+ * @param {IdentityCertificate} certificate The certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default
+ * certificate is set.
+ */
+IdentityManager.prototype.setDefaultCertificateForKeyPromise = function
+  (certificate, useSync)
+{
+  var thisManager = this;
+
+  var keyName = certificate.getPublicKeyName();
+  return this.identityStorage.doesKeyExistPromise(keyName, useSync)
+  .then(function(exists) {
+    if (!exists)
+      throw new SecurityException(new Error
+        ("No corresponding Key record for certificate!"));
+
+    return thisManager.identityStorage.setDefaultCertificateNameForKeyPromise
+      (keyName, certificate.getName(), useSync);
+  });
+};
+
+/**
+ * Set the certificate as the default for its corresponding key.
+ * @param {IdentityCertificate} certificate The certificate.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.setDefaultCertificateForKey = function
+  (certificate, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.setDefaultCertificateForKeyPromise(certificate, !onComplete));
+};
+
+/**
+ * Add a certificate into the public key identity storage and set the
+ * certificate as the default for its corresponding identity.
+ * @param {IdentityCertificate} certificate The certificate to be added. This
+ * makes a copy of the certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the certificate
+ * is added.
+ */
+IdentityManager.prototype.addCertificateAsIdentityDefaultPromise = function
+  (certificate, useSync)
+{
+  var thisManager = this;
+  return this.identityStorage.addCertificatePromise(certificate, useSync)
+  .then(function() {
+    var keyName = certificate.getPublicKeyName();
+    return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
+      (keyName, useSync);
+  })
+  .then(function() {
+    return thisManager.setDefaultCertificateForKeyPromise(certificate, useSync);
+  });
+};
+
+/**
+ * Add a certificate into the public key identity storage and set the
+ * certificate as the default of its corresponding key.
+ * @param {IdentityCertificate} certificate The certificate to be added. This
+ * makes a copy of the certificate.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to use
+ * these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.addCertificateAsDefault = function
+  (certificate, onComplete, onError)
+{
+  var useSync = !onComplete;
+  var thisManager = this;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.addCertificatePromise(certificate, useSync)
+    .then(function() {
+      return thisManager.setDefaultCertificateForKeyPromise(certificate, useSync);
+    }));
+};
+
+/**
+ * Get a certificate which is still valid with the specified name.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @param {function} onComplete (optional) This calls onComplete(certificate)
+ * with the requested IdentityCertificate. If omitted, the return value is 
+ * described below. (Some database libraries only use a callback, so onComplete
+ * is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {IdentityCertificate} If onComplete is omitted, return the requested
+ * certificate. Otherwise, if onComplete is supplied then return undefined and
+ * use onComplete as described above.
+ */
+IdentityManager.prototype.getCertificate = function
+  (certificateName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getCertificatePromise
+      (certificateName, false, !onComplete));
+};
+
+/**
+ * Get the default certificate name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the default certificate
+ * Name, or a promise rejected with SecurityException if the default key name
+ * for the identity is not set or the default certificate name for the key name
+ * is not set.
+ */
+IdentityManager.prototype.getDefaultCertificateNameForIdentityPromise = function
+  (identityName, useSync)
+{
+  return this.identityStorage.getDefaultCertificateNameForIdentityPromise
+    (identityName, useSync);
+}
+
+/**
+ * Get the default certificate name for the specified identity, which will be
+ * used when signing is performed based on identity.
+ * @param {Name} identityName The name of the specified identity.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with name of the default certificate. If omitted, the return value is described
+ * below. (Some database libraries only use a callback, so onComplete is required
+ * to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the default certificate name.
+ * Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * @throws SecurityException if the default key name for the identity is not
+ * set or the default certificate name for the key name is not set. However, if
+ * onComplete and onError are defined, then if there is an exception return
+ * undefined and call onError(exception).
+ */
+IdentityManager.prototype.getDefaultCertificateNameForIdentity = function
+  (identityName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getDefaultCertificateNameForIdentityPromise
+      (identityName, !onComplete));
+};
+
+/**
+ * Get the default certificate name of the default identity, which will be used
+ * when signing is based on identity and the identity is not specified.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with name of the default certificate. If omitted, the return value is described
+ * below. (Some database libraries only use a callback, so onComplete is required
+ * to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the default certificate name.
+ * Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * @throws SecurityException if the default identity is not set or the default
+ * key name for the identity is not set or the default certificate name for
+ * the key name is not set. However, if onComplete and onError are defined, then
+ * if there is an exception return undefined and call onError(exception).
+ */
+IdentityManager.prototype.getDefaultCertificateName = function
+  (onComplete, onError)
+{
+  var useSync = !onComplete;
+  var thisManager = this;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getDefaultIdentityPromise(useSync)
+    .then(function(identityName) {
+      return thisManager.identityStorage.getDefaultCertificateNameForIdentityPromise
+        (identityName, useSync);
+    }));
+};
+
+/**
+ * Append all the identity names to the nameList.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default identity name. If
+ * false, add only the non-default identity names.
+ * @param {function} onComplete (optional) This calls onComplete() when finished
+ * adding to nameList. If omitted, this returns when complete. (Some database
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {void} If onComplete is omitted, return when complete. Otherwise, if
+ * onComplete is supplied then return undefined and use onComplete as described
+ * above.
+ */
+IdentityManager.prototype.getAllIdentities = function
+  (nameList, isDefault, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getAllIdentitiesPromise
+      (nameList, isDefault, !onComplete));
+};
+
+/**
+ * Append all the key names of a particular identity to the nameList.
+ * @param {Name} identityName The identity name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default key name. If false,
+ * add only the non-default key names.
+ * @param {function} onComplete (optional) This calls onComplete() when finished
+ * adding to nameList. If omitted, this returns when complete. (Some database
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {void} If onComplete is omitted, return when complete. Otherwise, if
+ * onComplete is supplied then return undefined and use onComplete as described
+ * above.
+ */
+IdentityManager.prototype.getAllKeyNamesOfIdentity = function
+  (identityName, nameList, isDefault, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getAllKeyNamesOfIdentityPromise
+      (identityName, nameList, isDefault, !onComplete));
+};
+
+/**
+ * Append all the certificate names of a particular key name to the nameList.
+ * @param {Name} keyName The key name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default certificate name. If
+ * false, add only the non-default certificate names.
+ * @param {function} onComplete (optional) This calls onComplete() when finished
+ * adding to nameList. If omitted, this returns when complete. (Some database
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {void} If onComplete is omitted, return when complete. Otherwise, if
+ * onComplete is supplied then return undefined and use onComplete as described
+ * above.
+ */
+IdentityManager.prototype.getAllCertificateNamesOfKey = function
+  (keyName, nameList, isDefault, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getAllCertificateNamesOfKeyPromise
+      (keyName, nameList, isDefault, !onComplete));
+};
+
+/**
+ * Sign the Data packet or byte array data based on the certificate name.
+ * @param {Data|Buffer} target If this is a Data object, wire encode for signing,
+ * update its signature and key locator field and wireEncoding. If it is a
+ * Buffer, sign it to produce a Signature object.
+ * @param {Name} certificateName The Name identifying the certificate which
+ * identifies the signing key.
+ * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
+ * WireFormat.getDefaultWireFormat() if omitted.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the generated Signature
+ * object (if target is a Buffer) or the target (if target is Data).
+ */
+IdentityManager.prototype.signByCertificatePromise = function
+  (target, certificateName, wireFormat, useSync)
+{
+  useSync = (typeof wireFormat === "boolean") ? wireFormat : useSync;
+  wireFormat = (typeof wireFormat === "boolean" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  var keyName = IdentityManager.certificateNameToPublicKeyName(certificateName);
+
+  var thisManager = this;
+  if (target instanceof Data) {
+    var data = target;
+    var digestAlgorithm = [0];
+
+    return this.makeSignatureByCertificatePromise
+      (certificateName, digestAlgorithm, useSync)
+    .then(function(signature) {
+      data.setSignature(signature);
+      // Encode once to get the signed portion.
+      var encoding = data.wireEncode(wireFormat);
+
+      return thisManager.privateKeyStorage.signPromise
+        (encoding.signedBuf(), keyName, digestAlgorithm[0], useSync);
+    })
+    .then(function(signatureValue) {
+      data.getSignature().setSignature(signatureValue);
+      // Encode again to include the signature.
+      data.wireEncode(wireFormat);
+
+      return SyncPromise.resolve(data);
+    });
+  }
+  else {
+    var digestAlgorithm = [0];
+    return this.makeSignatureByCertificatePromise
+      (certificateName, digestAlgorithm, useSync)
+    .then(function(signature) {
+      return thisManager.privateKeyStorage.signPromise
+        (target, keyName, digestAlgorithm[0], useSync);
+    })
+    .then(function (signatureValue) {
+      signature.setSignature(signatureValue);
+      return SyncPromise.resolve(signature);
+    });
+  }
+};
+
+/**
+ * Sign the Data packet or byte array data based on the certificate name.
+ * @param {Data|Buffer} target If this is a Data object, wire encode for signing,
+ * update its signature and key locator field and wireEncoding. If it is a
+ * Buffer, sign it to produce a Signature object.
+ * @param {Name} certificateName The Name identifying the certificate which
+ * identifies the signing key.
+ * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
+ * WireFormat.getDefaultWireFormat() if omitted.
+ * @param {function} onComplete (optional) If target is a Data object, this calls
+ * onComplete(data) with the supplied Data object which has been modified to set
+ * its signature. If target is a Buffer, this calls onComplete(signature) where
+ * signature is the produced Signature object. If omitted, the return value is
+ * described below. (Some crypto libraries only use a callback, so onComplete is
+ * required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some crypto libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Signature} If onComplete is omitted, return the generated Signature
+ * object (if target is a Buffer) or the target (if target is Data). Otherwise,
+ * if onComplete is supplied then return undefined and use onComplete as described
+ * above.
+ */
+IdentityManager.prototype.signByCertificate = function
+  (target, certificateName, wireFormat, onComplete, onError)
+{
+  onError = (typeof wireFormat === "function") ? onComplete : onError;
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.signByCertificatePromise
+      (target, certificateName, wireFormat, !onComplete));
+};
+
+/**
+ * Append a SignatureInfo to the Interest name, sign the name components and
+ * append a final name component with the signature bits.
+ * @param {Interest} interest The Interest object to be signed. This appends
+ * name components of SignatureInfo and the signature bits.
+ * @param {Name} certificateName The certificate name of the key to use for
+ * signing.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the supplied Interest.
+ */
+IdentityManager.prototype.signInterestByCertificatePromise = function
+  (interest, certificateName, wireFormat, useSync)
+{
+  useSync = (typeof wireFormat === "boolean") ? wireFormat : useSync;
+  wireFormat = (typeof wireFormat === "boolean" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  var thisManager = this;
+  var signature;
+  var digestAlgorithm = [0];
+  return this.makeSignatureByCertificatePromise
+      (certificateName, digestAlgorithm, useSync)
+  .then(function(localSignature) {
+    signature = localSignature;
+    // Append the encoded SignatureInfo.
+    interest.getName().append(wireFormat.encodeSignatureInfo(signature));
+
+    // Append an empty signature so that the "signedPortion" is correct.
+    interest.getName().append(new Name.Component());
+    // Encode once to get the signed portion.
+    var encoding = interest.wireEncode(wireFormat);
+    var keyName = IdentityManager.certificateNameToPublicKeyName
+      (certificateName);
+
+    return thisManager.privateKeyStorage.signPromise
+      (encoding.signedBuf(), keyName, digestAlgorithm[0], useSync);
+  })
+  .then(function(signatureValue) {
+    signature.setSignature(signatureValue);
+
+    // Remove the empty signature and append the real one.
+    interest.setName(interest.getName().getPrefix(-1).append
+      (wireFormat.encodeSignatureValue(signature)));
+    return SyncPromise.resolve(interest);
+  });
+};
+
+/**
+ * Append a SignatureInfo to the Interest name, sign the name components and
+ * append a final name component with the signature bits.
+ * @param {Interest} interest The Interest object to be signed. This appends
+ * name components of SignatureInfo and the signature bits.
+ * @param {Name} certificateName The certificate name of the key to use for
+ * signing.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {function} onComplete (optional) This calls onComplete(interest) with
+ * the supplied Interest object which has been modified to set its signature. If
+ * omitted, then return when the interest has been signed. (Some crypto
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some crypto libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Signature} If onComplete is omitted, return the interest. Otherwise,
+ * if onComplete is supplied then return undefined and use onComplete as
+ * described above.
+ */
+IdentityManager.prototype.signInterestByCertificate = function
+  (interest, certificateName, wireFormat, onComplete, onError)
+{
+  onError = (typeof wireFormat === "function") ? onComplete : onError;
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.signInterestByCertificatePromise
+      (interest, certificateName, wireFormat, !onComplete));
+};
+
+/**
+ * Wire encode the Data object, digest it and set its SignatureInfo to a
+ * DigestSha256.
+ * @param {Data} data The Data object to be signed. This updates its signature
+ * and wireEncoding.
+ * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
+ * WireFormat.getDefaultWireFormat() if omitted.
+ */
+IdentityManager.prototype.signWithSha256 = function(data, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  data.setSignature(new DigestSha256Signature());
+  // Encode once to get the signed portion.
+  var encoding = data.wireEncode(wireFormat);
+
+  // Digest and set the signature.
+  var hash = Crypto.createHash('sha256');
+  hash.update(encoding.signedBuf());
+  data.getSignature().setSignature(new Blob(hash.digest(), false));
+
+  // Encode again to include the signature.
+  data.wireEncode(wireFormat);
+};
+
+/**
+ * Append a SignatureInfo for DigestSha256 to the Interest name, digest the
+   * name components and append a final name component with the signature bits
+   * (which is the digest).
+ * @param {Interest} interest The Interest object to be signed. This appends
+ * name components of SignatureInfo and the signature bits.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ */
+IdentityManager.prototype.signInterestWithSha256 = function(interest, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var signature = new DigestSha256Signature();
+
+  // Append the encoded SignatureInfo.
+  interest.getName().append(wireFormat.encodeSignatureInfo(signature));
+
+  // Append an empty signature so that the "signedPortion" is correct.
+  interest.getName().append(new Name.Component());
+  // Encode once to get the signed portion.
+  var encoding = interest.wireEncode(wireFormat);
+
+  // Digest and set the signature.
+  var hash = Crypto.createHash('sha256');
+  hash.update(encoding.signedBuf());
+  signature.setSignature(new Blob(hash.digest(), false));
+
+  // Remove the empty signature and append the real one.
+  interest.setName(interest.getName().getPrefix(-1).append
+    (wireFormat.encodeSignatureValue(signature)));
+};
+
+/**
+ * Generate a self-signed certificate for a public key.
+ * @param {Name} keyName The name of the public key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which returns the generated
+ * IdentityCertificate.
+ */
+IdentityManager.prototype.selfSignPromise = function(keyName, useSync)
+{
+  var certificate = new IdentityCertificate();
+
+  var thisManager = this;
+  return this.identityStorage.getKeyPromise(keyName, useSync)
+  .then(function(keyBlob) {
+    var publicKey = new PublicKey(keyBlob);
+
+    var notBefore = new Date().getTime();
+    var notAfter = notBefore + 2 * 365 * 24 * 3600 * 1000; // about 2 years
+
+    certificate.setNotBefore(notBefore);
+    certificate.setNotAfter(notAfter);
+
+    var certificateName = keyName.getPrefix(-1).append("KEY").append
+      (keyName.get(-1)).append("ID-CERT").appendVersion(certificate.getNotBefore());
+    certificate.setName(certificateName);
+
+    certificate.setPublicKeyInfo(publicKey);
+    certificate.addSubjectDescription(new CertificateSubjectDescription
+      ("2.5.4.41", keyName.toUri()));
+    certificate.encode();
+
+    return thisManager.signByCertificatePromise
+      (certificate, certificate.getName(), useSync);
+  })
+};
+
+/**
+ * Generate a self-signed certificate for a public key.
+ * @param {Name} keyName The name of the public key.
+ * @param {function} onComplete (optional) This calls onComplete(certificate)
+ * with the the generated IdentityCertificate. If omitted, the return value is
+ * described below. (Some crypto libraries only use a callback, so onComplete is
+ * required to use these.)
+ * @return {IdentityCertificate} If onComplete is omitted, return the
+ * generated certificate. Otherwise, if onComplete is supplied then return
+ * undefined and use onComplete as described above.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some crypto libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.selfSign = function(keyName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.selfSignPromise(keyName, !onComplete));
+};
+
+/**
+ * Get the public key name from the full certificate name.
+ *
+ * @param {Name} certificateName The full certificate name.
+ * @return {Name} The related public key name.
+ * TODO: Move this to IdentityCertificate
+ */
+IdentityManager.certificateNameToPublicKeyName = function(certificateName)
+{
+  var i = certificateName.size() - 1;
+  var idString = "ID-CERT";
+  while (i >= 0) {
+    if (certificateName.get(i).toEscapedString() == idString)
+      break;
+    --i;
+  }
+
+  var tmpName = certificateName.getSubName(0, i);
+  var keyString = "KEY";
+  i = 0;
+  while (i < tmpName.size()) {
+    if (tmpName.get(i).toEscapedString() == keyString)
+      break;
+    ++i;
+  }
+
+  return tmpName.getSubName(0, i).append(tmpName.getSubName
+    (i + 1, tmpName.size() - i - 1));
+};
+
+/**
+ * Return a new Signature object based on the signature algorithm of the public
+ * key with keyName (derived from certificateName).
+ * @param {Name} certificateName The certificate name.
+ * @param {Array} digestAlgorithm Set digestAlgorithm[0] to the signature
+ * algorithm's digest algorithm, e.g. DigestAlgorithm.SHA256.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which returns a new object of the
+ * correct subclass of Signature.
+ */
+IdentityManager.prototype.makeSignatureByCertificatePromise = function
+  (certificateName, digestAlgorithm, useSync)
+{
+  var keyName = IdentityManager.certificateNameToPublicKeyName(certificateName);
+  return this.privateKeyStorage.getPublicKeyPromise(keyName, useSync)
+  .then(function(publicKey) {
+    var keyType = publicKey.getKeyType();
+
+    var signature = null;
+    if (keyType == KeyType.RSA) {
+      signature = new Sha256WithRsaSignature();
+      digestAlgorithm[0] = DigestAlgorithm.SHA256;
+
+      signature.getKeyLocator().setType(KeyLocatorType.KEYNAME);
+      signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));
+    }
+    else if (keyType == KeyType.ECDSA) {
+      signature = new Sha256WithEcdsaSignature();
+      digestAlgorithm[0] = DigestAlgorithm.SHA256;
+
+      signature.getKeyLocator().setType(KeyLocatorType.KEYNAME);
+      signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));
+    }
+    else
+      throw new SecurityException(new Error("Key type is not recognized"));
+
+    return SyncPromise.resolve(signature);
+  });
+};
+
+/**
+ * A private method to generate a pair of keys for the specified identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk true for generating a Key-Signing-Key (KSK), false for
+ * a Data-Signing-Key (DSK).
+ * @param {KeyParams} params The parameters of the key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which returns the generated key name.
+ */
+IdentityManager.prototype.generateKeyPairPromise = function
+  (identityName, isKsk, params, useSync)
+{
+  var keyName;
+  var thisManager = this;
+  return this.identityStorage.getNewKeyNamePromise(identityName, isKsk, useSync)
+  .then(function(localKeyName) {
+    keyName = localKeyName;
+    return thisManager.privateKeyStorage.generateKeyPairPromise
+      (keyName, params, useSync);
+  })
+  .then(function() {
+    return thisManager.privateKeyStorage.getPublicKeyPromise
+      (keyName, useSync);
+  })
+  .then(function(publicKey) {
+    return thisManager.identityStorage.addKeyPromise
+      (keyName, params.getKeyType(), publicKey.getKeyDer());
+  })
+  .then(function() {
+    return SyncPromise.resolve(keyName);
+  });
+};
+
+/**
+ * Get the IdentityStorage from the pib value in the configuration file if
+ * supplied. Otherwise, get the default for this platform.
+ * @param {ConfigFile} config The configuration file to check.
+ * @param {function} initialCheckPromise This is passed to the
+ * BasicIdentityStorage constructor. See it for details.
+ * @return {IdentityStorage} A new IdentityStorage.
+ */
+IdentityManager.getDefaultIdentityStorage_ = function(config, initialCheckPromise)
+{
+  // Assume we are in Node.js.
+  var pibLocator = config.get("pib", "");
+
+  if (pibLocator !== "") {
+    // Don't support non-default locations for now.
+    if (pibLocator !== "pib-sqlite3")
+      throw new SecurityException(new Error
+        ("Invalid config file pib value: " + pibLocator));
+  }
+
+  return new BasicIdentityStorage(initialCheckPromise);
+};
+
+/**
+ * Get the PrivateKeyStorage from the tpm value in the configuration file if
+ * supplied. Otherwise, get the default for this platform.
+ * @param {ConfigFile} config The configuration file to check.
+ * @param {Array<string>} canonicalTpmLocator Set canonicalTpmLocator[0] to the
+ * canonical value including the colon, * e.g. "tpm-file:".
+ * @return A new PrivateKeyStorage.
+ */
+IdentityManager.getDefaultPrivateKeyStorage_ = function
+  (config, canonicalTpmLocator)
+{
+  var tpmLocator = config.get("tpm", "");
+
+  if (tpmLocator === "") {
+    // Assume we are in Node.js, so check the system.
+    if (process.platform === "darwin") {
+      canonicalTpmLocator[0] = "tpm-osxkeychain:";
+      throw new SecurityException(new Error
+        ("IdentityManager: OS X key chain storage is not yet implemented. You must supply a privateKeyStorage."));
+    }
+    else {
+      canonicalTpmLocator[0] = "tpm-file:";
+      return new FilePrivateKeyStorage();
+    }
+  }
+  else if (tpmLocator === "tpm-osxkeychain") {
+    canonicalTpmLocator[0] = "tpm-osxkeychain:";
+    throw new SecurityException(new Error
+      ("IdentityManager: tpm-osxkeychain is not yet implemented."));
+  }
+  else if (tpmLocator === "tpm-file") {
+    canonicalTpmLocator[0] = "tpm-file:";
+    return new FilePrivateKeyStorage();
+  }
+  else
+    throw new SecurityException(new Error
+      ("Invalid config file tpm value: " + tpmLocator));
+};
+
+/**
+ * Check that identityStorage.getTpmLocatorPromise() (if defined) matches the
+ * canonicalTpmLocator. This has to be an async Promise because it calls async
+ * getTpmLocatorPromise.
+ * @param canonicalTpmLocator The canonical locator from
+ * getDefaultPrivateKeyStorage().
+ * @return {Promise} A promise which resolves if canonicalTpmLocator is OK, or a
+ * promise rejected with SecurityException if the private key storage does not
+ * match.
+ */
+IdentityManager.prototype.checkTpmPromise_ = function(canonicalTpmLocator)
+{
+  return this.identityStorage.getTpmLocatorPromise()
+  .then(function(tpmLocator) {
+    // Just check. If a PIB reset is required, expect ndn-cxx/NFD to do it.
+    if (tpmLocator !== "" && tpmLocator !== canonicalTpmLocator)
+      return Promise.reject(new SecurityException(new Error
+        ("The TPM locator supplied does not match the TPM locator in the PIB: " +
+         tpmLocator + " != " + canonicalTpmLocator)));
+    else
+      return Promise.resolve();
+  }, function(err) {
+    // The TPM locator is not set in the PIB yet.
+    return Promise.resolve();
+  });
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A ValidationRequest is used to return information from
+ * PolicyManager.checkVerificationPolicy.
+ *
+ * Create a new ValidationRequest with the given values.
+ * @param {Interest} interest An interest for fetching more data.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(data).
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(data, reason).
+ * @param {number} retry The number of retrials when there is an interest timeout.
+ * @param {number} stepCount  The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @constructor
+ */
+var ValidationRequest = function ValidationRequest
+  (interest, onVerified, onValidationFailed, retry, stepCount)
+{
+  this.interest = interest;
+  this.onVerified = onVerified;
+  this.onValidationFailed = onValidationFailed;
+  this.retry = retry;
+  this.stepCount = stepCount;
+};
+
+exports.ValidationRequest = ValidationRequest;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DataUtils = require('../../encoding/data-utils.js').DataUtils; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var DigestSha256Signature = require('../../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
+var Sha256WithRsaSignature = require('../../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var Sha256WithEcdsaSignature = require('../../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
+var UseSubtleCrypto = require("../../use-subtle-crypto-node.js").UseSubtleCrypto;
+
+/**
+ * A PolicyManager is an abstract base class to represent the policy for
+ * verifying data packets. You must create an object of a subclass.
+ * @constructor
+ */
+var PolicyManager = function PolicyManager()
+{
+};
+
+exports.PolicyManager = PolicyManager;
+
+/**
+ * Check if the received data packet or signed interest can escape from
+ * verification and be trusted as valid.
+ * Your derived class should override.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} True if the data or interest does not need to be verified
+ * to be trusted as valid, otherwise false.
+ */
+PolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
+{
+  throw new Error("PolicyManager.skipVerifyAndTrust is not implemented");
+};
+
+/**
+ * Check if this PolicyManager has a verification rule for the received data
+ * packet or signed interest.
+ * Your derived class should override.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} True if the data or interest must be verified, otherwise
+ * false.
+ */
+PolicyManager.prototype.requireVerify = function(dataOrInterest)
+{
+  throw new Error("PolicyManager.requireVerify is not implemented");
+};
+
+/**
+ * Check whether the received data or interest packet complies with the
+ * verification policy, and get the indication of the next verification step.
+ * Your derived class should override.
+ *
+ * @param {Data|Interest} dataOrInterest The Data object or interest with the
+ * signature to check.
+ * @param {number} stepCount The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(dataOrInterest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(dataOrInterest, reason).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {WireFormat} wireFormat
+ * @return {ValidationRequest} The indication of next verification step, or
+ * null if there is no further step.
+ */
+PolicyManager.prototype.checkVerificationPolicy = function
+  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
+{
+  throw new Error("PolicyManager.checkVerificationPolicy is not implemented");
+};
+
+/**
+ * Check if the signing certificate name and data name satisfy the signing
+ * policy.
+ * Your derived class should override.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @param {Name} certificateName The name of signing certificate.
+ * @return {boolean} True if the signing certificate can be used to sign the
+ * data, otherwise false.
+ */
+PolicyManager.prototype.checkSigningPolicy = function(dataName, certificateName)
+{
+  throw new Error("PolicyManager.checkSigningPolicy is not implemented");
+};
+
+/**
+ * Infer the signing identity name according to the policy. If the signing
+ * identity cannot be inferred, return an empty name.
+ * Your derived class should override.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @return {Name} The signing identity or an empty name if cannot infer.
+ */
+PolicyManager.prototype.inferSigningIdentity = function(dataName)
+{
+  throw new Error("PolicyManager.inferSigningIdentity is not implemented");
+};
+
+// The first time verify is called, it sets this to determine if a signature
+// buffer needs to be converted to a string for the crypto verifier.
+PolicyManager.verifyUsesString_ = null;
+PolicyManager.setVerifyUsesString_ = function()
+{
+  var hashResult = Crypto.createHash('sha256').digest();
+  // If the hash result is a string, we assume that this is a version of
+  //   crypto where verify also uses a string signature.
+  PolicyManager.verifyUsesString_ = (typeof hashResult === 'string');
+};
+
+/**
+ * Check the type of signature and use the publicKeyDer to verify the
+ * signedBlob using the appropriate signature algorithm.
+ * @param {Signature} signature An object of a subclass of Signature, e.g.
+ * Sha256WithRsaSignature.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
+ * signature.
+ * @param {function} onComplete This calls onComplete(true) if the signature
+ * verifies, otherwise onComplete(false).
+ * @throws SecurityException if the signature type is not recognized or if
+ * publicKeyDer can't be decoded.
+ */
+PolicyManager.verifySignature = function
+  (signature, signedBlob, publicKeyDer, onComplete)
+{
+  if (signature instanceof Sha256WithRsaSignature) {
+    if (publicKeyDer.isNull()) {
+      onComplete(false);
+      return;
+    }
+    PolicyManager.verifySha256WithRsaSignature
+      (signature.getSignature(), signedBlob, publicKeyDer, onComplete);
+  }
+  else if (signature instanceof Sha256WithEcdsaSignature) {
+    if (publicKeyDer.isNull()) {
+      onComplete(false);
+      return;
+    }
+    PolicyManager.verifySha256WithEcdsaSignature
+      (signature.getSignature(), signedBlob, publicKeyDer, onComplete);
+  }
+  else if (signature instanceof DigestSha256Signature)
+    PolicyManager.verifyDigestSha256Signature
+      (signature.getSignature(), signedBlob, onComplete);
+  else
+    // We don't expect this to happen.
+    throw new SecurityException(new Error
+      ("PolicyManager.verify: Signature type is unknown"));
+};
+
+/**
+ * Verify the RSA signature on the SignedBlob using the given public key.
+ * @param {Blob} signature The signature bits.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
+ * signature.
+ * @param {function} onComplete This calls onComplete(true) if the signature
+ * verifies, otherwise onComplete(false).
+ */
+PolicyManager.verifySha256WithRsaSignature = function
+  (signature, signedBlob, publicKeyDer, onComplete)
+{
+  if (UseSubtleCrypto()){
+    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};
+
+    crypto.subtle.importKey("spki", publicKeyDer.buf().buffer, algo, true, ["verify"]).then(function(publicKey){
+      return crypto.subtle.verify(algo, publicKey, signature.buf(), signedBlob.signedBuf())
+    }).then(function(verified){
+      onComplete(verified);
+    });
+  } else {
+    if (PolicyManager.verifyUsesString_ === null)
+      PolicyManager.setVerifyUsesString_();
+
+    // The crypto verifier requires a PEM-encoded public key.
+    var keyBase64 = publicKeyDer.buf().toString('base64');
+    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END PUBLIC KEY-----";
+
+    var verifier = Crypto.createVerify('RSA-SHA256');
+    verifier.update(signedBlob.signedBuf());
+    var signatureBytes = PolicyManager.verifyUsesString_ ?
+      DataUtils.toString(signature.buf()) : signature.buf();
+    onComplete(verifier.verify(keyPem, signatureBytes));
+  }
+};
+
+/**
+ * Verify the ECDSA signature on the SignedBlob using the given public key.
+ * @param {Blob} signature The signature bits.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
+ * signature.
+ * @param {function} onComplete This calls onComplete(true) if the signature
+ * verifies, otherwise onComplete(false).
+ */
+PolicyManager.verifySha256WithEcdsaSignature = function
+  (signature, signedBlob, publicKeyDer, onComplete)
+{
+  if (UseSubtleCrypto()) {
 /*
+    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};
+
+    crypto.subtle.importKey("spki", publicKeyDer.buf().buffer, algo, true, ["verify"]).then(function(publicKey){
+      return crypto.subtle.verify(algo, publicKey, signature.buf(), signedBlob.signedBuf())
+    }).then(function(verified){
+      onComplete(verified);
+    });
+*/  onComplete(false);
+  } else {
+    if (PolicyManager.verifyUsesString_ === null)
+      PolicyManager.setVerifyUsesString_();
+
+    // The crypto verifier requires a PEM-encoded public key.
+    var keyBase64 = publicKeyDer.buf().toString("base64");
+    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END PUBLIC KEY-----";
+
+    // Just create a "sha256". The Crypto library will infer ECDSA from the key.
+    var verifier = Crypto.createVerify("sha256");
+    verifier.update(signedBlob.signedBuf());
+    var signatureBytes = PolicyManager.verifyUsesString_ ?
+      DataUtils.toString(signature.buf()) : signature.buf();
+    onComplete(verifier.verify(keyPem, signatureBytes));
+  }
+};
+
+/**
+ * Verify the DigestSha256 signature on the SignedBlob by verifying that the
+ * digest of SignedBlob equals the signature.
+ * @param {Blob} signature The signature bits.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {function} onComplete This calls onComplete(true) if the signature
+ * verifies, otherwise onComplete(false).
+ */
+PolicyManager.verifyDigestSha256Signature = function
+  (signature, signedBlob, onComplete)
+{
+  // Set signedPortionDigest to the digest of the signed portion of the signedBlob.
+  var hash = Crypto.createHash('sha256');
+  hash.update(signedBlob.signedBuf());
+  var signedPortionDigest = new Blob(hash.digest(), false);
+
+  onComplete(signedPortionDigest.equals(signature));
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From PyNDN certificate_cache.py by Adeola Bannis.
+ * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate;
+
+/**
+ * A CertificateCache is used to save other users' certificate during
+ * verification.
+ * @constructor
+ */
+var CertificateCache = function CertificateCache()
+{
+  // The key is the certificate name URI. The value is the wire encoding Blob.
+  this.cache = {};
+};
+
+exports.CertificateCache = CertificateCache;
+
+/**
+ * Insert the certificate into the cache. Assumes the timestamp is not yet
+ * removed from the name.
+ * @param {IdentityCertificate} certificate The certificate to insert.
+ */
+CertificateCache.prototype.insertCertificate = function(certificate)
+{
+  var certName = certificate.getName().getPrefix(-1);
+  this.cache[certName.toUri()] = certificate.wireEncode();
+};
+
+/**
+ * Remove a certificate from the cache. This does nothing if it is not present.
+ * @param {Name} certificateName The name of the certificate to remove. This
+ * assumes there is no timestamp in the name.
+ */
+CertificateCache.prototype.deleteCertificate = function(certificateName)
+{
+  delete this.cache[certificateName.toUri()];
+};
+
+/**
+ * Fetch a certificate from the cache.
+ * @param {Name} certificateName The name of the certificate to remove. This
+ * assumes there is no timestamp in the name.
+ * @return {IdentityCertificate} A new copy of the IdentityCertificate, or null
+ * if not found.
+ */
+CertificateCache.prototype.getCertificate = function(certificateName)
+{
+  var certData = this.cache[certificateName.toUri()];
+  if (certData === undefined)
+    return null;
+
+  var cert = new IdentityCertificate();
+  cert.wireDecode(certData);
+  return cert;
+};
+
+/**
+ * Clear all certificates from the store.
+ */
+CertificateCache.prototype.reset = function()
+{
+  this.cache = {};
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From PyNDN config_policy_manager.py by Adeola Bannis.
+ * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var fs = require('fs'); /** @ignore */
+var path = require('path'); /** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var Interest = require('../../interest.js').Interest; /** @ignore */
+var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
+var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var BoostInfoParser = require('../../util/boost-info-parser.js').BoostInfoParser; /** @ignore */
+var NdnRegexMatcher = require('../../util/ndn-regex-matcher.js').NdnRegexMatcher; /** @ignore */
+var CertificateCache = require('./certificate-cache.js').CertificateCache; /** @ignore */
+var ValidationRequest = require('./validation-request.js').ValidationRequest; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
+var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
+var NdnCommon = require('../../util/ndn-common.js').NdnCommon;
+
+/**
+ * ConfigPolicyManager manages trust according to a configuration file in the
+ * Validator Configuration File Format
+ * (http://redmine.named-data.net/projects/ndn-cxx/wiki/CommandValidatorConf)
+ *
+ * Once a rule is matched, the ConfigPolicyManager looks in the
+ * CertificateCache for the IdentityCertificate matching the name in the KeyLocator
+ * and uses its public key to verify the data packet or signed interest. If the
+ * certificate can't be found, it is downloaded, verified and installed. A chain
+ * of certificates will be followed to a maximum depth.
+ * If the new certificate is accepted, it is used to complete the verification.
+ *
+ * The KeyLocators of data packets and signed interests MUST contain a name for
+ * verification to succeed.
+ *
+ * Create a new ConfigPolicyManager which will act on the rules specified in the
+ * configuration and download unknown certificates when necessary.
+ *
+ * @param {string} configFileName (optional) If not null or empty, the path to
+ * the configuration file containing verification rules. (This only works in
+ * Node.js since it reads files using the "fs" module.) Otherwise, you should
+ * separately call load().
+ * @param {CertificateCache} certificateCache (optional) A CertificateCache to
+ * hold known certificates. If this is null or omitted, then create an internal
+ * CertificateCache.
+ * @param {number} searchDepth (optional) The maximum number of links to follow
+ * when verifying a certificate chain. If omitted, use a default.
+ * @param {number} graceInterval (optional) The window of time difference
+ * (in milliseconds) allowed between the timestamp of the first interest signed with
+ * a new public key and the validation time. If omitted, use a default value.
+ * @param {number} keyTimestampTtl (optional) How long a public key's last-used
+ * timestamp is kept in the store (milliseconds). If omitted, use a default value.
+ * @param {number} maxTrackedKeys The maximum number of public key use
+ * timestamps to track. If omitted, use a default.
+ * @constructor
+ */
+var ConfigPolicyManager = function ConfigPolicyManager
+  (configFileName, certificateCache, searchDepth, graceInterval,
+   keyTimestampTtl, maxTrackedKeys)
+{
+  // Call the base constructor.
+  PolicyManager.call(this);
+
+  if (certificateCache == undefined)
+    certificateCache = null;
+  if (searchDepth == undefined)
+    searchDepth = 5;
+  if (graceInterval == undefined)
+    graceInterval = 3000;
+  if (keyTimestampTtl == undefined)
+    keyTimestampTtl = 3600000;
+  if (maxTrackedKeys == undefined)
+    maxTrackedKeys = 1000;
+
+  if (certificateCache == null)
+    this.certificateCache = new CertificateCache();
+  else
+    this.certificateCache = certificateCache;
+  this.maxDepth = searchDepth;
+  this.keyGraceInterval = graceInterval;
+  this.keyTimestampTtl = keyTimestampTtl;
+  this.maxTrackedKeys = maxTrackedKeys;
+
+  this.reset();
+
+  if (configFileName != null && configFileName != "")
+    this.load(configFileName);
+};
+
+ConfigPolicyManager.prototype = new PolicyManager();
+ConfigPolicyManager.prototype.name = "ConfigPolicyManager";
+
+exports.ConfigPolicyManager = ConfigPolicyManager;
+
+/**
+ * Reset the certificate cache and other fields to the constructor state.
+ */
+ConfigPolicyManager.prototype.reset = function()
+{
+  this.certificateCache.reset();
+
+  // Stores the fixed-signer certificate name associated with validation rules
+  // so we don't keep loading from files.
+  this.fixedCertificateCache = {};
+
+  // Stores the timestamps for each public key used in command interests to
+  // avoid replay attacks.
+  // Key is public key name, value is last timestamp.
+  this.keyTimestamps = {};
+
+  this.requiresVerification = true;
+
+  this.config = new BoostInfoParser();
+  this.refreshManager = new ConfigPolicyManager.TrustAnchorRefreshManager();
+};
+
+/**
+ * Call reset() and load the configuration rules from the file name or the input
+ * string. There are two forms:
+ * load(configFileName) reads configFileName from the file system. (This only
+ * works in Node.js since it reads files using the "fs" module.)
+ * load(input, inputName) reads from the input, in which case inputName is used
+ * only for log messages, etc.
+ * @param {string} configFileName The path to the file containing configuration
+ * rules.
+ * @param {string} input The contents of the configuration rules, with lines
+ * separated by "\n" or "\r\n".
+ * @param {string} inputName Use with input for log messages, etc.
+ */
+ConfigPolicyManager.prototype.load = function(configFileNameOrInput, inputName)
+{
+  this.reset();
+  this.config.read(configFileNameOrInput, inputName);
+  this.loadTrustAnchorCertificates();
+}
+
+/**
+ * Check if this PolicyManager has a verification rule for the received data.
+ * If the configuration file contains the trust anchor 'any', nothing is
+ * verified.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} true if the data must be verified, otherwise false.
+ */
+ConfigPolicyManager.prototype.requireVerify = function(dataOrInterest)
+{
+  return this.requiresVerification;
+};
+
+/**
+ * Override to always indicate that the signing certificate name and data name
+ * satisfy the signing policy.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @param {Name} certificateName The name of signing certificate.
+ * @return {boolean} True to indicate that the signing certificate can be used
+ * to sign the data.
+ */
+ConfigPolicyManager.prototype.checkSigningPolicy = function
+  (dataName, certificateName)
+{
+  return true;
+};
+
+/**
+ * Check if the received signed interest can escape from verification and be
+ * trusted as valid. If the configuration file contains the trust anchor
+ * 'any', nothing is verified.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} true if the data or interest does not need to be verified
+ * to be trusted as valid, otherwise false.
+ */
+ConfigPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
+{
+  return !this.requiresVerification;
+};
+
+/**
+ * Check whether the received data packet or interest complies with the
+ * verification policy, and get the indication of the next verification step.
+ *
+ * @param {Data|Interest} dataOrInterest The Data object or interest with the
+ * signature to check.
+ * @param {number} stepCount The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(dataOrInterest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(dataOrInterest, reason).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {WireFormat} wireFormat
+ * @return {ValidationRequest} The indication of next verification step, or
+ * null if there is no further step.
+ */
+ConfigPolicyManager.prototype.checkVerificationPolicy = function
+  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
+{
+  if (stepCount > this.maxDepth) {
+    try {
+      onValidationFailed
+        (dataOrInterest, "The verification stepCount " + stepCount +
+           " exceeded the maxDepth " + this.maxDepth);
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var signature = ConfigPolicyManager.extractSignature(dataOrInterest, wireFormat);
+  // No signature -> fail.
+  if (signature == null) {
+    try {
+      onValidationFailed
+        (dataOrInterest, "Cannot extract the signature from " +
+         dataOrInterest.getName().toUri());
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  if (!KeyLocator.canGetFromSignature(signature)) {
+    // We only support signature types with key locators.
+    try {
+      onValidationFailed
+        (dataOrInterest, "The signature type does not support a KeyLocator");
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var keyLocator = null;
+  try {
+    keyLocator = KeyLocator.getFromSignature(signature);
+  }
+  catch (ex) {
+    // No key locator -> fail.
+    try {
+      onValidationFailed
+        (dataOrInterest, "Error in KeyLocator.getFromSignature: " + ex);
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var signatureName = keyLocator.getKeyName();
+  // No key name in KeyLocator -> fail.
+  if (signatureName.size() == 0) {
+    try {
+      onValidationFailed
+        (dataOrInterest, "The signature KeyLocator doesn't have a key name");
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var objectName = dataOrInterest.getName();
+  var matchType = "data";
+
+  // For command interests, we need to ignore the last 4 components when
+  // matching the name.
+  if (dataOrInterest instanceof Interest) {
+    objectName = objectName.getPrefix(-4);
+    matchType = "interest";
+  }
+
+  // First see if we can find a rule to match this packet.
+  var matchedRule = this.findMatchingRule(objectName, matchType);
+
+  // No matching rule -> fail.
+  if (matchedRule == null) {
+    try {
+      onValidationFailed
+        (dataOrInterest, "No matching rule found for " + objectName.toUri());
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var failureReason = ["unknown"];
+  var signatureMatches = this.checkSignatureMatch
+    (signatureName, objectName, matchedRule, failureReason);
+  if (!signatureMatches) {
+    try {
+      onValidationFailed(dataOrInterest, failureReason[0]);
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  // Before we look up keys, refresh any certificate directories.
+  this.refreshManager.refreshAnchors();
+
+  // Now finally check that the data or interest was signed correctly.
+  // If we don't actually have the certificate yet, create a
+  // ValidationRequest for it.
+  var foundCert = this.refreshManager.getCertificate(signatureName);
+  if (foundCert == null)
+    foundCert = this.certificateCache.getCertificate(signatureName);
+  var thisManager = this;
+  if (foundCert == null) {
+    var certificateInterest = new Interest(signatureName);
+    var onCertificateDownloadComplete = function(data) {
+      var certificate;
+      try {
+        certificate = new IdentityCertificate(data);
+      } catch (ex) {
+        try {
+          onValidationFailed
+            (dataOrInterest, "Cannot decode certificate " + data.getName().toUri());
+        } catch (ex) {
+          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+        return null;
+      }
+      thisManager.certificateCache.insertCertificate(certificate);
+      thisManager.checkVerificationPolicy
+        (dataOrInterest, stepCount + 1, onVerified, onValidationFailed);
+    };
+
+    var nextStep = new ValidationRequest
+      (certificateInterest, onCertificateDownloadComplete, onValidationFailed,
+       2, stepCount + 1);
+
+    return nextStep;
+  }
+
+  // For interests, we must check that the timestamp is fresh enough.
+  // We do this after (possibly) downloading the certificate to avoid
+  // filling the cache with bad keys.
+  if (dataOrInterest instanceof Interest) {
+    var keyName = foundCert.getPublicKeyName();
+    var timestamp = dataOrInterest.getName().get(-4).toNumber();
+
+    if (!this.interestTimestampIsFresh(keyName, timestamp, failureReason)) {
+      try {
+        onValidationFailed(dataOrInterest, failureReason[0]);
+      } catch (ex) {
+        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return null;
+    }
+  }
+
+  // Certificate is known, so verify the signature.
+  this.verify(signature, dataOrInterest.wireEncode(), function (verified, reason) {
+    if (verified) {
+      try {
+        onVerified(dataOrInterest);
+      } catch (ex) {
+        console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      if (dataOrInterest instanceof Interest)
+        thisManager.updateTimestampForKey(keyName, timestamp);
+    }
+    else {
+      try {
+        onValidationFailed(dataOrInterest, reason);
+      } catch (ex) {
+        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+  });
+};
+
+/**
+ * The configuration file allows 'trust anchor' certificates to be preloaded.
+ * The certificates may also be loaded from a directory, and if the 'refresh'
+ * option is set to an interval, the certificates are reloaded at the specified
+ * interval.
+ */
+ConfigPolicyManager.prototype.loadTrustAnchorCertificates = function()
+{
+  var anchors = this.config.getRoot().get("validator/trust-anchor");
+
+  for (var i = 0; i < anchors.length; ++i) {
+    var anchor = anchors[i];
+
+    var typeName = anchor.get("type")[0].getValue();
+    var isPath = false;
+    var certID;
+    if (typeName == 'file') {
+      certID = anchor.get("file-name")[0].getValue();
+      isPath = true;
+    }
+    else if (typeName == 'base64') {
+      certID = anchor.get("base64-string")[0].getValue();
+      isPath = false;
+    }
+    else if (typeName == "dir") {
+      var dirName = anchor.get("dir")[0].getValue();
+
+      var refreshPeriod = 0;
+      var refreshTrees = anchor.get("refresh");
+      if (refreshTrees.length >= 1) {
+        var refreshPeriodStr = refreshTrees[0].getValue();
+
+        var refreshMatch = refreshPeriodStr.match(/(\d+)([hms])/);
+        if (refreshMatch == null)
+          refreshPeriod = 0;
+        else {
+          refreshPeriod = parseInt(refreshMatch[1]);
+          if (refreshMatch[2] != 's') {
+            refreshPeriod *= 60;
+            if (refreshMatch[2] != 'm')
+              refreshPeriod *= 60;
+          }
+        }
+      }
+
+      // Convert refreshPeriod from seconds to milliseconds.
+      this.refreshManager.addDirectory(dirName, refreshPeriod * 1000);
+      continue;
+    }
+    else if (typeName == "any") {
+      // This disables all security!
+      this.requiresVerification = false;
+      break;
+    }
+
+    this.lookupCertificate(certID, isPath);
+  }
+};
+
+/**
+ * Once a rule is found to match data or a signed interest, the name in the
+ * KeyLocator must satisfy the condition in the 'checker' section of the rule,
+ * else the data or interest is rejected.
+ * @param {Name} signatureName The certificate name from the KeyLocator.
+ * @param {Name} objectName The name of the data packet or interest. In the case
+ * of signed interests, this excludes the timestamp, nonce and signature
+ * components.
+ * @param {BoostInfoTree} rule The rule from the configuration file that matches
+ * the data or interest.
+ * @param {Array<string>} failureReason If matching fails, set failureReason[0]
+ * to the failure reason.
+ * @return {boolean} True if matches.
+ */
+ConfigPolicyManager.prototype.checkSignatureMatch = function
+  (signatureName, objectName, rule, failureReason)
+{
+  var checker = rule.get("checker")[0];
+  var checkerType = checker.get("type")[0].getValue();
+  if (checkerType == "fixed-signer") {
+    var signerInfo = checker.get("signer")[0];
+    var signerType = signerInfo.get("type")[0].getValue();
+
+    var cert;
+    if (signerType == "file") {
+      cert = this.lookupCertificate
+        (signerInfo.get("file-name")[0].getValue(), true);
+      if (cert == null) {
+        failureReason[0] = "Can't find fixed-signer certificate file: " +
+          signerInfo.get("file-name")[0].getValue();
+        return false;
+      }
+    }
+    else if (signerType == "base64") {
+      cert = this.lookupCertificate
+        (signerInfo.get("base64-string")[0].getValue(), false);
+      if (cert == null) {
+        failureReason[0] = "Can't find fixed-signer certificate base64: " +
+          signerInfo.get("base64-string")[0].getValue();
+        return false;
+      }
+    }
+    else {
+      failureReason[0] = "Unrecognized fixed-signer signerType: " + signerType;
+      return false;
+    }
+
+    if (cert.getName().equals(signatureName))
+      return true;
+    else {
+      failureReason[0] = "fixed-signer cert name \"" + cert.getName().toUri() +
+        "\" does not equal signatureName \"" + signatureName.toUri() + "\"";
+      return false;
+    }
+  }
+  else if (checkerType == "hierarchical") {
+    // This just means the data/interest name has the signing identity as a prefix.
+    // That means everything before "ksk-?" in the key name.
+    var identityRegex = "^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>";
+    var identityMatch = NdnRegexMatcher.match(identityRegex, signatureName);
+    if (identityMatch != null) {
+      var identityPrefix = new Name(identityMatch[1]).append
+        (new Name(identityMatch[2]));
+      if (ConfigPolicyManager.matchesRelation
+          (objectName, identityPrefix, "is-prefix-of"))
+        return true;
+      else {
+        failureReason[0] = "The hierarchical objectName \"" + objectName.toUri() +
+          "\" is not a prefix of \"" + identityPrefix.toUri() + "\"";
+        return false;
+      }
+    }
+    else {
+      failureReason[0] = "The hierarchical identityRegex \"" + identityRegex +
+        "\" does not match signatureName \"" + signatureName.toUri() + "\"";
+      return false;
+    }
+  }
+  else if (checkerType == "customized") {
+    var keyLocatorInfo = checker.get("key-locator")[0];
+    // Not checking type - only name is supported.
+
+    // Is this a simple relation?
+    var relationType = keyLocatorInfo.getFirstValue("relation");
+    if (relationType != null) {
+      var matchName = new Name(keyLocatorInfo.get("name")[0].getValue());
+      if (ConfigPolicyManager.matchesRelation
+          (signatureName, matchName, relationType))
+        return true;
+      else {
+        failureReason[0] = "The custom signatureName \"" + signatureName.toUri() +
+          "\" does not match matchName \"" + matchName.toUri() +
+          "\" using relation " + relationType;
+        return false;
+      }
+    }
+
+    // Is this a simple regex?
+    var keyRegex = keyLocatorInfo.getFirstValue("regex");
+    if (keyRegex != null) {
+      if (NdnRegexMatcher.match(keyRegex, signatureName) != null)
+        return true;
+      else {
+        failureReason[0] = "The custom signatureName \"" + signatureName.toUri() +
+          "\" does not regex match simpleKeyRegex \"" + keyRegex + "\"";
+        return false;
+      }
+    }
+
+    // Is this a hyper-relation?
+    var hyperRelationList = keyLocatorInfo.get("hyper-relation");
+    if (hyperRelationList.length >= 1) {
+      var hyperRelation = hyperRelationList[0];
+
+      var keyRegex = hyperRelation.getFirstValue("k-regex");
+      var keyExpansion = hyperRelation.getFirstValue("k-expand");
+      var nameRegex = hyperRelation.getFirstValue("p-regex");
+      var nameExpansion = hyperRelation.getFirstValue("p-expand");
+      var relationType = hyperRelation.getFirstValue("h-relation");
+      if (keyRegex != null && keyExpansion != null && nameRegex != null &&
+          nameExpansion != null && relationType != null) {
+        var keyMatch = NdnRegexMatcher.match(keyRegex, signatureName);
+        if (keyMatch == null || keyMatch[1] === undefined) {
+          failureReason[0] = "The custom hyper-relation signatureName \"" +
+            signatureName.toUri() + "\" does not match the keyRegex \"" +
+            keyRegex + "\"";
+          return false;
+        }
+        var keyMatchPrefix = ConfigPolicyManager.expand(keyMatch, keyExpansion);
+
+        var nameMatch = NdnRegexMatcher.match(nameRegex, objectName);
+        if (nameMatch == null || nameMatch[1] === undefined) {
+          failureReason[0] = "The custom hyper-relation objectName \"" +
+            objectName.toUri() + "\" does not match the nameRegex \"" +
+            nameRegex + "\"";
+          return false;
+        }
+        var nameMatchStr = ConfigPolicyManager.expand(nameMatch, nameExpansion);
+
+        if (ConfigPolicyManager.matchesRelation
+            (new Name(nameMatchStr), new Name(keyMatchPrefix), relationType))
+          return true;
+        else {
+          failureReason[0] = "The custom hyper-relation nameMatch \"" +
+            nameMatchStr + "\" does not match the keyMatchPrefix \"" +
+            keyMatchPrefix + "\" using relation " + relationType;
+          return false;
+        }
+      }
+    }
+  }
+
+  failureReason[0] = "Unrecognized checkerType: " + checkerType;
+  return false;
+};
+
+/**
+ * Similar to Python expand, return expansion where every \1, \2, etc. is
+ * replaced by match[1], match[2], etc.  Note: Even though this is a general
+ * utility function, we define it locally because it is only tested to work in
+ * the cases used by this class.
+ * @param {Object} match The match object from String.match.
+ * @param {string} expansion The string with \1, \2, etc. to replace from match.
+ * @return {string} The expanded string.
+ */
+ConfigPolicyManager.expand = function(match, expansion)
+{
+  return expansion.replace
+    (/\\(\d)/g,
+     function(fullMatch, n) { return match[parseInt(n)];})
+};
+
+/**
+ * This looks up certificates specified as base64-encoded data or file names.
+ * These are cached by filename or encoding to avoid repeated reading of files
+ * or decoding.
+ * @param {string} certID
+ * @param {boolean} isPath
+ * @return {IdentityCertificate} The certificate object, or null if not found.
+ */
+ConfigPolicyManager.prototype.lookupCertificate = function(certID, isPath)
+{
+  var cert;
+
+  var cachedCertUri = this.fixedCertificateCache[certID];
+  if (cachedCertUri === undefined) {
+    if (isPath)
+      // load the certificate data (base64 encoded IdentityCertificate)
+      cert = ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile
+        (certID);
+    else {
+      var certData = new Buffer(certID, 'base64');
+      cert = new IdentityCertificate();
+      cert.wireDecode(certData);
+    }
+
+    var certUri = cert.getName().getPrefix(-1).toUri();
+    this.fixedCertificateCache[certID] = certUri;
+    this.certificateCache.insertCertificate(cert);
+  }
+  else
+    cert = this.certificateCache.getCertificate(new Name(cachedCertUri));
+
+  return cert;
+};
+
+/**
+ * Search the configuration file for the first rule that matches the data or
+ * signed interest name. In the case of interests, the name to match should
+ * exclude the timestamp, nonce, and signature components.
+ * @param {Name} objName The name to be matched.
+ * @param {string} matchType The rule type to match, "data" or "interest".
+ * @return {BoostInfoTree} The matching rule, or null if not found.
+ */
+ConfigPolicyManager.prototype.findMatchingRule = function(objName, matchType)
+{
+  var rules = this.config.getRoot().get("validator/rule");
+  for (var iRule = 0; iRule < rules.length; ++iRule) {
+    var r = rules[iRule];
+
+    if (r.get('for')[0].getValue() == matchType) {
+      var passed = true;
+      var filters = r.get('filter');
+      if (filters.length == 0)
+        // No filters means we pass!
+        return r;
+      else {
+        for (var iFilter = 0; iFilter < filters.length; ++iFilter) {
+          var f = filters[iFilter];
+
+          // Don't check the type - it can only be name for now.
+          // We need to see if this is a regex or a relation.
+          var regexPattern = f.getFirstValue("regex");
+          if (regexPattern === null) {
+            var matchRelation = f.get('relation')[0].getValue();
+            var matchUri = f.get('name')[0].getValue();
+            var matchName = new Name(matchUri);
+            passed = ConfigPolicyManager.matchesRelation(objName, matchName, matchRelation);
+          }
+          else
+            passed = (NdnRegexMatcher.match(regexPattern, objName) !== null);
+
+          if (!passed)
+            break;
+        }
+
+        if (passed)
+          return r;
+      }
+    }
+  }
+
+  return null;
+};
+
+/**
+ * Determines if a name satisfies the relation to matchName.
+ * @param {Name} name
+ * @param {Name} matchName
+ * @param {string} matchRelation Can be one of:
+ *   'is-prefix-of' - passes if the name is equal to or has the other
+ *      name as a prefix
+ *   'is-strict-prefix-of' - passes if the name has the other name as a
+ *      prefix, and is not equal
+ *   'equal' - passes if the two names are equal
+ * @return {boolean}
+ */
+ConfigPolicyManager.matchesRelation = function(name, matchName, matchRelation)
+{
+  var passed = false;
+  if (matchRelation == 'is-strict-prefix-of') {
+    if (matchName.size() == name.size())
+      passed = false;
+    else if (matchName.match(name))
+      passed = true;
+  }
+  else if (matchRelation == 'is-prefix-of') {
+    if (matchName.match(name))
+      passed = true;
+  }
+  else if (matchRelation == 'equal') {
+    if (matchName.equals(name))
+      passed = true;
+  }
+  return passed;
+};
+
+/**
+ * Extract the signature information from the interest name or from the data
+ * packet or interest.
+ * @param {Data|Interest} dataOrInterest The object whose signature is needed.
+ * @param {WireFormat} wireFormat (optional) The wire format used to decode
+ * signature information from the interest name.
+ * @return {Signature} The object of a sublcass of Signature or null if can't
+ * decode.
+ */
+ConfigPolicyManager.extractSignature = function(dataOrInterest, wireFormat)
+{
+  if (dataOrInterest instanceof Data)
+    return dataOrInterest.getSignature();
+  else if (dataOrInterest instanceof Interest) {
+    wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+    try {
+      var signature = wireFormat.decodeSignatureInfoAndValue
+        (dataOrInterest.getName().get(-2).getValue().buf(),
+         dataOrInterest.getName().get(-1).getValue().buf(), false);
+    }
+    catch (e) {
+      return null;
+    }
+
+    return signature;
+  }
+
+  return null;
+};
+
+/**
+ * Determine whether the timestamp from the interest is newer than the last use
+ * of this key, or within the grace interval on first use.
+ * @param {Name} keyName The name of the public key used to sign the interest.
+ * @param {number} timestamp The timestamp extracted from the interest name.
+ * @param {Array<string>} failureReason If matching fails, set failureReason[0]
+ * to the failure reason.
+ * @return {boolean} True if timestamp is fresh as described above.
+ */
+ConfigPolicyManager.prototype.interestTimestampIsFresh = function
+  (keyName, timestamp, failureReason)
+{
+  var lastTimestamp = this.keyTimestamps[keyName.toUri()];
+  if (lastTimestamp == undefined) {
+    var now = new Date().getTime();
+    var notBefore = now - this.keyGraceInterval;
+    var notAfter = now + this.keyGraceInterval;
+    if (!(timestamp > notBefore && timestamp < notAfter)) {
+      failureReason[0] =
+        "The command interest timestamp is not within the first use grace period of " +
+        this.keyGraceInterval + " milliseconds.";
+      return false;
+    }
+    else
+      return true;
+  }
+  else {
+    if (timestamp <= lastTimestamp) {
+      failureReason[0] =
+        "The command interest timestamp is not newer than the previous timestamp";
+      return false;
+    }
+    else
+      return true;
+  }
+};
+
+/**
+ * Trim the table size down if necessary, and insert/update the latest interest
+ * signing timestamp for the key. Any key which has not been used within the TTL
+ * period is purged. If the table is still too large, the oldest key is purged.
+ * @param {Name} keyName The name of the public key used to sign the interest.
+ * @param {number} timestamp The timestamp extracted from the interest name.
+ */
+ConfigPolicyManager.prototype.updateTimestampForKey = function
+  (keyName, timestamp)
+{
+  this.keyTimestamps[keyName.toUri()] = timestamp;
+
+  // JavaScript does have a direct way to get the number of entries, so first
+  //   get the keysToErase while counting.
+  var keyTimestampsSize = 0;
+  var keysToErase = [];
+
+  var now = new Date().getTime();
+  var oldestTimestamp = now;
+  var oldestKey = null;
+  for (var keyUri in this.keyTimestamps) {
+    ++keyTimestampsSize;
+    var ts = this.keyTimestamps[keyUri];
+    if (now - ts > this.keyTimestampTtl)
+      keysToErase.push(keyUri);
+    else if (ts < oldestTimestamp) {
+      oldestTimestamp = ts;
+      oldestKey = keyUri;
+    }
+  }
+
+  if (keyTimestampsSize >= this.maxTrackedKeys) {
+    // Now delete the expired keys.
+    for (var i = 0; i < keysToErase.length; ++i) {
+      delete this.keyTimestamps[keysToErase[i]];
+      --keyTimestampsSize;
+    }
+
+    if (keyTimestampsSize > this.maxTrackedKeys)
+      // We have not removed enough.
+      delete this.keyTimestamps[oldestKey];
+  }
+};
+
+/**
+ * Check the type of signatureInfo to get the KeyLocator. Look in the
+ * IdentityStorage for the public key with the name in the KeyLocator and use it
+ * to verify the signedBlob. If the public key can't be found, return false.
+ * (This is a generalized method which can verify both a data packet and an
+ * interest.)
+ * @param {Signature} signatureInfo An object of a subclass of Signature, e.g.
+ * Sha256WithRsaSignature.
+ * @param {SignedBlob} signedBlob The SignedBlob with the signed portion to
+ * verify.
+ * @param {function} onComplete This calls onComplete(true, undefined) if the
+ * signature verifies, otherwise onComplete(false, reason).
+ */
+ConfigPolicyManager.prototype.verify = function
+  (signatureInfo, signedBlob, onComplete)
+{
+  // We have already checked once that there is a key locator.
+  var keyLocator = KeyLocator.getFromSignature(signatureInfo);
+
+  if (keyLocator.getType() == KeyLocatorType.KEYNAME) {
+    // Assume the key name is a certificate name.
+    var signatureName = keyLocator.getKeyName();
+    var certificate = this.refreshManager.getCertificate(signatureName);
+    if (certificate == null)
+      certificate = this.certificateCache.getCertificate(signatureName);
+    if (certificate == null) {
+      onComplete(false,  "Cannot find a certificate with name " +
+        signatureName.toUri());
+      return;
+    }
+
+    var publicKeyDer = certificate.getPublicKeyInfo().getKeyDer();
+    if (publicKeyDer.isNull()) {
+      // Can't find the public key with the name.
+      onComplete(false, "There is no public key in the certificate with name " +
+        certificate.getName().toUri());
+      return;
+    }
+
+    PolicyManager.verifySignature
+      (signatureInfo, signedBlob, publicKeyDer, function(verified) {
+        if (verified)
+          onComplete(true);
+        else
+          onComplete
+            (false,
+             "The signature did not verify with the given public key");
+      });
+  }
+  else
+    onComplete(false, "The KeyLocator does not have a key name");
+};
+
+ConfigPolicyManager.TrustAnchorRefreshManager =
+  function ConfigPolicyManagerTrustAnchorRefreshManager()
+{
+  this.certificateCache = new CertificateCache();
+  // Maps the directory name to certificate names so they can be deleted when
+  // necessary. The key is the directory name string. The value is the object
+  //  {certificateNames,  // array of string
+  //   nextRefresh,       // number
+  //   refreshPeriod      // number
+  //  }.
+  this.refreshDirectories = {};
+};
+
+ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile =
+  function(fileName)
+{
+  var encodedData = fs.readFileSync(fileName).toString();
+  var decodedData = new Buffer(encodedData, 'base64');
+  var cert = new IdentityCertificate();
+  cert.wireDecode(new Blob(decodedData, false));
+  return cert;
+};
+
+ConfigPolicyManager.TrustAnchorRefreshManager.prototype.getCertificate = function
+  (certificateName)
+{
+  // This assumes the timestamp is already removed.
+  return this.certificateCache.getCertificate(certificateName);
+};
+
+// refreshPeriod in milliseconds.
+ConfigPolicyManager.TrustAnchorRefreshManager.prototype.addDirectory = function
+  (directoryName, refreshPeriod)
+{
+  var allFiles;
+  try {
+    allFiles = fs.readdirSync(directoryName);
+  }
+  catch (e) {
+    throw new SecurityException(new Error
+      ("Cannot list files in directory " + directoryName));
+  }
+
+  var certificateNames = [];
+  for (var i = 0; i < allFiles.length; ++i) {
+    var cert;
+    try {
+      var fullPath = path.join(directoryName, allFiles[i]);
+      cert = ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile
+        (fullPath);
+    }
+    catch (e) {
+      // Allow files that are not certificates.
+      continue;
+    }
+
+    // Cut off the timestamp so it matches the KeyLocator Name format.
+    var certUri = cert.getName().getPrefix(-1).toUri();
+    this.certificateCache.insertCertificate(cert);
+    certificateNames.push(certUri);
+  }
+
+  this.refreshDirectories[directoryName] = {
+    certificates: certificateNames,
+    nextRefresh: new Date().getTime() + refreshPeriod,
+    refreshPeriod: refreshPeriod };
+};
+
+ConfigPolicyManager.TrustAnchorRefreshManager.prototype.refreshAnchors = function()
+{
+  var refreshTime =  new Date().getTime();
+  for (var directory in this.refreshDirectories) {
+    var info = this.refreshDirectories[directory];
+    var nextRefreshTime = info.nextRefresh;
+    if (nextRefreshTime <= refreshTime) {
+      var certificateList = info.certificates.slice(0);
+      // Delete the certificates associated with this directory if possible
+      //   then re-import.
+      // IdentityStorage subclasses may not support deletion.
+      for (var c in certificateList)
+        this.certificateCache.deleteCertificate(new Name(c));
+
+      this.addDirectory(directory, info.refreshPeriod);
+    }
+  }
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
+var NdnCommon = require('../../util/ndn-common.js').NdnCommon;
+
+/**
+ * @constructor
+ */
+var NoVerifyPolicyManager = function NoVerifyPolicyManager()
+{
+  // Call the base constructor.
+  PolicyManager.call(this);
+};
+
+NoVerifyPolicyManager.prototype = new PolicyManager();
+NoVerifyPolicyManager.prototype.name = "NoVerifyPolicyManager";
+
+exports.NoVerifyPolicyManager = NoVerifyPolicyManager;
+
+/**
+ * Override to always skip verification and trust as valid.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} True.
+ */
+NoVerifyPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
+{
+  return true;
+};
+
+/**
+ * Override to return false for no verification rule for the received data or
+ * signed interest.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} False.
+ */
+NoVerifyPolicyManager.prototype.requireVerify = function(dataOrInterest)
+{
+  return false;
+};
+
+/**
+ * Override to call onVerified(data) and to indicate no further verification
+ * step.
+ *
+ * @param {Data|Interest} dataOrInterest The Data object or interest with the
+ * signature to check.
+ * @param {number} stepCount The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @param {function} onVerified This does override to call
+ * onVerified(dataOrInterest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed Override to ignore this.
+ * @param {WireFormat} wireFormat
+ * @return {ValidationRequest} null for no further step for looking up a
+ * certificate chain.
+ */
+NoVerifyPolicyManager.prototype.checkVerificationPolicy = function
+  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
+{
+  try {
+    onVerified(dataOrInterest);
+  } catch (ex) {
+    console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+  return null;
+};
+
+/**
+ * Override to always indicate that the signing certificate name and data name
+ * satisfy the signing policy.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @param {Name} certificateName The name of signing certificate.
+ * @return {boolean} True to indicate that the signing certificate can be used
+ * to sign the data.
+ */
+NoVerifyPolicyManager.prototype.checkSigningPolicy = function
+  (dataName, certificateName)
+{
+  return true;
+};
+
+/**
+ * Override to indicate that the signing identity cannot be inferred.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @return {Name} An empty name because cannot infer.
+ */
+NoVerifyPolicyManager.prototype.inferSigningIdentity = function(dataName)
+{
+  return new Name();
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var Interest = require('../../interest.js').Interest; /** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
+var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
+var NdnCommon = require('../../util/ndn-common.js').NdnCommon;
+
+/**
+ * A SelfVerifyPolicyManager implements a PolicyManager to look in the
+ * IdentityStorage for the public key with the name in the KeyLocator (if
+ * available) and use it to verify the data packet, without searching a
+ * certificate chain.  If the public key can't be found, the verification fails.
+ *
+ * @param {IdentityStorage} identityStorage (optional) The IdentityStorage for
+ * looking up the public key. This object must remain valid during the life of
+ * this SelfVerifyPolicyManager. If omitted, then don't look for a public key
+ * with the name in the KeyLocator and rely on the KeyLocator having the full
+ * public key DER.
+ * @constructor
+ */
+var SelfVerifyPolicyManager = function SelfVerifyPolicyManager(identityStorage)
+{
+  // Call the base constructor.
+  PolicyManager.call(this);
+
+  this.identityStorage = identityStorage;
+};
+
+SelfVerifyPolicyManager.prototype = new PolicyManager();
+SelfVerifyPolicyManager.prototype.name = "SelfVerifyPolicyManager";
+
+exports.SelfVerifyPolicyManager = SelfVerifyPolicyManager;
+
+/**
+ * Never skip verification.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} False.
+ */
+SelfVerifyPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
+{
+  return false;
+};
+
+/**
+ * Always return true to use the self-verification rule for the received data.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} True.
+ */
+SelfVerifyPolicyManager.prototype.requireVerify = function(dataOrInterest)
+{
+  return true;
+};
+
+/**
+ * Look in the IdentityStorage for the public key with the name in the
+ * KeyLocator (if available) and use it to verify the data packet.  If the
+ * public key can't be found, call onValidationFailed.
+ *
+ * @param {Data|Interest} dataOrInterest The Data object or interest with the
+ * signature to check.
+ * @param {number} stepCount The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(dataOrInterest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(dataOrInterest, reason).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {WireFormat} wireFormat
+ * @return {ValidationRequest} null for no further step for looking up a
+ * certificate chain.
+ */
+SelfVerifyPolicyManager.prototype.checkVerificationPolicy = function
+  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (dataOrInterest instanceof Data) {
+    var data = dataOrInterest;
+    // wireEncode returns the cached encoding if available.
+    this.verify(data.getSignature(), data.wireEncode(), function(verified, reason) {
+      if (verified) {
+        try {
+          onVerified(data);
+        } catch (ex) {
+          console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+      else {
+        try {
+          onValidationFailed(data, reason);
+        } catch (ex) {
+          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+    });
+  }
+  else if (dataOrInterest instanceof Interest) {
+    var interest = dataOrInterest;
+
+    if (interest.getName().size() < 2) {
+      try {
+        onValidationFailed
+          (interest, "The signed interest has less than 2 components: " +
+             interest.getName().toUri());
+      } catch (ex) {
+        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return;
+    }
+
+    // Decode the last two name components of the signed interest
+    var signature;
+    try {
+      signature = wireFormat.decodeSignatureInfoAndValue
+        (interest.getName().get(-2).getValue().buf(),
+         interest.getName().get(-1).getValue().buf(), false);
+    } catch (ex) {
+      try {
+        onValidationFailed
+          (interest, "Error decoding the signed interest signature: " + ex);
+      } catch (ex) {
+        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return;
+    }
+
+    // wireEncode returns the cached encoding if available.
+    this.verify(signature, interest.wireEncode(), function(verified, reason) {
+      if (verified) {
+        try {
+          onVerified(interest);
+        } catch (ex) {
+          console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+      else {
+        try {
+          onValidationFailed(interest, reason);
+        } catch (ex) {
+          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+    });
+  }
+  else
+    throw new SecurityException(new Error
+      ("checkVerificationPolicy: unrecognized type for dataOrInterest"));
+
+  // No more steps, so return null.
+  return null;
+};
+
+/**
+ * Override to always indicate that the signing certificate name and data name
+ * satisfy the signing policy.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @param {Name} certificateName The name of signing certificate.
+ * @return {boolean} True to indicate that the signing certificate can be used
+ * to sign the data.
+ */
+SelfVerifyPolicyManager.prototype.checkSigningPolicy = function
+  (dataName, certificateName)
+{
+  return true;
+};
+
+/**
+ * Override to indicate that the signing identity cannot be inferred.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @return {Name} An empty name because cannot infer.
+ */
+SelfVerifyPolicyManager.prototype.inferSigningIdentity = function(dataName)
+{
+  return new Name();
+};
+
+/**
+ * Check the type of signatureInfo to get the KeyLocator. Look in the
+ * IdentityStorage for the public key with the name in the KeyLocator (if
+ * available) and use it to verify the signedBlob. If the public key can't be
+ * found, return false. (This is a generalized method which can verify both a
+ * Data packet and an interest.)
+ * @param {Signature} signatureInfo An object of a subclass of Signature, e.g.
+ * Sha256WithRsaSignature.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {function} onComplete This calls onComplete(true, undefined) if the
+ * signature verifies, otherwise onComplete(false, reason).
+ */
+SelfVerifyPolicyManager.prototype.verify = function
+  (signatureInfo, signedBlob, onComplete)
+{
+  if (KeyLocator.canGetFromSignature(signatureInfo)) {
+    this.getPublicKeyDer
+      (KeyLocator.getFromSignature(signatureInfo), function(publicKeyDer, reason) {
+        if (publicKeyDer.isNull())
+          onComplete(false, reason);
+        else {
+          try {
+            PolicyManager.verifySignature
+              (signatureInfo, signedBlob, publicKeyDer, function(verified) {
+                if (verified)
+                  onComplete(true);
+                else
+                  onComplete
+                    (false,
+                     "The signature did not verify with the given public key");
+              });
+          } catch (ex) {
+            onComplete(false, "Error in verifySignature: " + ex);
+          }
+        }
+      });
+  }
+  else {
+    try {
+      // Assume that the signature type does not require a public key.
+      PolicyManager.verifySignature
+        (signatureInfo, signedBlob, null, function(verified) {
+          if (verified)
+            onComplete(true);
+          else
+            onComplete
+              (false, "The signature did not verify with the given public key");
+        });
+    } catch (ex) {
+      onComplete(false, "Error in verifySignature: " + ex);
+    }
+  }
+};
+
+/**
+ * Look in the IdentityStorage for the public key with the name in the
+ * KeyLocator (if available). If the public key can't be found, return and empty
+ * Blob.
+ * @param {KeyLocator} keyLocator The KeyLocator.
+ * @param {function} onComplete This calls 
+ * onComplete(publicKeyDer, reason) where publicKeyDer is the public key
+ * DER Blob or an isNull Blob if not found and reason is the reason
+ * string if not found.
+ */
+SelfVerifyPolicyManager.prototype.getPublicKeyDer = function
+  (keyLocator, onComplete)
+{
+  if (keyLocator.getType() == KeyLocatorType.KEYNAME &&
+      this.identityStorage != null) {
+    var keyName;
+    try {
+      // Assume the key name is a certificate name.
+      keyName = IdentityCertificate.certificateNameToPublicKeyName
+        (keyLocator.getKeyName());
+    } catch (ex) {
+      onComplete
+        (new Blob(), "Cannot get a public key name from the certificate named: " +
+           keyLocator.getKeyName().toUri());
+      return;
+    }
+    SyncPromise.complete
+      (onComplete,
+       function(err) {
+         // The storage doesn't have the key.
+         onComplete
+           (new Blob(), "The identityStorage doesn't have the key named " +
+              keyName.toUri());
+       },
+       this.identityStorage.getKeyPromise(keyName));
+  }
+  else
+    // Can't find a key to verify.
+    onComplete(new Blob(), "The signature KeyLocator doesn't have a key name");
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('../crypto.js'); /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
+var SecurityException = require('./security-exception.js').SecurityException; /** @ignore */
+var RsaKeyParams = require('./key-params.js').RsaKeyParams; /** @ignore */
+var IdentityCertificate = require('./certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
+var IdentityManager = require('./identity/identity-manager.js').IdentityManager; /** @ignore */
+var NoVerifyPolicyManager = require('./policy/no-verify-policy-manager.js').NoVerifyPolicyManager;
+
+/**
+ * A KeyChain provides a set of interfaces to the security library such as
+ * identity management, policy configuration and packet signing and verification.
+ * Note: This class is an experimental feature. See the API docs for more detail at
+ * http://named-data.net/doc/ndn-ccl-api/key-chain.html .
+ *
+ * Create a new KeyChain with the identityManager and policyManager.
+ * @param {IdentityManager} identityManager (optional) The identity manager as a
+ * subclass of IdentityManager. If omitted, use the default IdentityManager
+ * constructor.
+ * @param {PolicyManager} policyManager (optional) The policy manager as a
+ * subclass of PolicyManager. If omitted, use NoVerifyPolicyManager.
+ * @throws SecurityException if this is not in Node.js and this uses the default
+ * IdentityManager constructor. (See IdentityManager for details.)
+ * @constructor
+ */
+var KeyChain = function KeyChain(identityManager, policyManager)
+{
+  if (!identityManager)
+    identityManager = new IdentityManager();
+  if (!policyManager)
+    policyManager = new NoVerifyPolicyManager();
+
+  this.identityManager = identityManager;
+  this.policyManager = policyManager;
+  this.face = null;
+};
+
+exports.KeyChain = KeyChain;
+
+/*****************************************
+ *          Identity Management          *
+ *****************************************/
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @param {Name} identityName The name of the identity.
+ * @param {KeyParams} params (optional) The key parameters if a key needs to be
+ * generated for the identity. If omitted, use KeyChain.DEFAULT_KEY_PARAMS.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with name of the default certificate of the identity. If omitted, the return
+ * value is described below. (Some crypto libraries only use a callback, so
+ * onComplete is required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {Name} If onComplete is omitted, return the name of the default
+ * certificate of the identity. Otherwise, if onComplete is supplied then return
+ * undefined and use onComplete as described above.
+ */
+KeyChain.prototype.createIdentityAndCertificate = function
+  (identityName, params, onComplete, onError)
+{
+  onError = (typeof params === "function") ? onComplete : onError;
+  onComplete = (typeof params === "function") ? params : onComplete;
+  params = (typeof params === "function" || !params) ?
+    KeyChain.DEFAULT_KEY_PARAMS : params;
+
+  return this.identityManager.createIdentityAndCertificate
+    (identityName, params, onComplete, onError);
+};
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @deprecated Use createIdentityAndCertificate which returns the
+ * certificate name instead of the key name. You can use
+ * IdentityCertificate.certificateNameToPublicKeyName to convert the
+ * certificate name to the key name.
+ * @param {Name} identityName The name of the identity.
+ * @param {KeyParams} params (optional) The key parameters if a key needs to be
+ * generated for the identity. If omitted, use KeyChain.DEFAULT_KEY_PARAMS.
+ * @return {Name} The key name of the auto-generated KSK of the identity.
+ */
+KeyChain.prototype.createIdentity = function(identityName, params)
+{
+  return IdentityCertificate.certificateNameToPublicKeyName
+    (this.createIdentityAndCertificate(identityName, params));
+};
+
+/**
+ * Delete the identity from the public and private key storage. If the
+ * identity to be deleted is the current default system default, this will not
+ * delete the identity and will return immediately.
+ * @param {Name} identityName The name of the identity.
+ * @param {function} onComplete (optional) This calls onComplete() when the
+ * operation is complete. If omitted, do not use it. (Some database libraries
+ * only use a callback, so onComplete is required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.deleteIdentity = function
+  (identityName, onComplete, onError)
+{
+  this.identityManager.deleteIdentity(identityName, onComplete, onError);
+};
+
+/**
+ * Get the default identity.
+ * @param {function} onComplete (optional) This calls onComplete(identityName)
+ * with name of the default identity. If omitted, the return value is described
+ * below. (Some crypto libraries only use a callback, so onComplete is required
+ * to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the name of the default
+ * identity. Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @throws SecurityException if the default identity is not set. However, if
+ * onComplete and onError are defined, then if there is an exception return
+ * undefined and call onError(exception).
+ */
+KeyChain.prototype.getDefaultIdentity = function(onComplete, onError)
+{
+  return this.identityManager.getDefaultIdentity(onComplete, onError);
+};
+
+/**
+ * Get the default certificate name of the default identity, which will be used
+ * when signing is based on identity and the identity is not specified.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with name of the default certificate. If omitted, the return value is described
+ * below. (Some crypto libraries only use a callback, so onComplete is required
+ * to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {Name} If onComplete is omitted, return the default certificate name.
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete
+ * as described above.
+ * @throws SecurityException if the default identity is not set or the default
+ * key name for the identity is not set or the default certificate name for
+ * the key name is not set. However, if onComplete and onError are defined, then
+ * if there is an exception return undefined and call onError(exception).
+ */
+KeyChain.prototype.getDefaultCertificateName = function(onComplete, onError)
+{
+  return this.identityManager.getDefaultCertificateName(onComplete, onError);
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk (optional) true for generating a Key-Signing-Key (KSK),
+ * false for a Data-Signing-Key (DSK). If omitted, generate a Data-Signing-Key.
+ * @param {number} keySize (optional) The size of the key. If omitted, use a
+ * default secure key size.
+ * @return {Name} The generated key name.
+ */
+KeyChain.prototype.generateRSAKeyPair = function(identityName, isKsk, keySize)
+{
+  keySize = (typeof isKsk === "boolean") ? isKsk : keySize;
+  isKsk = (typeof isKsk === "boolean") ? isKsk : false;
+
+  if (!keySize)
+    keySize = 2048;
+
+  return this.identityManager.generateRSAKeyPair(identityName, isKsk, keySize);
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.setDefaultKeyForIdentity = function
+  (keyName, identityNameCheck, onComplete, onError)
+{
+  return this.identityManager.setDefaultKeyForIdentity
+    (keyName, identityNameCheck, onComplete, onError);
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity and set it as default
+ * key for the identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk (optional) true for generating a Key-Signing-Key (KSK),
+ * false for a Data-Signing-Key (DSK). If omitted, generate a Data-Signing-Key.
+ * @param {number} keySize (optional) The size of the key. If omitted, use a
+ * default secure key size.
+ * @return {Name} The generated key name.
+ */
+KeyChain.prototype.generateRSAKeyPairAsDefault = function
+  (identityName, isKsk, keySize)
+{
+  return this.identityManager.generateRSAKeyPairAsDefault
+    (identityName, isKsk, keySize);
+};
+
+/**
+ * Create a public key signing request.
+ * @param {Name} keyName The name of the key.
+ * @return {Blob} The signing request data.
+ */
+KeyChain.prototype.createSigningRequest = function(keyName)
+{
+  return this.identityManager.getPublicKey(keyName).getKeyDer();
+};
+
+/**
+ * Install an identity certificate into the public key identity storage.
+ * @param {IdentityCertificate} certificate The certificate to to added.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.installIdentityCertificate = function
+  (certificate, onComplete, onError)
+{
+  this.identityManager.addCertificate(certificate, onComplete, onError);
+};
+
+/**
+ * Set the certificate as the default for its corresponding key.
+ * @param {IdentityCertificate} certificate The certificate.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.setDefaultCertificateForKey = function
+  (certificate, onComplete, onError)
+{
+  this.identityManager.setDefaultCertificateForKey
+    (certificate, onComplete, onError);
+};
+
+/**
+ * Get a certificate which is still valid with the specified name.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @param {function} onComplete (optional) This calls onComplete(certificate)
+ * with the requested IdentityCertificate. If omitted, the return value is 
+ * described below. (Some crypto libraries only use a callback, so onComplete is
+ * required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {IdentityCertificate} If onComplete is omitted, return the requested
+ * certificate. Otherwise, if onComplete is supplied then return undefined and
+ * use onComplete as described above.
+ */
+KeyChain.prototype.getCertificate = function
+  (certificateName, onComplete, onError)
+{
+  return this.identityManager.getCertificate
+    (certificateName, onComplete, onError);
+};
+
+/**
+ * @deprecated Use getCertificate.
+ */
+KeyChain.prototype.getIdentityCertificate = function
+  (certificateName, onComplete, onError)
+{
+  return this.identityManager.getCertificate
+    (certificateName, onComplete, onError);
+};
+
+/**
+ * Revoke a key.
+ * @param {Name} keyName The name of the key that will be revoked.
+ */
+KeyChain.prototype.revokeKey = function(keyName)
+{
+  //TODO: Implement
+};
+
+/**
+ * Revoke a certificate.
+ * @param {Name} certificateName The name of the certificate that will be
+ * revoked.
+ */
+KeyChain.prototype.revokeCertificate = function(certificateName)
+{
+  //TODO: Implement
+};
+
+/**
+ * Get the identity manager given to or created by the constructor.
+ * @return {IdentityManager} The identity manager.
+ */
+KeyChain.prototype.getIdentityManager = function()
+{
+  return this.identityManager;
+};
+
+/*****************************************
+ *           Policy Management           *
+ *****************************************/
+
+/**
+ * Get the policy manager given to or created by the constructor.
+ * @return {PolicyManager} The policy manager.
+ */
+KeyChain.prototype.getPolicyManager = function()
+{
+  return this.policyManager;
+};
+
+/*****************************************
+ *              Sign/Verify              *
+ *****************************************/
+
+/**
+ * Sign the target. If it is a Data or Interest object, set its signature. If it
+ * is an array, produce a Signature object. There are two forms of sign:
+ * sign(target, certificateName [, wireFormat] [, onComplete] [, onError]).
+ * sign(target [, wireFormat] [, onComplete] [, onError]).
+ * @param {Data|Interest|Buffer} target If this is a Data object, wire encode for
+ * signing, update its signature and key locator field and wireEncoding. If this
+ * is an Interest object, wire encode for signing, append a SignatureInfo to the
+ * Interest name, sign the name components and append a final name component
+ * with the signature bits. If it is an array, sign it and produce a Signature
+ * object.
+ * @param {Name} certificateName (optional) The certificate name of the key to
+ * use for signing. If omitted, use the default identity in the identity storage.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {function} onComplete (optional) If target is a Data object, this calls
+ * onComplete(data) with the supplied Data object which has been modified to set
+ * its signature. If target is an Interest object, this calls
+ * onComplete(interest) with the supplied Interest object which has been
+ * modified to set its signature. If target is a Buffer, this calls
+ * onComplete(signature) where signature is the produced Signature object. If
+ * omitted, the return value is described below. (Some crypto libraries only use
+ * a callback, so onComplete is required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {Signature} If onComplete is omitted, return the generated Signature
+ * object (if target is a Buffer) or the target (if target is Data or Interest).
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete as
+ * described above.
+ */
+KeyChain.prototype.sign = function
+  (target, certificateName, wireFormat, onComplete, onError)
+{
+  var arg2 = certificateName;
+  var arg3 = wireFormat;
+  var arg4 = onComplete;
+  var arg5 = onError;
+  // arg2,            arg3,       arg4,       arg5
+  // certificateName, wireFormat, onComplete, onError
+  // certificateName, wireFormat, null,       null
+  // certificateName, onComplete, onError,    null
+  // certificateName, null,       null,       null
+  // wireFormat,      onComplete, onError,    null
+  // wireFormat,      null,       null,       null
+  // onComplete,      onError,    null,       null
+  // null,            null,       null,       null
+  if (arg2 instanceof Name)
+    certificateName = arg2;
+  else
+    certificateName = null;
+
+  if (arg2 instanceof WireFormat)
+    wireFormat = arg2;
+  else if (arg3 instanceof WireFormat)
+    wireFormat = arg3;
+  else
+    wireFormat = null;
+
+  if (typeof arg2 === "function") {
+    onComplete = arg2;
+    onError = arg3;
+  }
+  else if (typeof arg3 === "function") {
+    onComplete = arg3;
+    onError = arg4;
+  }
+  else if (typeof arg4 === "function") {
+    onComplete = arg4;
+    onError = arg5;
+  }
+  else {
+    onComplete = null;
+    onError = null;
+  }
+
+  return SyncPromise.complete(onComplete, onError,
+    this.signPromise(target, certificateName, wireFormat, !onComplete));
+};
+
+/**
+ * Sign the target. If it is a Data or Interest object, set its signature. If it
+ * is an array, produce a Signature object. There are two forms of signPromise:
+ * signPromise(target, certificateName [, wireFormat] [, useSync]).
+ * sign(target [, wireFormat] [, useSync]).
+ * @param {Data|Interest|Buffer} target If this is a Data object, wire encode for
+ * signing, update its signature and key locator field and wireEncoding. If this
+ * is an Interest object, wire encode for signing, append a SignatureInfo to the
+ * Interest name, sign the name components and append a final name component
+ * with the signature bits. If it is an array, sign it and produce a Signature
+ * object.
+ * @param {Name} certificateName (optional) The certificate name of the key to
+ * use for signing. If omitted, use the default identity in the identity storage.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the generated Signature
+ * object (if target is a Buffer) or the target (if target is Data or Interest).
+ */
+KeyChain.prototype.signPromise = function
+  (target, certificateName, wireFormat, useSync)
+{
+  var arg2 = certificateName;
+  var arg3 = wireFormat;
+  var arg4 = useSync;
+  // arg2,            arg3,       arg4
+  // certificateName, wireFormat, useSync
+  // certificateName, wireFormat, null
+  // certificateName, useSync,    null
+  // certificateName, null,       null
+  // wireFormat,      useSync,    null
+  // wireFormat,      null,       null
+  // useSync,         null,       null
+  // null,            null,       null
+  if (arg2 instanceof Name)
+    certificateName = arg2;
+  else
+    certificateName = null;
+
+  if (arg2 instanceof WireFormat)
+    wireFormat = arg2;
+  else if (arg3 instanceof WireFormat)
+    wireFormat = arg3;
+  else
+    wireFormat = null;
+
+  if (typeof arg2 === 'boolean')
+    useSync = arg2;
+  else if (typeof arg3 === 'boolean')
+    useSync = arg3;
+  else if (typeof arg4 === 'boolean')
+    useSync = arg4;
+  else
+    useSync = false;
+
+  var thisKeyChain = this;
+  return SyncPromise.resolve()
+  .then(function() {
+    if (certificateName != null)
+      return SyncPromise.resolve();
+
+    // Get the default certificate name.
+    return thisKeyChain.identityManager.getDefaultCertificatePromise(useSync)
+    .then(function(signingCertificate) {
+      if (signingCertificate != null) {
+        certificateName = signingCertificate.getName();
+        return SyncPromise.resolve();
+      }
+
+      // Set the default certificate and default certificate name again.
+      return thisKeyChain.prepareDefaultCertificateNamePromise_(useSync)
+      .then(function(localCertificateName) {
+        certificateName =localCertificateName;
+        return SyncPromise.resolve();
+      });
+    });
+  })
+  .then(function() {
+    // certificateName is now set. Do the actual signing.
+    if (target instanceof Interest)
+      return thisKeyChain.identityManager.signInterestByCertificatePromise
+        (target, certificateName, wireFormat, useSync);
+    else if (target instanceof Data)
+      return thisKeyChain.identityManager.signByCertificatePromise
+        (target, certificateName, wireFormat, useSync);
+    else
+      return thisKeyChain.identityManager.signByCertificatePromise
+        (target, certificateName, useSync);
+  });
+};
+
+/**
+ * Sign the target. If it is a Data object, set its signature. If it is an
+ * array, produce a signature object.
+ * @param {Data|Buffer} target If this is a Data object, wire encode for
+ * signing, update its signature and key locator field and wireEncoding. If it
+ * is an array, sign it and return a Signature object.
+ * @param {Name} identityName (optional) The identity name for the key to use for
+ * signing.  If omitted, infer the signing identity from the data packet name.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {function} onComplete (optional) If target is a Data object, this calls
+ * onComplete(data) with the supplied Data object which has been modified to set
+ * its signature. If target is a Buffer, this calls
+ * onComplete(signature) where signature is the produced Signature object. If
+ * omitted, the return value is described below. (Some crypto libraries only use
+ * a callback, so onComplete is required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {Signature} If onComplete is omitted, return the generated Signature
+ * object (if target is a Buffer) or undefined (if target is Data).
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete
+ * as described above.
+ */
+KeyChain.prototype.signByIdentity = function
+  (target, identityName, wireFormat, onComplete, onError)
+{
+  onError = (typeof wireFormat === "function") ? onComplete : onError;
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  var useSync = !onComplete;
+  var thisKeyChain = this;
+
+  if (identityName == null)
+    identityName = new Name();
+
+  if (target instanceof Data) {
+    var data = target;
+
+    var mainPromise = SyncPromise.resolve()
+    .then(function() {
+      if (identityName.size() == 0) {
+        var inferredIdentity = thisKeyChain.policyManager.inferSigningIdentity
+          (data.getName());
+        if (inferredIdentity.size() == 0)
+          return thisKeyChain.identityManager.getDefaultCertificateNamePromise
+            (useSync);
+        else
+          return thisKeyChain.identityManager.getDefaultCertificateNameForIdentityPromise
+              (inferredIdentity, useSync);
+      }
+      else
+        return thisKeyChain.identityManager.getDefaultCertificateNameForIdentityPromise
+          (identityName, useSync);
+    })
+    .then(function(signingCertificateName) {
+      if (signingCertificateName.size() == 0)
+        throw new SecurityException(new Error
+          ("No qualified certificate name found!"));
+
+      if (!thisKeyChain.policyManager.checkSigningPolicy
+           (data.getName(), signingCertificateName))
+        throw new SecurityException(new Error
+          ("Signing Cert name does not comply with signing policy"));
+
+      return thisKeyChain.identityManager.signByCertificatePromise
+        (data, signingCertificateName, wireFormat, useSync);
+    });
+
+    return SyncPromise.complete(onComplete, onError, mainPromise);
+  }
+  else {
+    var array = target;
+
+    return SyncPromise.complete(onComplete, onError,
+      this.identityManager.getDefaultCertificateNameForIdentityPromise
+        (identityName, useSync)
+      .then(function(signingCertificateName) {
+        if (signingCertificateName.size() == 0)
+          throw new SecurityException(new Error
+            ("No qualified certificate name found!"));
+
+        return thisKeyChain.identityManager.signByCertificatePromise
+          (array, signingCertificateName, wireFormat, useSync);
+      }));
+  }
+};
+
+/**
+ * Sign the target using DigestSha256.
+ * @param {Data|Interest} target If this is a Data object, wire encode for
+ * signing, digest it and set its SignatureInfo to a DigestSha256, updating its
+ * signature and wireEncoding. If this is an Interest object, wire encode for
+ * signing, append a SignatureInfo for DigestSha256 to the Interest name, digest
+ * the name components and append a final name component with the signature bits.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ */
+KeyChain.prototype.signWithSha256 = function(target, wireFormat)
+{
+  if (target instanceof Interest)
+    this.identityManager.signInterestWithSha256(target, wireFormat);
+  else
+    this.identityManager.signWithSha256(target, wireFormat);
+};
+
+/**
+ * Check the signature on the Data object and call either onVerify or
+ * onValidationFailed. We use callback functions because verify may fetch
+ * information to check the signature.
+ * @param {Data} data The Data object with the signature to check.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(data).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(data, reason) with the Data object and reason string.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {number} stepCount
+ */
+KeyChain.prototype.verifyData = function
+  (data, onVerified, onValidationFailed, stepCount)
+{
+  if (stepCount == null)
+    stepCount = 0;
+
+  if (this.policyManager.requireVerify(data)) {
+    var nextStep = this.policyManager.checkVerificationPolicy
+      (data, stepCount, onVerified, onValidationFailed);
+    if (nextStep != null) {
+      var thisKeyChain = this;
+      this.face.expressInterest
+        (nextStep.interest,
+         function(callbackInterest, callbackData) {
+           thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
+         },
+         function(callbackInterest) {
+           thisKeyChain.onCertificateInterestTimeout
+             (callbackInterest, nextStep.retry, onValidationFailed, data, nextStep);
+         });
+    }
+  }
+  else if (this.policyManager.skipVerifyAndTrust(data)) {
+    try {
+      onVerified(data);
+    } catch (ex) {
+      console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+  else {
+    try {
+      onValidationFailed
+        (data, "The packet has no verify rule but skipVerifyAndTrust is false");
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Check the signature on the signed interest and call either onVerify or
+ * onValidationFailed. We use callback functions because verify may fetch
+ * information to check the signature.
+ * @param {Interest} interest The interest with the signature to check.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(interest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(interest, reason) with the Interest object and reason
+ * string.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.verifyInterest = function
+  (interest, onVerified, onValidationFailed, stepCount, wireFormat)
+{
+  if (stepCount == null)
+    stepCount = 0;
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (this.policyManager.requireVerify(interest)) {
+    var nextStep = this.policyManager.checkVerificationPolicy
+      (interest, stepCount, onVerified, onValidationFailed, wireFormat);
+    if (nextStep != null) {
+      var thisKeyChain = this;
+      this.face.expressInterest
+        (nextStep.interest,
+         function(callbackInterest, callbackData) {
+           thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
+         },
+         function(callbackInterest) {
+           thisKeyChain.onCertificateInterestTimeout
+             (callbackInterest, nextStep.retry, onValidationFailed, interest,
+              nextStep);
+         });
+    }
+  }
+  else if (this.policyManager.skipVerifyAndTrust(interest)) {
+    try {
+      onVerified(interest);
+    } catch (ex) {
+      console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+  else {
+    try {
+      onValidationFailed
+        (interest,
+         "The packet has no verify rule but skipVerifyAndTrust is false");
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Set the Face which will be used to fetch required certificates.
+ * @param {Face} face A pointer to the Face object.
+ */
+KeyChain.prototype.setFace = function(face)
+{
+  this.face = face;
+};
+
+/**
+ * Wire encode the target, compute an HmacWithSha256 and update the signature
+ * value.
+ * Note: This method is an experimental feature. The API may change.
+ * @param {Data} target If this is a Data object, update its signature and wire
+ * encoding.
+ * @param {Blob} key The key for the HmacWithSha256.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the target. If omitted, use WireFormat getDefaultWireFormat().
+ */
+KeyChain.signWithHmacWithSha256 = function(target, key, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (target instanceof Data) {
+    var data = target;
+    // Encode once to get the signed portion.
+    var encoding = data.wireEncode(wireFormat);
+
+    var signer = Crypto.createHmac('sha256', key.buf());
+    signer.update(encoding.signedBuf());
+    data.getSignature().setSignature(
+      new Blob(signer.digest(), false));
+  }
+  else
+    throw new SecurityException(new Error
+      ("signWithHmacWithSha256: Unrecognized target type"));
+};
+
+/**
+ * Compute a new HmacWithSha256 for the target and verify it against the
+ * signature value.
+ * Note: This method is an experimental feature. The API may change.
+ * @param {Data} target The Data object to verify.
+ * @param {Blob} key The key for the HmacWithSha256.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the target. If omitted, use WireFormat getDefaultWireFormat().
+ * @return {boolean} True if the signature verifies, otherwise false.
+ */
+KeyChain.verifyDataWithHmacWithSha256 = function(data, key, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  // wireEncode returns the cached encoding if available.
+  var encoding = data.wireEncode(wireFormat);
+
+  var signer = Crypto.createHmac('sha256', key.buf());
+  signer.update(encoding.signedBuf());
+  var newSignatureBits = new Blob(signer.digest(), false);
+
+  // Use the flexible Blob.equals operator.
+  return newSignatureBits.equals(data.getSignature().getSignature());
+};
+
+KeyChain.DEFAULT_KEY_PARAMS = new RsaKeyParams();
+
+KeyChain.prototype.onCertificateData = function(interest, data, nextStep)
+{
+  // Try to verify the certificate (data) according to the parameters in nextStep.
+  this.verifyData
+    (data, nextStep.onVerified, nextStep.onValidationFailed, nextStep.stepCount);
+};
+
+KeyChain.prototype.onCertificateInterestTimeout = function
+  (interest, retry, onValidationFailed, originalDataOrInterest, nextStep)
+{
+  if (retry > 0) {
+    // Issue the same expressInterest as in verifyData except decrement retry.
+    var thisKeyChain = this;
+    this.face.expressInterest
+      (interest,
+       function(callbackInterest, callbackData) {
+         thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
+       },
+       function(callbackInterest) {
+         thisKeyChain.onCertificateInterestTimeout
+           (callbackInterest, retry - 1, onValidationFailed,
+            originalDataOrInterest, nextStep);
+       });
+  }
+  else {
+    try {
+      onValidationFailed
+        (originalDataOrInterest, "The retry count is zero after timeout for fetching " +
+          interest.getName().toUri());
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Get the default certificate from the identity storage and return its name.
+ * If there is no default identity or default certificate, then create one.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the default certificate
+ * name.
+ */
+KeyChain.prototype.prepareDefaultCertificateNamePromise_ = function(useSync)
+{
+  var signingCertificate;
+  var thisKeyChain = this;
+  return this.identityManager.getDefaultCertificatePromise(useSync)
+  .then(function(localCertificate) {
+    signingCertificate = localCertificate;
+    if (signingCertificate != null)
+      return SyncPromise.resolve();
+
+    // Set the default certificate and get the certificate again.
+    return thisKeyChain.setDefaultCertificatePromise_(useSync)
+    .then(function() {
+      return thisKeyChain.identityManager.getDefaultCertificatePromise(useSync);
+    })
+    .then(function(localCertificate) {
+      signingCertificate = localCertificate;
+      return SyncPromise.resolve();
+    });
+  })
+  .then(function() {
+    return SyncPromise.resolve(signingCertificate.getName());
+  });
+}
+
+/**
+ * Create the default certificate if it is not initialized. If there is no
+ * default identity yet, creating a new tmp-identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that resolves when the default
+ * certificate is set.
+ */
+KeyChain.prototype.setDefaultCertificatePromise_ = function(useSync)
+{
+  var thisKeyChain = this;
+
+  return this.identityManager.getDefaultCertificatePromise(useSync)
+  .then(function(certificate) {
+    if (certificate != null)
+      // We already have a default certificate.
+      return SyncPromise.resolve();
+
+    var defaultIdentity;
+    return thisKeyChain.identityManager.getDefaultIdentityPromise(useSync)
+    .then(function(localDefaultIdentity) {
+      defaultIdentity = localDefaultIdentity;
+      return SyncPromise.resolve();
+    }, function(ex) {
+      // Create a default identity name.
+      randomComponent = Crypto.randomBytes(4);
+      defaultIdentity = new Name().append("tmp-identity")
+        .append(new Blob(randomComponent, false));
+
+      return SyncPromise.resolve();
+    })
+    .then(function() {
+      return thisKeyChain.identityManager.createIdentityAndCertificatePromise
+        (defaultIdentity, KeyChain.DEFAULT_KEY_PARAMS, useSync);
+    })
+    .then(function() {
+      return thisKeyChain.identityManager.setDefaultIdentityPromise
+        (defaultIdentity, useSync);
+    });
+  });
+};
+/**
+ * This class represents an Interest Exclude.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * Create a new Exclude.
+ * @constructor
+ * @param {Array<Name.Component|Buffer|Exclude.ANY>} values (optional) An array where each element is either a Name.Component, Buffer component or Exclude.ANY.
+ */
+var Exclude = function Exclude(values)
+{
+  this.values = [];
+
+  if (typeof values === 'object' && values instanceof Exclude)
+    // Copy the exclude.
+    this.values = values.values.slice(0);
+  else if (values) {
+    // Set the changeCount now since append expects it.
+    this.changeCount = 0;
+    for (var i = 0; i < values.length; ++i) {
+      if (values[i] == Exclude.ANY)
+        this.appendAny();
+      else
+        this.appendComponent(values[i]);
+    }
+  }
+
+  this.changeCount = 0;
+};
+
+exports.Exclude = Exclude;
+
+Exclude.ANY = "*";
+
+/**
+ * Get the number of entries.
+ * @return {number} The number of entries.
+ */
+Exclude.prototype.size = function() { return this.values.length; };
+
+/**
+ * Get the entry at the given index.
+ * @param {number} i The index of the entry, starting from 0.
+ * @return {Exclude.ANY|Name.Component} Exclude.ANY or a Name.Component.
+ */
+Exclude.prototype.get = function(i) { return this.values[i]; };
+
+/**
+ * Append an Exclude.ANY element.
+ * @return This Exclude so that you can chain calls to append.
+ */
+Exclude.prototype.appendAny = function()
+{
+  this.values.push(Exclude.ANY);
+  ++this.changeCount;
+  return this;
+};
+
+/**
+ * Append a component entry, copying from component.
+ * @param {Name.Component|Buffer} component
+ * @return This Exclude so that you can chain calls to append.
+ */
+Exclude.prototype.appendComponent = function(component)
+{
+  this.values.push(new Name.Component(component));
+  ++this.changeCount;
+  return this;
+};
+
+/**
+ * Clear all the entries.
+ */
+Exclude.prototype.clear = function()
+{
+  ++this.changeCount;
+  this.values = [];
+};
+
+/**
+ * Return a string with elements separated by "," and Exclude.ANY shown as "*".
+ */
+Exclude.prototype.toUri = function()
+{
+  if (this.values == null || this.values.length == 0)
+    return "";
+
+  var result = "";
+  for (var i = 0; i < this.values.length; ++i) {
+    if (i > 0)
+      result += ",";
+
+    if (this.values[i] == Exclude.ANY)
+      result += "*";
+    else
+      result += this.values[i].toEscapedString();
+  }
+  return result;
+};
+
+/**
+ * Return true if the component matches any of the exclude criteria.
+ */
+Exclude.prototype.matches = function(component)
+{
+  if (!(typeof component == 'object' && component instanceof Name.Component))
+    component = new Name.Component(component);
+
+  for (var i = 0; i < this.values.length; ++i) {
+    if (this.values[i] == Exclude.ANY) {
+      var lowerBound = null;
+      if (i > 0)
+        lowerBound = this.values[i - 1];
+
+      // Find the upper bound, possibly skipping over multiple ANY in a row.
+      var iUpperBound;
+      var upperBound = null;
+      for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
+        if (this.values[iUpperBound] != Exclude.ANY) {
+          upperBound = this.values[iUpperBound];
+          break;
+        }
+      }
+
+      // If lowerBound != null, we already checked component equals lowerBound on the last pass.
+      // If upperBound != null, we will check component equals upperBound on the next pass.
+      if (upperBound != null) {
+        if (lowerBound != null) {
+          if (component.compare(lowerBound) > 0 &&
+              component.compare(upperBound) < 0)
+            return true;
+        }
+        else {
+          if (component.compare(upperBound) < 0)
+            return true;
+        }
+
+        // Make i equal iUpperBound on the next pass.
+        i = iUpperBound - 1;
+      }
+      else {
+        if (lowerBound != null) {
+            if (component.compare(lowerBound) > 0)
+              return true;
+        }
+        else
+          // this.values has only ANY.
+          return true;
+      }
+    }
+    else {
+      if (component.equals(this.values[i]))
+        return true;
+    }
+  }
+
+  return false;
+};
+
+/**
+ * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
+ * A component is less if it is shorter, otherwise if equal length do a byte comparison.
+ */
+Exclude.compareComponents = function(component1, component2)
+{
+  if (typeof component1 == 'object' && component1 instanceof Name.Component)
+    component1 = component1.getValue().buf();
+  if (typeof component2 == 'object' && component2 instanceof Name.Component)
+    component2 = component2.getValue().buf();
+
+  return Name.Component.compareBuffers(component1, component2);
+};
+
+/**
+ * Get the change count, which is incremented each time this object is changed.
+ * @return {number} The change count.
+ */
+Exclude.prototype.getChangeCount = function()
+{
+  return this.changeCount;
+};
+/**
+ * This class represents Interest Objects
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('./crypto.js'); /** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var SignedBlob = require('./util/signed-blob.js').SignedBlob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var Exclude = require('./exclude.js').Exclude; /** @ignore */
+var Link = require('./link.js').Link; /** @ignore */
+var KeyLocator = require('./key-locator.js').KeyLocator; /** @ignore */
+var IncomingFaceId = require('./lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat;
+
+/**
+ * Create a new Interest with the optional values.
+ *
+ * @constructor
+ * @param {Name|Interest} nameOrInterest If this is an Interest, copy values from the interest and ignore the
+ * other arguments.  Otherwise this is the optional name for the new Interest.
+ * @param {number} minSuffixComponents
+ * @param {number} maxSuffixComponents
+ */
+var Interest = function Interest
+   (nameOrInterest, minSuffixComponents, maxSuffixComponents,
+    publisherPublicKeyDigest, exclude, childSelector, answerOriginKind, scope,
+    interestLifetimeMilliseconds, nonce)
+{
+  if (publisherPublicKeyDigest)
+    throw new Error
+      ("Interest constructor: PublisherPublicKeyDigest support has been removed.");
+  if (answerOriginKind)
+    throw new Error
+      ("Interest constructor: answerOriginKind support has been removed. Use setMustBeFresh().");
+  if (scope)
+    throw new Error("Interest constructor: scope support has been removed.");
+
+  if (typeof nameOrInterest === 'object' && nameOrInterest instanceof Interest) {
+    // Special case: this is a copy constructor.  Ignore all but the first argument.
+    var interest = nameOrInterest;
+    // Copy the name.
+    this.name_ = new ChangeCounter(new Name(interest.getName()));
+    this.maxSuffixComponents_ = interest.maxSuffixComponents_;
+    this.minSuffixComponents_ = interest.minSuffixComponents_;
+
+    this.keyLocator_ = new ChangeCounter(new KeyLocator(interest.getKeyLocator()));
+    this.exclude_ = new ChangeCounter(new Exclude(interest.getExclude()));
+    this.childSelector_ = interest.childSelector_;
+    this.mustBeFresh_ = interest.mustBeFresh_;
+    this.interestLifetimeMilliseconds_ = interest.interestLifetimeMilliseconds_;
+    this.nonce_ = interest.nonce_;
+    this.linkWireEncoding_ = interest.linkWireEncoding_;
+    this.linkWireEncodingFormat_ = interest.linkWireEncodingFormat_;
+    this.link_ = new ChangeCounter(null);
+    if (interest.link_.get() != null)
+      this.link_.set(new Link(interest.link_.get()));
+    this.selectedDelegationIndex_ = interest.selectedDelegationIndex_;
+    this.defaultWireEncoding_ = interest.getDefaultWireEncoding();
+    this.defaultWireEncodingFormat_ = interest.defaultWireEncodingFormat_;
+  }
+  else {
+    this.name_ = new ChangeCounter(typeof nameOrInterest === 'object' &&
+                                   nameOrInterest instanceof Name ?
+      new Name(nameOrInterest) : new Name());
+    this.maxSuffixComponents_ = maxSuffixComponents;
+    this.minSuffixComponents_ = minSuffixComponents;
+
+    this.keyLocator_ = new ChangeCounter(new KeyLocator());
+    this.exclude_ = new ChangeCounter(typeof exclude === 'object' && exclude instanceof Exclude ?
+      new Exclude(exclude) : new Exclude());
+    this.childSelector_ = childSelector;
+    this.mustBeFresh_ = true;
+    this.interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
+    this.nonce_ = typeof nonce === 'object' && nonce instanceof Blob ?
+      nonce : new Blob(nonce, true);
+    this.linkWireEncoding_ = new Blob();
+    this.linkWireEncodingFormat_ = null;
+    this.link_ = new ChangeCounter(null);
+    this.selectedDelegationIndex_ = null;
+    this.defaultWireEncoding_ = new SignedBlob();
+    this.defaultWireEncodingFormat_ = null;
+  }
+
+  this.getNonceChangeCount_ = 0;
+  this.getDefaultWireEncodingChangeCount_ = 0;
+  this.changeCount_ = 0;
+  this.lpPacket_ = null;
+};
+
+exports.Interest = Interest;
+
+Interest.RECURSIVE_POSTFIX = "*";
+
+Interest.CHILD_SELECTOR_LEFT = 0;
+Interest.CHILD_SELECTOR_RIGHT = 1;
+
+/**
+ * Check if this interest's name matches the given name (using Name.match) and
+ * the given name also conforms to the interest selectors.
+ * @param {Name} name The name to check.
+ * @return {boolean} True if the name and interest selectors match, False otherwise.
+ */
+Interest.prototype.matchesName = function(name)
+{
+  if (!this.getName().match(name))
+    return false;
+
+  if (this.minSuffixComponents_ != null &&
+      // Add 1 for the implicit digest.
+      !(name.size() + 1 - this.getName().size() >= this.minSuffixComponents_))
+    return false;
+  if (this.maxSuffixComponents_ != null &&
+      // Add 1 for the implicit digest.
+      !(name.size() + 1 - this.getName().size() <= this.maxSuffixComponents_))
+    return false;
+  if (this.getExclude() != null && name.size() > this.getName().size() &&
+      this.getExclude().matches(name.get(this.getName().size())))
+    return false;
+
+  return true;
+};
+
+/**
+ * @deprecated Use matchesName.
+ */
+Interest.prototype.matches_name = function(/*Name*/ name)
+{
+  return this.matchesName(name);
+};
+
+/**
+ * Check if the given Data packet can satisfy this Interest. This method
+ * considers the Name, MinSuffixComponents, MaxSuffixComponents,
+ * PublisherPublicKeyLocator, and Exclude. It does not consider the
+ * ChildSelector or MustBeFresh. This uses the given wireFormat to get the
+ * Data packet encoding for the full Name.
+ * @param {Data} data The Data packet to check.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the Data packet to get its full Name. If omitted, use
+ * WireFormat.getDefaultWireFormat().
+ * @return {boolean} True if the given Data packet can satisfy this Interest.
+ */
+Interest.prototype.matchesData = function(data, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  // Imitate ndn-cxx Interest::matchesData.
+  var interestNameLength = this.getName().size();
+  var dataName = data.getName();
+  var fullNameLength = dataName.size() + 1;
+
+  // Check MinSuffixComponents.
+  var hasMinSuffixComponents = (this.getMinSuffixComponents() != null);
+  var minSuffixComponents =
+    hasMinSuffixComponents ? this.getMinSuffixComponents() : 0;
+  if (!(interestNameLength + minSuffixComponents <= fullNameLength))
+    return false;
+
+  // Check MaxSuffixComponents.
+  var hasMaxSuffixComponents = (this.getMaxSuffixComponents() != null);
+  if (hasMaxSuffixComponents &&
+      !(interestNameLength + this.getMaxSuffixComponents() >= fullNameLength))
+    return false;
+
+  // Check the prefix.
+  if (interestNameLength === fullNameLength) {
+    if (this.getName().get(-1).isImplicitSha256Digest()) {
+      if (!this.getName().equals(data.getFullName(wireFormat)))
+        return false;
+    }
+    else
+      // The Interest Name is the same length as the Data full Name, but the
+      //   last component isn't a digest so there's no possibility of matching.
+      return false;
+  }
+  else {
+    // The Interest Name should be a strict prefix of the Data full Name.
+    if (!this.getName().isPrefixOf(dataName))
+      return false;
+  }
+
+  // Check the Exclude.
+  // The Exclude won't be violated if the Interest Name is the same as the
+  //   Data full Name.
+  if (this.getExclude().size() > 0 && fullNameLength > interestNameLength) {
+    if (interestNameLength == fullNameLength - 1) {
+      // The component to exclude is the digest.
+      if (this.getExclude().matches
+          (data.getFullName(wireFormat).get(interestNameLength)))
+        return false;
+    }
+    else {
+      // The component to exclude is not the digest.
+      if (this.getExclude().matches(dataName.get(interestNameLength)))
+        return false;
+    }
+  }
+
+  // Check the KeyLocator.
+  var publisherPublicKeyLocator = this.getKeyLocator();
+  if (publisherPublicKeyLocator.getType()) {
+    var signature = data.getSignature();
+    if (!KeyLocator.canGetFromSignature(signature))
+      // No KeyLocator in the Data packet.
+      return false;
+    if (!publisherPublicKeyLocator.equals
+        (KeyLocator.getFromSignature(signature)))
+      return false;
+  }
+
+  return true;
+};
+
+/**
+ * Return a new Interest with the same fields as this Interest.
+ */
+Interest.prototype.clone = function()
+{
+  return new Interest(this);
+};
+
+/**
+ * Get the interest Name.
+ * @return {Name} The name.  The name size() may be 0 if not specified.
+ */
+Interest.prototype.getName = function() { return this.name_.get(); };
+
+/**
+ * Get the min suffix components.
+ * @return {number} The min suffix components, or null if not specified.
+ */
+Interest.prototype.getMinSuffixComponents = function()
+{
+  return this.minSuffixComponents_;
+};
+
+/**
+ * Get the max suffix components.
+ * @return {number} The max suffix components, or null if not specified.
+ */
+Interest.prototype.getMaxSuffixComponents = function()
+{
+  return this.maxSuffixComponents_;
+};
+
+/**
+ * Get the interest key locator.
+ * @return {KeyLocator} The key locator. If its getType() is null,
+ * then the key locator is not specified.
+ */
+Interest.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_.get();
+};
+
+/**
+ * Get the exclude object.
+ * @return {Exclude} The exclude object. If the exclude size() is zero, then
+ * the exclude is not specified.
+ */
+Interest.prototype.getExclude = function() { return this.exclude_.get(); };
+
+/**
+ * Get the child selector.
+ * @return {number} The child selector, or null if not specified.
+ */
+Interest.prototype.getChildSelector = function()
+{
+  return this.childSelector_;
+};
+
+/**
+ * Get the must be fresh flag. If not specified, the default is true.
+ * @return {boolean} The must be fresh flag.
+ */
+Interest.prototype.getMustBeFresh = function()
+{
+  return this.mustBeFresh_;
+};
+
+/**
+ * Return the nonce value from the incoming interest.  If you change any of the
+ * fields in this Interest object, then the nonce value is cleared.
+ * @return {Blob} The nonce. If not specified, the value isNull().
+ */
+Interest.prototype.getNonce = function()
+{
+  if (this.getNonceChangeCount_ != this.getChangeCount()) {
+    // The values have changed, so the existing nonce is invalidated.
+    this.nonce_ = new Blob();
+    this.getNonceChangeCount_ = this.getChangeCount();
+  }
+
+  return this.nonce_;
+};
+
+/**
+ * @deprecated Use getNonce. This method returns a Buffer which is the former
+ * behavior of getNonce, and should only be used while updating your code.
+ */
+Interest.prototype.getNonceAsBuffer = function()
+{
+  return this.getNonce().buf();
+};
+
+/**
+ * Check if this interest has a link object (or a link wire encoding which
+ * can be decoded to make the link object).
+ * @return {boolean} True if this interest has a link object, false if not.
+ */
+Interest.prototype.hasLink = function()
+{
+  return this.link_.get() != null || !this.linkWireEncoding_.isNull();
+};
+
+/**
+ * Get the link object. If necessary, decode it from the link wire encoding.
+ * @return {Link} The link object, or null if not specified.
+ * @throws DecodingException For error decoding the link wire encoding (if
+ * necessary).
+ */
+Interest.prototype.getLink = function()
+{
+  if (this.link_.get() != null)
+    return this.link_.get();
+  else if (!this.linkWireEncoding_.isNull()) {
+    // Decode the link object from linkWireEncoding_.
+    var link = new Link();
+    link.wireDecode(this.linkWireEncoding_, this.linkWireEncodingFormat_);
+    this.link_.set(link);
+
+    // Clear linkWireEncoding_ since it is now managed by the link object.
+    this.linkWireEncoding_ = new Blob();
+    this.linkWireEncodingFormat_ = null;
+
+    return link;
+  }
+  else
+    return null;
+};
+
+/**
+ * Get the wire encoding of the link object. If there is already a wire
+ * encoding then return it. Otherwise encode from the link object (if
+ * available).
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * the Link. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The wire encoding, or an isNull Blob if the link is not
+ * specified.
+ */
+Interest.prototype.getLinkWireEncoding = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (!this.linkWireEncoding_.isNull() && this.linkWireEncodingFormat_ == wireFormat)
+    return this.linkWireEncoding_;
+
+  var link = this.getLink();
+  if (link != null)
+    return link.wireEncode(wireFormat);
+  else
+    return new Blob();
+};
+
+/**
+ * Get the selected delegation index.
+ * @return {number} The selected delegation index. If not specified, return null.
+ */
+Interest.prototype.getSelectedDelegationIndex = function()
+{
+  return this.selectedDelegationIndex_;
+};
+
+/**
+ * Get the interest lifetime.
+ * @return {number} The interest lifetime in milliseconds, or null if not
+ * specified.
+ */
+Interest.prototype.getInterestLifetimeMilliseconds = function()
+{
+  return this.interestLifetimeMilliseconds_;
+};
+
+/**
+ * Return the default wire encoding, which was encoded with
+ * getDefaultWireEncodingFormat().
+ * @return {SignedBlob} The default wire encoding, whose isNull() may be true
+ * if there is no default wire encoding.
+ */
+Interest.prototype.getDefaultWireEncoding = function()
+{
+  if (this.getDefaultWireEncodingChangeCount_ != this.getChangeCount()) {
+    // The values have changed, so the default wire encoding is invalidated.
+    this.defaultWireEncoding_ = new SignedBlob();
+    this.defaultWireEncodingFormat_ = null;
+    this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
+  }
+
+  return this.defaultWireEncoding_;
+};
+
+/**
+ * Get the WireFormat which is used by getDefaultWireEncoding().
+ * @return {WireFormat} The WireFormat, which is only meaningful if the
+ * getDefaultWireEncoding() is not isNull().
+ */
+Interest.prototype.getDefaultWireEncodingFormat = function()
+{
+  return this.defaultWireEncodingFormat_;
+};
+
+/**
+ * Get the incoming face ID according to the incoming packet header.
+ * @return {number} The incoming face ID. If not specified, return null.
+ */
+Interest.prototype.getIncomingFaceId = function()
+{
+  var field =
+    this.lpPacket_ === null ? null : IncomingFaceId.getFirstHeader(this.lpPacket_);
+  return field === null ? null : field.getFaceId();
+};
+
+/**
+ * Set the interest name.
+ * Note: You can also call getName and change the name values directly.
+ * @param {Name} name The interest name. This makes a copy of the name.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setName = function(name)
+{
+  this.name_.set(typeof name === 'object' && name instanceof Name ?
+    new Name(name) : new Name());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the min suffix components count.
+ * @param {number} minSuffixComponents The min suffix components count. If not
+ * specified, set to undefined.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setMinSuffixComponents = function(minSuffixComponents)
+{
+  this.minSuffixComponents_ = minSuffixComponents;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the max suffix components count.
+ * @param {number} maxSuffixComponents The max suffix components count. If not
+ * specified, set to undefined.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setMaxSuffixComponents = function(maxSuffixComponents)
+{
+  this.maxSuffixComponents_ = maxSuffixComponents;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set this interest to use a copy of the given KeyLocator object.
+ * Note: You can also call getKeyLocator and change the key locator directly.
+ * @param {KeyLocator} keyLocator The KeyLocator object. This makes a copy of the object.
+ * If no key locator is specified, set to a new default KeyLocator(), or to a
+ * KeyLocator with an unspecified type.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_.set
+    (typeof keyLocator === 'object' && keyLocator instanceof KeyLocator ?
+     new KeyLocator(keyLocator) : new KeyLocator());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set this interest to use a copy of the given exclude object. Note: You can
+ * also call getExclude and change the exclude entries directly.
+ * @param {Exclude} exclude The Exclude object. This makes a copy of the object.
+ * If no exclude is specified, set to a new default Exclude(), or to an Exclude
+ * with size() 0.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setExclude = function(exclude)
+{
+  this.exclude_.set(typeof exclude === 'object' && exclude instanceof Exclude ?
+    new Exclude(exclude) : new Exclude());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the link wire encoding bytes, without decoding them. If there is
+ * a link object, set it to null. If you later call getLink(), it will
+ * decode the wireEncoding to create the link object.
+ * @param {Blob} encoding The Blob with the bytes of the link wire encoding.
+ * If no link is specified, set to an empty Blob() or call unsetLink().
+ * @param {WireFormat} wireFormat The wire format of the encoding, to be used
+ * later if necessary to decode. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setLinkWireEncoding = function(encoding, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  this.linkWireEncoding_ = encoding;
+  this.linkWireEncodingFormat_ = wireFormat;
+
+  // Clear the link object, assuming that it has a different encoding.
+  this.link_.set(null);
+
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Clear the link wire encoding and link object so that getLink() returns null.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.unsetLink = function()
+{
+  return this.setLinkWireEncoding(new Blob(), null);
+};
+
+/**
+ * Set the selected delegation index.
+ * @param {number} selectedDelegationIndex The selected delegation index. If not
+ * specified, set to null.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setSelectedDelegationIndex = function(selectedDelegationIndex)
+{
+  this.selectedDelegationIndex_ = selectedDelegationIndex;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the child selector.
+ * @param {number} childSelector The child selector. If not specified, set to
+ * undefined.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setChildSelector = function(childSelector)
+{
+  this.childSelector_ = childSelector;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the MustBeFresh flag.
+ * @param {boolean} mustBeFresh True if the content must be fresh, otherwise
+ * false. If you do not set this flag, the default value is true.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setMustBeFresh = function(mustBeFresh)
+{
+  this.mustBeFresh_ = (mustBeFresh ? true : false);
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the interest lifetime.
+ * @param {number} interestLifetimeMilliseconds The interest lifetime in
+ * milliseconds. If not specified, set to undefined.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setInterestLifetimeMilliseconds = function(interestLifetimeMilliseconds)
+{
+  this.interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * @deprecated You should let the wire encoder generate a random nonce
+ * internally before sending the interest.
+ */
+Interest.prototype.setNonce = function(nonce)
+{
+  this.nonce_ = typeof nonce === 'object' && nonce instanceof Blob ?
+    nonce : new Blob(nonce, true);
+  // Set getNonceChangeCount_ so that the next call to getNonce() won't clear
+  // this.nonce_.
+  ++this.changeCount_;
+  this.getNonceChangeCount_ = this.getChangeCount();
+  return this;
+};
+
+/**
+ * Encode the name according to the "NDN URI Scheme".  If there are interest selectors, append "?" and
+ * added the selectors as a query string.  For example "/test/name?ndn.ChildSelector=1".
+ * Note: This is an experimental feature.  See the API docs for more detail at
+ * http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .
+ * @return {string} The URI string.
+ */
+Interest.prototype.toUri = function()
+{
+  var selectors = "";
+
+  if (this.minSuffixComponents_ != null)
+    selectors += "&ndn.MinSuffixComponents=" + this.minSuffixComponents_;
+  if (this.maxSuffixComponents_ != null)
+    selectors += "&ndn.MaxSuffixComponents=" + this.maxSuffixComponents_;
+  if (this.childSelector_ != null)
+    selectors += "&ndn.ChildSelector=" + this.childSelector_;
+  selectors += "&ndn.MustBeFresh=" + (this.mustBeFresh_ ? 1 : 0);
+  if (this.interestLifetimeMilliseconds_ != null)
+    selectors += "&ndn.InterestLifetime=" + this.interestLifetimeMilliseconds_;
+  if (this.getNonce().size() > 0)
+    selectors += "&ndn.Nonce=" + Name.toEscapedString(this.getNonce().buf());
+  if (this.getExclude() != null && this.getExclude().size() > 0)
+    selectors += "&ndn.Exclude=" + this.getExclude().toUri();
+
+  var result = this.getName().toUri();
+  if (selectors != "")
+    // Replace the first & with ?.
+    result += "?" + selectors.substr(1);
+
+  return result;
+};
+
+/**
+ * Encode this Interest for a particular wire format. If wireFormat is the
+ * default wire format, also set the defaultWireEncoding field to the encoded
+ * result.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {SignedBlob} The encoded buffer in a SignedBlob object.
+ */
+Interest.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (!this.getDefaultWireEncoding().isNull() &&
+      this.getDefaultWireEncodingFormat() == wireFormat)
+    // We already have an encoding in the desired format.
+    return this.getDefaultWireEncoding();
+
+  var result = wireFormat.encodeInterest(this);
+  var wireEncoding = new SignedBlob
+    (result.encoding, result.signedPortionBeginOffset,
+     result.signedPortionEndOffset);
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // This is the default wire encoding.
+    this.setDefaultWireEncoding
+      (wireEncoding, WireFormat.getDefaultWireFormat());
+  return wireEncoding;
+};
+
+/**
+ * Decode the input using a particular wire format and update this Interest. If
+ * wireFormat is the default wire format, also set the defaultWireEncoding to
+ * another pointer to the input.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Interest.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var result;
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    result = wireFormat.decodeInterest(this, input.buf(), false);
+  else
+    result = wireFormat.decodeInterest(this, input, true);
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // This is the default wire encoding.  In the Blob constructor, set copy
+    // true, but if input is already a Blob, it won't copy.
+    this.setDefaultWireEncoding(new SignedBlob
+      (new Blob(input, true), result.signedPortionBeginOffset,
+       result.signedPortionEndOffset),
+      WireFormat.getDefaultWireFormat());
+  else
+    this.setDefaultWireEncoding(new SignedBlob(), null);
+};
+
+/**
+ * Update the bytes of the nonce with new random values. This ensures that the
+ * new nonce value is different than the current one. If the current nonce is
+ * not specified, this does nothing.
+ */
+Interest.prototype.refreshNonce = function()
+{
+  var currentNonce = this.getNonce();
+  if (currentNonce.size() === 0)
+    return;
+
+  var newNonce;
+  while (true) {
+    newNonce = new Blob(Crypto.randomBytes(currentNonce.size()), false);
+    if (!newNonce.equals(currentNonce))
+      break;
+  }
+
+  this.nonce_ = newNonce;
+  // Set getNonceChangeCount_ so that the next call to getNonce() won't clear
+  // this.nonce_.
+  ++this.changeCount_;
+  this.getNonceChangeCount_ = this.getChangeCount();
+};
+
+/**
+ * An internal library method to set the LpPacket for an incoming packet. The
+ * application should not call this.
+ * @param {LpPacket} lpPacket The LpPacket. This does not make a copy.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ * @note This is an experimental feature. This API may change in the future.
+ */
+Interest.prototype.setLpPacket = function(lpPacket)
+{
+  this.lpPacket_ = lpPacket;
+  // Don't update changeCount_ since this doesn't affect the wire encoding.
+  return this;
+}
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+Interest.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.name_.checkChanged();
+  changed = this.keyLocator_.checkChanged() || changed;
+  changed = this.exclude_.checkChanged() || changed;
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+
+Interest.prototype.setDefaultWireEncoding = function
+  (defaultWireEncoding, defaultWireEncodingFormat)
+{
+  this.defaultWireEncoding_ = defaultWireEncoding;
+  this.defaultWireEncodingFormat_ = defaultWireEncodingFormat;
+  // Set getDefaultWireEncodingChangeCount_ so that the next call to
+  // getDefaultWireEncoding() won't clear _defaultWireEncoding.
+  this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(Interest.prototype, "name",
+  { get: function() { return this.getName(); },
+    set: function(val) { this.setName(val); } });
+Object.defineProperty(Interest.prototype, "minSuffixComponents",
+  { get: function() { return this.getMinSuffixComponents(); },
+    set: function(val) { this.setMinSuffixComponents(val); } });
+Object.defineProperty(Interest.prototype, "maxSuffixComponents",
+  { get: function() { return this.getMaxSuffixComponents(); },
+    set: function(val) { this.setMaxSuffixComponents(val); } });
+Object.defineProperty(Interest.prototype, "keyLocator",
+  { get: function() { return this.getKeyLocator(); },
+    set: function(val) { this.setKeyLocator(val); } });
+Object.defineProperty(Interest.prototype, "exclude",
+  { get: function() { return this.getExclude(); },
+    set: function(val) { this.setExclude(val); } });
+Object.defineProperty(Interest.prototype, "childSelector",
+  { get: function() { return this.getChildSelector(); },
+    set: function(val) { this.setChildSelector(val); } });
+/**
+ * @deprecated Use getInterestLifetimeMilliseconds and setInterestLifetimeMilliseconds.
+ */
+Object.defineProperty(Interest.prototype, "interestLifetime",
+  { get: function() { return this.getInterestLifetimeMilliseconds(); },
+    set: function(val) { this.setInterestLifetimeMilliseconds(val); } });
+/**
+ * @deprecated Use getNonce and setNonce.
+ */
+Object.defineProperty(Interest.prototype, "nonce",
+  { get: function() { return this.getNonceAsBuffer(); },
+    set: function(val) { this.setNonce(val); } });
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A ForwardingFlags object holds the flags which specify how the forwarding daemon should forward an interest for
+ * a registered prefix.  We use a separate ForwardingFlags object to retain future compatibility if the daemon forwarding
+ * bits are changed, amended or deprecated.
+ * Create a new ForwardingFlags with "childInherit" set and all other flags cleared.
+ * @constructor
+ */
+var ForwardingFlags = function ForwardingFlags(value)
+{
+  if (typeof value === 'object' && value instanceof ForwardingFlags) {
+    // Make a copy.
+    this.childInherit = value.childInherit;
+    this.capture = value.capture;
+  }
+  else {
+    this.childInherit = true;
+    this.capture = false;
+  }
+};
+
+exports.ForwardingFlags = ForwardingFlags;
+
+ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT = 1;
+ForwardingFlags.NfdForwardingFlags_CAPTURE       = 2;
+
+/**
+ * Get an integer with the bits set according to the NFD forwarding flags as
+ * used in the ControlParameters of the command interest.
+ * @return {number} An integer with the bits set.
+ */
+ForwardingFlags.prototype.getNfdForwardingFlags = function()
+{
+  var result = 0;
+
+  if (this.childInherit)
+    result |= ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT;
+  if (this.capture)
+    result |= ForwardingFlags.NfdForwardingFlags_CAPTURE;
+
+  return result;
+};
+
+/**
+ * Set the flags according to the NFD forwarding flags as used in the
+ * ControlParameters of the command interest.
+ * @param {number} nfdForwardingFlags An integer with the bits set.
+ */
+ForwardingFlags.prototype.setNfdForwardingFlags = function(nfdForwardingFlags)
+{
+  this.childInherit =
+    ((nfdForwardingFlags & ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT) != 0);
+  this.capture =
+    ((nfdForwardingFlags & ForwardingFlags.NfdForwardingFlags_CAPTURE) != 0);
+};
+
+/**
+ * Get the value of the "childInherit" flag.
+ * @return {Boolean} true if the flag is set, false if it is cleared.
+ */
+ForwardingFlags.prototype.getChildInherit = function() { return this.childInherit; };
+
+/**
+ * Get the value of the "capture" flag.
+ * @return {Boolean} true if the flag is set, false if it is cleared.
+ */
+ForwardingFlags.prototype.getCapture = function() { return this.capture; };
+
+/**
+ * Set the value of the "childInherit" flag
+ * @param {number} value true to set the flag, false to clear it.
+ */
+ForwardingFlags.prototype.setChildInherit = function(value) { this.childInherit = value; };
+
+/**
+ * Set the value of the "capture" flag
+ * @param {number} value true to set the flag, false to clear it.
+ */
+ForwardingFlags.prototype.setCapture = function(value) { this.capture = value; };
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var ForwardingFlags = require('./forwarding-flags.js').ForwardingFlags; /** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * A ControlParameters which holds a Name and other fields for a
+ * ControlParameters which is used, for example, in the command interest to
+ * register a prefix with a forwarder. See
+ * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand#ControlParameters
+ * @constructor
+ */
+var ControlParameters = function ControlParameters(value)
+{
+  if (typeof value === 'object' && value instanceof ControlParameters) {
+    // Make a deep copy.
+    this.name = value.name == null ? null : new Name(value.name);
+    this.faceId = value.faceId;
+    this.uri = value.uri;
+    this.localControlFeature = value.localControlFeature;
+    this.origin = value.origin;
+    this.cost = value.cost;
+    this.forwardingFlags = new ForwardingFlags(value.forwardingFlags);
+    this.strategy = new Name(value.strategy);
+    this.expirationPeriod = value.expirationPeriod;
+  }
+  else {
+    this.name = null;
+    this.faceId = null;
+    this.uri = '';
+    this.localControlFeature = null;
+    this.origin = null;
+    this.cost = null;
+    this.forwardingFlags = new ForwardingFlags();
+    this.strategy = new Name();
+    this.expirationPeriod = null;
+  }
+};
+
+exports.ControlParameters = ControlParameters;
+
+ControlParameters.prototype.clear = function()
+{
+  this.name = null;
+  this.faceId = null;
+  this.uri = '';
+  this.localControlFeature = null;
+  this.origin = null;
+  this.cost = null;
+  this.forwardingFlags = new ForwardingFlags();
+  this.strategy = new Name();
+  this.expirationPeriod = null;
+};
+
+/**
+ * Encode this ControlParameters for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+ControlParameters.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeControlParameters(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this
+ * ControlParameters.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+ControlParameters.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeControlParameters(this, input.buf(), false);
+  else
+    wireFormat.decodeControlParameters(this, input, true);
+};
+
+/**
+ * Get the name.
+ * @return {Name} The name. If not specified, return null.
+ */
+ControlParameters.prototype.getName = function()
+{
+  return this.name;
+};
+
+/**
+ * Get the face ID.
+ * @return {number} The face ID, or null if not specified.
+ */
+ControlParameters.prototype.getFaceId = function()
+{
+  return this.faceId;
+};
+
+/**
+ * Get the URI.
+ * @return {string} The face URI, or an empty string if not specified.
+ */
+ControlParameters.prototype.getUri = function()
+{
+  return this.uri;
+};
+
+/**
+ * Get the local control feature value.
+ * @return {number} The local control feature value, or null if not specified.
+ */
+ControlParameters.prototype.getLocalControlFeature = function()
+{
+  return this.localControlFeature;
+};
+
+/**
+ * Get the origin value.
+ * @return {number} The origin value, or null if not specified.
+ */
+ControlParameters.prototype.getOrigin = function()
+{
+  return this.origin;
+};
+
+/**
+ * Get the cost value.
+ * @return {number} The cost value, or null if not specified.
+ */
+ControlParameters.prototype.getCost = function()
+{
+  return this.cost;
+};
+
+/**
+ * Get the ForwardingFlags object.
+ * @return {ForwardingFlags} The ForwardingFlags object.
+ */
+ControlParameters.prototype.getForwardingFlags = function()
+{
+  return this.forwardingFlags;
+};
+
+/**
+ * Get the strategy.
+ * @return {Name} The strategy or an empty Name
+ */
+ControlParameters.prototype.getStrategy = function()
+{
+  return this.strategy;
+};
+
+/**
+ * Get the expiration period.
+ * @return {number} The expiration period in milliseconds, or null if not specified.
+ */
+ControlParameters.prototype.getExpirationPeriod = function()
+{
+  return this.expirationPeriod;
+};
+
+/**
+ * Set the name.
+ * @param {Name} name The name. If not specified, set to null. If specified, this
+ * makes a copy of the name.
+ */
+ControlParameters.prototype.setName = function(name)
+{
+  this.name = typeof name === 'object' && name instanceof Name ?
+              new Name(name) : null;
+};
+
+/**
+ * Set the Face ID.
+ * @param {number} faceId The new face ID, or null for not specified.
+ */
+ControlParameters.prototype.setFaceId = function(faceId)
+{
+  this.faceId = faceId;
+};
+
+/**
+ * Set the URI.
+ * @param {string} uri The new uri, or an empty string for not specified.
+ */
+ControlParameters.prototype.setUri = function(uri)
+{
+  this.uri = uri || '';
+};
+
+/**
+ * Set the local control feature value.
+ * @param {number} localControlFeature The new local control feature value, or
+ * null for not specified.
+ */
+ControlParameters.prototype.setLocalControlFeature = function(localControlFeature)
+{
+  this.localControlFeature = localControlFeature;
+};
+
+/**
+ * Set the origin value.
+ * @param {number} origin The new origin value, or null for not specified.
+ */
+ControlParameters.prototype.setOrigin = function(origin)
+{
+  this.origin = origin;
+};
+
+/**
+ * Set the cost value.
+ * @param {number} cost The new cost value, or null for not specified.
+ */
+ControlParameters.prototype.setCost = function(cost)
+{
+  this.cost = cost;
+};
+
+/**
+ * Set the ForwardingFlags object to a copy of forwardingFlags. You can use
+ * getForwardingFlags() and change the existing ForwardingFlags object.
+ * @param {ForwardingFlags} forwardingFlags The new cost value, or null for not specified.
+ */
+ControlParameters.prototype.setForwardingFlags = function(forwardingFlags)
+{
+  this.forwardingFlags =
+    typeof forwardingFlags === 'object' && forwardingFlags instanceof ForwardingFlags ?
+      new ForwardingFlags(forwardingFlags) : new ForwardingFlags();
+};
+
+/**
+ * Set the strategy to a copy of the given Name.
+ * @param {Name} strategy The Name to copy, or an empty Name if not specified.
+ */
+ControlParameters.prototype.setStrategy = function(strategy)
+{
+  this.strategy = typeof strategy === 'object' && strategy instanceof Name ?
+              new Name(strategy) : new Name();
+};
+
+/**
+ * Set the expiration period.
+ * @param {number} expirationPeriod The expiration period in milliseconds, or
+ * null for not specified.
+ */
+ControlParameters.prototype.setExpirationPeriod = function(expirationPeriod)
+{
+  this.expirationPeriod = expirationPeriod;
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var ControlParameters = require('./control-parameters.js').ControlParameters; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * A ControlResponse holds a status code, status text and other fields for a
+ * ControlResponse which is used, for example, in the response from sending a
+ * register prefix control command to a forwarder.
+ * @see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ * @constructor
+ */
+var ControlResponse = function ControlResponse(value)
+{
+  if (typeof value === 'object' && value instanceof ControlResponse) {
+    // Make a deep copy.
+    this.statusCode_ = value.statusCode_;
+    this.statusText_ = value.statusText_;
+    this.bodyAsControlParameters_ = value.bodyAsControlParameters_ == null ? null
+      : new ControlParameters(value.bodyAsControlParameters_);
+  }
+  else {
+    this.statusCode_ = null;
+    this.statusText_ = "";
+    this.bodyAsControlParameters_ = null;
+  }
+};
+
+exports.ControlResponse = ControlResponse;
+
+ControlResponse.prototype.clear = function()
+{
+  this.statusCode_ = null;
+  this.statusText_ = "";
+  this.bodyAsControlParameters_ = null;
+};
+
+/**
+ * Encode this ControlResponse for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+ControlResponse.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeControlResponse(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this
+ * ControlResponse.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+ControlResponse.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeControlResponse(this, input.buf(), false);
+  else
+    wireFormat.decodeControlResponse(this, input, true);
+};
+
+/**
+ * Get the status code.
+ * @return {number} The status code. If not specified, return null.
+ */
+ControlResponse.prototype.getStatusCode = function()
+{
+  return this.statusCode_;
+};
+
+/**
+ * Get the status text.
+ * @return {string} The status text. If not specified, return "".
+ */
+ControlResponse.prototype.getStatusText = function()
+{
+  return this.statusText_;
+};
+
+/**
+ * Get the control response body as a ControlParameters.
+ * @return {ControlParameters} The ControlParameters, or null if the body is not
+ * specified or if it is not a ControlParameters.
+ */
+ControlResponse.prototype.getBodyAsControlParameters = function()
+{
+  return this.bodyAsControlParameters_;
+};
+
+/**
+ * Set the status code.
+ * @param statusCode {number} The status code. If not specified, set to null.
+ * @return {ControlResponse} This ControlResponse so that you can chain calls to
+ * update values.
+ */
+ControlResponse.prototype.setStatusCode = function(statusCode)
+{
+  this.statusCode_ = statusCode;
+  return this;
+};
+
+/**
+ * Set the status text.
+ * @param statusText {string} The status text. If not specified, set to "".
+ * @return {ControlResponse} This ControlResponse so that you can chain calls to
+ * update values.
+ */
+ControlResponse.prototype.setStatusText = function(statusText)
+{
+  this.statusText_ = statusText || "";
+  return this;
+};
+
+/**
+ * Set the control response body as a ControlParameters.
+ * @param {ControlParameters} controlParameters The ControlParameters for the
+ * body. This makes a copy of the ControlParameters. If not specified or if the
+ * body is not a ControlParameters, set to null.
+ * @return {ControlResponse} This ControlResponse so that you can chain calls to
+ * update values.
+ */
+ControlResponse.prototype.setBodyAsControlParameters = function(controlParameters)
+{
+  this.bodyAsControlParameters_ =
+    typeof controlParameters === 'object' && controlParameters instanceof ControlParameters ?
+      new ControlParameters(controlParameters) : null;
+  return this;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var NdnRegexMatcher = require('./util/ndn-regex-matcher.js').NdnRegexMatcher;
+
+/**
+ * An InterestFilter holds a Name prefix and optional regex match expression for
+ * use in Face.setInterestFilter.
+ *
+ * Create an InterestFilter to match any Interest whose name starts with the
+ * given prefix. If the optional regexFilter is provided then the remaining
+ * components match the regexFilter regular expression as described in doesMatch.
+ * @param {InterestFilter|Name|string} prefix If prefix is another
+ * InterestFilter copy its values. If prefix is a Name then this makes a copy of
+ * the Name. Otherwise this creates a Name from the URI string.
+ * @param {string} regexFilter (optional) The regular expression for matching
+ * the remaining name components.
+ * @constructor
+ */
+var InterestFilter = function InterestFilter(prefix, regexFilter)
+{
+  if (typeof prefix === 'object' && prefix instanceof InterestFilter) {
+    // The copy constructor.
+    var interestFilter = prefix;
+    this.prefix = new Name(interestFilter.prefix);
+    this.regexFilter = interestFilter.regexFilter;
+    this.regexFilterPattern = interestFilter.regexFilterPattern;
+  }
+  else {
+    this.prefix = new Name(prefix);
+    if (regexFilter) {
+      this.regexFilter = regexFilter;
+      this.regexFilterPattern = InterestFilter.makePattern(regexFilter);
+    }
+    else {
+      this.regexFilter = null;
+      this.regexFilterPattern = null;
+    }
+  }
+};
+
+exports.InterestFilter = InterestFilter;
+
+/**
+ * Check if the given name matches this filter. Match if name starts with this
+ * filter's prefix. If this filter has the optional regexFilter then the
+ * remaining components match the regexFilter regular expression.
+ * For example, the following InterestFilter:
+ *
+ *    InterestFilter("/hello", "<world><>+")
+ *
+ * will match all Interests, whose name has the prefix `/hello` which is
+ * followed by a component `world` and has at least one more component after it.
+ * Examples:
+ *
+ *    /hello/world/!
+ *    /hello/world/x/y/z
+ *
+ * Note that the regular expression will need to match all remaining components
+ * (e.g., there are implicit heading `^` and trailing `$` symbols in the
+ * regular expression).
+ * @param {Name} name The name to check against this filter.
+ * @return {boolean} True if name matches this filter, otherwise false.
+ */
+InterestFilter.prototype.doesMatch = function(name)
+{
+  if (name.size() < this.prefix.size())
+    return false;
+
+  if (this.hasRegexFilter()) {
+    // Perform a prefix match and regular expression match for the remaining
+    // components.
+    if (!this.prefix.match(name))
+      return false;
+
+    return null != NdnRegexMatcher.match
+      (this.regexFilterPattern, name.getSubName(this.prefix.size()));
+  }
+  else
+    // Just perform a prefix match.
+    return this.prefix.match(name);
+};
+
+/**
+ * Get the prefix given to the constructor.
+ * @return {Name} The prefix Name which you should not modify.
+ */
+InterestFilter.prototype.getPrefix = function() { return this.prefix; };
+
+/**
+ * Check if a regexFilter was supplied to the constructor.
+ * @return {boolean} True if a regexFilter was supplied to the constructor.
+ */
+InterestFilter.prototype.hasRegexFilter = function()
+{
+  return this.regexFilter != null;
+};
+
+/**
+ * Get the regex filter. This is only valid if hasRegexFilter() is true.
+ * @return {string} The regular expression for matching the remaining name
+ * components.
+ */
+InterestFilter.prototype.getRegexFilter = function() { return this.regexFilter; };
+
+/**
+ * If regexFilter doesn't already have them, add ^ to the beginning and $ to
+ * the end since these are required by NdnRegexMatcher.match.
+ * @param {string} regexFilter The regex filter.
+ * @return {string} The regex pattern with ^ and $.
+ */
+InterestFilter.makePattern = function(regexFilter)
+{
+  if (regexFilter.length == 0)
+    // We don't expect this.
+    return "^$";
+
+  var pattern = regexFilter;
+  if (pattern[0] != '^')
+    pattern = "^" + pattern;
+  if (pattern[pattern.length - 1] != '$')
+    pattern = pattern + "$";
+
+  return pattern;
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat;
+
+/**
+ * A DelegationSet holds a list of DelegationSet.Delegation entries which is
+ * used as the content of a Link instance. If you add elements with add(), then
+ * the list is a set sorted by preference number then by name. But wireDecode
+ * will add the elements from the wire encoding, preserving the given order and
+ * possible duplicates (in which case a DelegationSet really holds a "list" and
+ * not necessarily a "set").
+ *
+ * Create a new DelegationSet object, possibly copying values from another
+ * object.
+ *
+ * @param {DelegationSet} value (optional) If value is a DelegationSet, copy its
+ * values.
+ * @constructor
+ */
+var DelegationSet = function DelegationSet(value)
+{
+  if (typeof value === 'object' && value instanceof DelegationSet)
+    // Copy the list.
+    this.delegations_ = value.delegations_.slice(0);
+  else
+    this.delegations_ = []; // of DelegationSet.Delegation.
+};
+
+exports.DelegationSet = DelegationSet;
+
+/**
+ * A DelegationSet.Delegation holds a preference number and delegation name.
+ * Create a new DelegationSet.Delegation with the given values.
+ * @param {number} preference The preference number.
+ * @param {Name} name The delegation name. This makes a copy of the name.
+ * @constructor
+ */
+DelegationSet.Delegation = function DelegationSetDelegation(preference, name)
+{
+  this.preference_ = preference;
+  this.name_ = new Name(name);
+};
+
+/**
+ * Get the preference number.
+ * @return {number} The preference number.
+ */
+DelegationSet.Delegation.prototype.getPreference = function()
+{
+  return this.preference_;
+};
+
+/**
+ * Get the delegation name.
+ * @return {Name} The delegation name. NOTE: You must not change the name object -
+ * if you need to change it then make a copy.
+ */
+DelegationSet.Delegation.prototype.getName = function()
+{
+  return this.name_;
+};
+
+/**
+ * Compare this Delegation with other according to the ordering, based first
+ * on the preference number, then on the delegation name.
+ * @param {DelegationSet.Delegation} other The other Delegation to compare with.
+ * @return {number} 0 If they compare equal, -1 if this Delegation comes before
+ * other in the ordering, or 1 if this Delegation comes after.
+ */
+DelegationSet.Delegation.prototype.compare = function(other)
+{
+  if (this.preference_ < other.preference_)
+    return -1;
+  if (this.preference_ > other.preference_)
+    return 1;
+
+  return this.name_.compare(other.name_);
+};
+
+/**
+ * Add a new DelegationSet.Delegation to the list of delegations, sorted by
+ * preference number then by name. If there is already a delegation with the
+ * same name, update its preference, and remove any extra delegations with the
+ * same name.
+ * @param {number} preference The preference number.
+ * @param {Name} name The delegation name. This makes a copy of the name.
+ */
+DelegationSet.prototype.add = function(preference, name)
+{
+  this.remove(name);
+
+  var newDelegation = new DelegationSet.Delegation(preference, name);
+  // Find the index of the first entry where it is not less than newDelegation.
+  var i = 0;
+  while (i < this.delegations_.length) {
+    if (this.delegations_[i].compare(newDelegation) >= 0)
+      break;
+
+    ++i;
+  }
+
+  this.delegations_.splice(i, 0, newDelegation);
+};
+
+/**
+ * Add a new DelegationSet.Delegation to the end of the list of delegations,
+ * without sorting or updating any existing entries. This is useful for adding
+ * preferences from a wire encoding, preserving the supplied ordering and
+ * possible duplicates.
+ * @param {number} preference The preference number.
+ * @param {Name} name The delegation name. This makes a copy of the name.
+ */
+DelegationSet.prototype.addUnsorted = function(preference, name)
+{
+  this.delegations_.push(new DelegationSet.Delegation(preference, name));
+};
+
+/**
+ * Remove every DelegationSet.Delegation with the given name.
+ * @param {Name} name The name to match the name of the delegation(s) to be
+ * removed.
+ * @return {boolean} True if a DelegationSet.Delegation was removed, otherwise
+ * false.
+ */
+DelegationSet.prototype.remove = function(name)
+{
+  var wasRemoved = false;
+  // Go backwards through the list so we can remove entries.
+  for (var i = this.delegations_.length - 1; i >= 0; --i) {
+    if (this.delegations_[i].getName().equals(name)) {
+      wasRemoved = true;
+      this.delegations_.splice(i, 1);
+    }
+  }
+
+  return wasRemoved;
+};
+
+/**
+ * Clear the list of delegations.
+ */
+DelegationSet.prototype.clear = function() { this.delegations_ = []; };
+
+/**
+ * Get the number of delegation entries.
+ * @return {number} The number of delegation entries.
+ */
+DelegationSet.prototype.size = function() { return this.delegations_.length; };
+
+/**
+ * Get the delegation at the given index, according to the ordering described
+ * in add().
+ * @param {number} i The index of the component, starting from 0.
+ * @return {DelegationSet.Delegation} The delegation at the index.
+ */
+DelegationSet.prototype.get = function(i) { return this.delegations_[i]; };
+
+/**
+ * Find the first delegation with the given name and return its index.
+ * @param {Name} name Then name of the delegation to find.
+ * @return {number} The index of the delegation, or -1 if not found.
+ */
+DelegationSet.prototype.find = function(name)
+{
+  for (var i = 0; i < this.delegations_.length; ++i) {
+    if (this.delegations_[i].getName().equals(name))
+      return i;
+  }
+
+  return -1;
+};
+
+/**
+ * Encode this DelegationSet for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+DelegationSet.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeDelegationSet(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this DelegationSet.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+DelegationSet.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeDelegationSet(this, input.buf(), false);
+  else
+    wireFormat.decodeDelegationSet(this, input, true);
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DelegationSet = require('./delegation-set.js').DelegationSet; /** @ignore */
+var ContentType = require('./meta-info.js').ContentType; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var Data = require('./data.js').Data;
+
+/**
+ * The Link class extends Data and represents a Link instance where the Data
+ * content is an encoded delegation set. The format is defined in "link.pdf"
+ * attached to Redmine issue http://redmine.named-data.net/issues/2587 .
+ *
+ * Create a new Link with the optional values. There are 3 forms of the constructor:
+ * Link(name);
+ * Link(data);
+ * Link();
+ * @param {Name} name The name for constructing the base Data.
+ * @param {Data} data The Data object to copy values from. If the content can be
+ * decoded using the default wire encoding, then update the list of delegations.
+ * @constructor
+ */
+var Link = function Link(value)
+{
+  this.delegations_ = new DelegationSet();
+
+  if (value instanceof Data) {
+    // Call the base constructor.
+    Data.call(this, value);
+
+    if (!this.getContent().isNull()) {
+      try {
+        this.delegations_.wireDecode(this.getContent());
+        this.getMetaInfo().setType(ContentType.LINK);
+      }
+      catch (ex) {
+        this.delegations_.clear();
+      }
+    }
+  }
+  else {
+    if (value != undefined)
+      // value is a Name.
+      Data.call(this, value);
+    else
+      Data.call(this);
+
+    this.getMetaInfo().setType(ContentType.LINK);
+  }
+};
+
+Link.prototype = new Data();
+Link.prototype.name = "Link";
+
+exports.Link = Link;
+
+/**
+ * Override to call the base class wireDecode then populate the list of
+ * delegations from the content.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Link.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  Data.prototype.wireDecode.call(this, input, wireFormat);
+  if (this.getMetaInfo().getType() != ContentType.LINK)
+    throw new Error
+      ("Link.wireDecode: MetaInfo ContentType is not LINK.");
+
+  this.delegations_.wireDecode(this.getContent());
+};
+
+/**
+ * Add a new delegation to the list of delegations, sorted by preference number
+ * then by name. Re-encode this object's content using the optional wireFormat.
+ * @param {number} preference The preference number.
+ * @param {Name} name The delegation name. This makes a copy of the name. If
+ * there is already a delegation with the same name, this updates its preference.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the DelegationSet. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Link} This Link so that you can chain calls to update values.
+ */
+Link.prototype.addDelegation = function(preference, name, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  this.delegations_.add(preference, name);
+  this.encodeContent(wireFormat);
+
+  return this;
+};
+
+/**
+ * Remove every delegation with the given name. Re-encode this object's content
+ * using the optional wireFormat.
+ * @param {Name} name Then name to match the name of the delegation(s) to be
+ * removed.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the DelegationSet. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {boolean} True if a delegation was removed, otherwise false.
+ */
+Link.prototype.removeDelegation = function(name, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var wasRemoved = this.delegations_.remove(name);
+  if (wasRemoved)
+    this.encodeContent(wireFormat);
+
+  return wasRemoved;
+};
+
+/**
+ * Get the list of delegation for read only.
+ * @return {DelegationSet} The list of delegation, which you should treat as
+ * read-only. To modify it, call Link.addDelegation, etc.
+ */
+Link.prototype.getDelegations = function() { return this.delegations_; };
+
+/**
+ * A private method to encode the delegations_ and set this object's content.
+ * Also set the meta info content type to LINK.
+ * @param {WireFormat} wireFormat A WireFormat object used to encode the
+ * DelegationSet.
+ */
+Link.prototype.encodeContent = function(wireFormat)
+{
+  this.setContent(this.delegations_.wireEncode(wireFormat));
+  this.getMetaInfo().setType(ContentType.LINK);
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-cxx nack.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/nack.hpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * NetworkNack represents a network Nack packet and includes a Nack reason.
+ * @constructor
+ */
+var NetworkNack = function NetworkNack()
+{
+  this.reason_ = NetworkNack.Reason.NONE;
+  this.otherReasonCode_ = -1;
+};
+
+exports.NetworkNack = NetworkNack;
+
+/**
+ * A NetworkNack.Reason specifies the reason in a NetworkNack packet. If the
+ * reason code in the packet is not a recognized enum value, then we use
+ * Reason.OTHER_CODE and you can call getOtherReasonCode(). We do this to keep
+ * the recognized reason values independent of packet encoding formats.
+ */
+NetworkNack.Reason = {
+  NONE:         0,
+  CONGESTION:  50,
+  DUPLICATE:  100,
+  NO_ROUTE:   150,
+  OTHER_CODE: 0x7fff
+};
+
+/**
+ * Get the network Nack reason.
+ * @return {number} The reason enum value from NetworkNack.Reason. If this is
+ * Reason.OTHER_CODE, then call getOtherReasonCode() to get the unrecognized
+ * reason code.
+ */
+NetworkNack.prototype.getReason = function() { return this.reason_; };
+
+/**
+ * Get the reason code from the packet which is other than a recognized
+ * Reason enum value. This is only meaningful if getReason() is
+ * Reason.OTHER_CODE.
+ * @return {number} The reason code.
+ */
+NetworkNack.prototype.getOtherReasonCode = function()
+{ 
+  return this.otherReasonCode_;
+};
+
+/**
+ * Set the network Nack reason.
+ * @param {number} reason The network Nack reason enum value from 
+ * NetworkNack.Reason. If the packet's reason code is not a recognized Reason
+ * enum value, use Reason.OTHER_CODE and call setOtherReasonCode().
+ */
+NetworkNack.prototype.setReason = function(reason) { this.reason_ = reason; };
+
+/**
+ * Set the packet's reason code to use when the reason enum is
+ * Reason.OTHER_CODE. If the packet's reason code is a recognized enum value,
+ * just call setReason().
+ * @param {number} otherReasonCode The packet's unrecognized reason code, which
+ * must be non-negative.
+ */
+NetworkNack.prototype.setOtherReasonCode = function(otherReasonCode)
+{
+  if (otherReasonCode < 0)
+    throw new Error("NetworkNack other reason code must be non-negative");
+  this.otherReasonCode_ = otherReasonCode;
+};
+
+/**
+ * Get the first header field in lpPacket which is a NetworkNack. This is
+ * an internal method which the application normally would not use.
+ * @param {LpPacket} lpPacket The LpPacket with the header fields to search.
+ * @return {NetworkNack} The first NetworkNack header field, or null if not
+ * found.
+ */
+NetworkNack.getFirstHeader = function(lpPacket)
+{
+  for (var i = 0; i < lpPacket.countHeaderFields(); ++i) {
+    var field = lpPacket.getHeaderField(i);
+    if (field instanceof NetworkNack)
+      return field;
+  }
+
+  return null;
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('../crypto.js'); /** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var ForwardingFlags = require('../forwarding-flags').ForwardingFlags; /** @ignore */
+var Tlv = require('./tlv/tlv.js').Tlv; /** @ignore */
+var TlvEncoder = require('./tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
+var TlvDecoder = require('./tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
+var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
+var Exclude = require('../exclude.js').Exclude; /** @ignore */
+var ContentType = require('../meta-info.js').ContentType; /** @ignore */
+var KeyLocatorType = require('../key-locator.js').KeyLocatorType; /** @ignore */
+var Sha256WithRsaSignature = require('../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var Sha256WithEcdsaSignature = require('../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
+var GenericSignature = require('../generic-signature.js').GenericSignature; /** @ignore */
+var HmacWithSha256Signature = require('../hmac-with-sha256-signature.js').HmacWithSha256Signature; /** @ignore */
+var DigestSha256Signature = require('../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
+var ControlParameters = require('../control-parameters.js').ControlParameters; /** @ignore */
+var ForwardingFlags = require('../forwarding-flags.js').ForwardingFlags; /** @ignore */
+var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
+var IncomingFaceId = require('../lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
+var DecodingException = require('./decoding-exception.js').DecodingException;
+
+/**
+ * A Tlv0_2WireFormat implements the WireFormat interface for encoding and
+ * decoding with the NDN-TLV wire format, version 0.2.
+ * @constructor
+ */
+var Tlv0_2WireFormat = function Tlv0_2WireFormat()
+{
+  // Inherit from WireFormat.
+  WireFormat.call(this);
+};
+
+Tlv0_2WireFormat.prototype = new WireFormat();
+Tlv0_2WireFormat.prototype.name = "Tlv0_2WireFormat";
+
+exports.Tlv0_2WireFormat = Tlv0_2WireFormat;
+
+// Default object.
+Tlv0_2WireFormat.instance = null;
+
+/**
+ * Encode name as an NDN-TLV Name and return the encoding.
+ * @param {Name} name The Name to encode.
+ * @return {Blobl} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeName = function(name)
+{
+  var encoder = new TlvEncoder();
+  Tlv0_2WireFormat.encodeName(name, encoder);
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode input as a NDN-TLV name and set the fields of the Name object.
+ * @param {Name} name The Name object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ */
+Tlv0_2WireFormat.prototype.decodeName = function(name, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  Tlv0_2WireFormat.decodeName(name, decoder, copy);
+};
+
+/**
+ * Encode the interest using NDN-TLV and return a Buffer.
+ * @param {Interest} interest The Interest object to encode.
+ * @return {object} An associative array with fields
+ * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
+ * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
+ * the encoding of the beginning of the signed portion, and
+ * signedPortionEndOffset is the offset in the encoding of the end of the signed
+ * portion. The signed portion starts from the first name component and ends
+ * just before the final name component (which is assumed to be a signature for
+ * a signed interest).
+ */
+Tlv0_2WireFormat.prototype.encodeInterest = function(interest)
+{
+  var encoder = new TlvEncoder(256);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.SelectedDelegation, interest.getSelectedDelegationIndex());
+  var linkWireEncoding = interest.getLinkWireEncoding(this);
+  if (!linkWireEncoding.isNull())
+    // Encode the entire link as is.
+    encoder.writeBuffer(linkWireEncoding.buf());
+
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.InterestLifetime, interest.getInterestLifetimeMilliseconds());
+
+  // Encode the Nonce as 4 bytes.
+  if (interest.getNonce().isNull() || interest.getNonce().size() == 0)
+    // This is the most common case. Generate a nonce.
+    encoder.writeBlobTlv(Tlv.Nonce, Crypto.randomBytes(4));
+  else if (interest.getNonce().size() < 4) {
+    var nonce = Buffer(4);
+    // Copy existing nonce bytes.
+    interest.getNonce().buf().copy(nonce);
+
+    // Generate random bytes for remaining bytes in the nonce.
+    for (var i = interest.getNonce().size(); i < 4; ++i)
+      nonce[i] = Crypto.randomBytes(1)[0];
+
+    encoder.writeBlobTlv(Tlv.Nonce, nonce);
+  }
+  else if (interest.getNonce().size() == 4)
+    // Use the nonce as-is.
+    encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().buf());
+  else
+    // Truncate.
+    encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().buf().slice(0, 4));
+
+  Tlv0_2WireFormat.encodeSelectors(interest, encoder);
+  var tempOffsets = Tlv0_2WireFormat.encodeName(interest.getName(), encoder);
+  var signedPortionBeginOffsetFromBack =
+    encoder.getLength() - tempOffsets.signedPortionBeginOffset;
+  var signedPortionEndOffsetFromBack =
+    encoder.getLength() - tempOffsets.signedPortionEndOffset;
+
+  encoder.writeTypeAndLength(Tlv.Interest, encoder.getLength() - saveLength);
+  var signedPortionBeginOffset =
+    encoder.getLength() - signedPortionBeginOffsetFromBack;
+  var signedPortionEndOffset =
+    encoder.getLength() - signedPortionEndOffsetFromBack;
+
+  return { encoding: new Blob(encoder.getOutput(), false),
+           signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Decode input as an NDN-TLV interest and set the fields of the interest
+ * object.
+ * @param {Interest} interest The Interest object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion. The signed portion starts from the first
+ * name component and ends just before the final name component (which is
+ * assumed to be a signature for a signed interest).
+ */
+Tlv0_2WireFormat.prototype.decodeInterest = function(interest, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Interest);
+  var offsets = Tlv0_2WireFormat.decodeName(interest.getName(), decoder, copy);
+  if (decoder.peekType(Tlv.Selectors, endOffset))
+    Tlv0_2WireFormat.decodeSelectors(interest, decoder, copy);
+  // Require a Nonce, but don't force it to be 4 bytes.
+  var nonce = decoder.readBlobTlv(Tlv.Nonce);
+  interest.setInterestLifetimeMilliseconds
+    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime, endOffset));
+
+  if (decoder.peekType(Tlv.Data, endOffset)) {
+    // Get the bytes of the Link TLV.
+    var linkBeginOffset = decoder.getOffset();
+    var linkEndOffset = decoder.readNestedTlvsStart(Tlv.Data);
+    decoder.seek(linkEndOffset);
+
+    interest.setLinkWireEncoding
+      (new Blob(decoder.getSlice(linkBeginOffset, linkEndOffset), copy), this);
+  }
+  else
+    interest.unsetLink();
+  interest.setSelectedDelegationIndex
+    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.SelectedDelegation, endOffset));
+  if (interest.getSelectedDelegationIndex() != null &&
+      interest.getSelectedDelegationIndex() >= 0 && !interest.hasLink())
+    throw new Error("Interest has a selected delegation, but no link object");
+
+  // Set the nonce last because setting other interest fields clears it.
+  interest.setNonce(new Blob(nonce, copy));
+
+  decoder.finishNestedTlvs(endOffset);
+  return offsets;
+};
+
+/**
+ * Encode data as NDN-TLV and return the encoding and signed offsets.
+ * @param {Data} data The Data object to encode.
+ * @return {object} An associative array with fields
+ * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
+ * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
+ * the encoding of the beginning of the signed portion, and
+ * signedPortionEndOffset is the offset in the encoding of the end of the
+ * signed portion.
+ */
+Tlv0_2WireFormat.prototype.encodeData = function(data)
+{
+  var encoder = new TlvEncoder(1500);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  encoder.writeBlobTlv(Tlv.SignatureValue, data.getSignature().getSignature().buf());
+  var signedPortionEndOffsetFromBack = encoder.getLength();
+
+  Tlv0_2WireFormat.encodeSignatureInfo_(data.getSignature(), encoder);
+  encoder.writeBlobTlv(Tlv.Content, data.getContent().buf());
+  Tlv0_2WireFormat.encodeMetaInfo(data.getMetaInfo(), encoder);
+  Tlv0_2WireFormat.encodeName(data.getName(), encoder);
+  var signedPortionBeginOffsetFromBack = encoder.getLength();
+
+  encoder.writeTypeAndLength(Tlv.Data, encoder.getLength() - saveLength);
+  var signedPortionBeginOffset =
+    encoder.getLength() - signedPortionBeginOffsetFromBack;
+  var signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;
+
+  return { encoding: new Blob(encoder.getOutput(), false),
+           signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Decode input as an NDN-TLV data packet, set the fields in the data object,
+ * and return the signed offsets.
+ * @param {Data} data The Data object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion.
+ */
+Tlv0_2WireFormat.prototype.decodeData = function(data, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Data);
+  var signedPortionBeginOffset = decoder.getOffset();
+
+  Tlv0_2WireFormat.decodeName(data.getName(), decoder, copy);
+  Tlv0_2WireFormat.decodeMetaInfo(data.getMetaInfo(), decoder, copy);
+  data.setContent(new Blob(decoder.readBlobTlv(Tlv.Content), copy));
+  Tlv0_2WireFormat.decodeSignatureInfo(data, decoder, copy);
+
+  var signedPortionEndOffset = decoder.getOffset();
+  data.getSignature().setSignature
+    (new Blob(decoder.readBlobTlv(Tlv.SignatureValue), copy));
+
+  decoder.finishNestedTlvs(endOffset);
+  return { signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Encode controlParameters as NDN-TLV and return the encoding.
+ * @param {ControlParameters} controlParameters The ControlParameters object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeControlParameters = function(controlParameters)
+{
+  var encoder = new TlvEncoder(256);
+  Tlv0_2WireFormat.encodeControlParameters(controlParameters, encoder);
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+  * Decode controlParameters in NDN-TLV and return the encoding.
+  * @param {ControlParameters} controlParameters The ControlParameters object to
+  * encode.
+  * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+  * @throws DecodingException For invalid encoding
+  */
+Tlv0_2WireFormat.prototype.decodeControlParameters = function
+  (controlParameters, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  Tlv0_2WireFormat.decodeControlParameters(controlParameters, decoder, copy);
+};
+
+/**
+ * Encode controlResponse as NDN-TLV and return the encoding.
+ * @param {ControlResponse} controlResponse The ControlResponse object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeControlResponse = function(controlResponse)
+{
+  var encoder = new TlvEncoder(256);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+
+  // Encode the body.
+  if (controlResponse.getBodyAsControlParameters() != null)
+    Tlv0_2WireFormat.encodeControlParameters
+      (controlResponse.getBodyAsControlParameters(), encoder);
+
+  encoder.writeBlobTlv
+    (Tlv.NfdCommand_StatusText, new Blob(controlResponse.getStatusText()).buf());
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.NfdCommand_StatusCode, controlResponse.getStatusCode());
+
+  encoder.writeTypeAndLength
+    (Tlv.NfdCommand_ControlResponse, encoder.getLength() - saveLength);
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode controlResponse in NDN-TLV and return the encoding.
+ * @param {ControlResponse} controlResponse The ControlResponse object to
+ * encode.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws DecodingException For invalid encoding
+ */
+Tlv0_2WireFormat.prototype.decodeControlResponse = function
+  (controlResponse, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  var endOffset = decoder.readNestedTlvsStart(Tlv.NfdCommand_ControlResponse);
+
+  controlResponse.setStatusCode(decoder.readNonNegativeIntegerTlv
+    (Tlv.NfdCommand_StatusCode));
+  // Set copy false since we just immediately get a string.
+  var statusText = new Blob
+    (decoder.readBlobTlv(Tlv.NfdCommand_StatusText), false);
+  controlResponse.setStatusText(statusText.toString());
+
+  // Decode the body.
+  if (decoder.peekType(Tlv.ControlParameters_ControlParameters, endOffset)) {
+    controlResponse.setBodyAsControlParameters(new ControlParameters());
+    // Decode into the existing ControlParameters to avoid copying.
+    Tlv0_2WireFormat.decodeControlParameters
+      (controlResponse.getBodyAsControlParameters(), decoder, copy);
+  }
+  else
+    controlResponse.setBodyAsControlParameters(null);
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * Encode signature as an NDN-TLV SignatureInfo and return the encoding.
+ * @param {Signature} signature An object of a subclass of Signature to encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeSignatureInfo = function(signature)
+{
+  var encoder = new TlvEncoder(256);
+  Tlv0_2WireFormat.encodeSignatureInfo_(signature, encoder);
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+// SignatureHolder is used by decodeSignatureInfoAndValue.
+Tlv0_2WireFormat.SignatureHolder = function Tlv0_2WireFormatSignatureHolder()
+{
+};
+
+Tlv0_2WireFormat.SignatureHolder.prototype.setSignature = function(signature)
+{
+  this.signature = signature;
+};
+
+Tlv0_2WireFormat.SignatureHolder.prototype.getSignature = function()
+{
+  return this.signature;
+};
+
+/**
+ * Decode signatureInfo as an NDN-TLV SignatureInfo and signatureValue as the
+ * related SignatureValue, and return a new object which is a subclass of Signature.
+ * @param {Buffer} signatureInfo The buffer with the signature info bytes to
+ * decode.
+ * @param {Buffer} signatureValue The buffer with the signature value to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {Signature} A new object which is a subclass of Signature.
+ */
+Tlv0_2WireFormat.prototype.decodeSignatureInfoAndValue = function
+  (signatureInfo, signatureValue, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  // Use a SignatureHolder to imitate a Data object for decodeSignatureInfo.
+  var signatureHolder = new Tlv0_2WireFormat.SignatureHolder();
+  var decoder = new TlvDecoder(signatureInfo);
+  Tlv0_2WireFormat.decodeSignatureInfo(signatureHolder, decoder, copy);
+
+  decoder = new TlvDecoder(signatureValue);
+  signatureHolder.getSignature().setSignature
+    (new Blob(decoder.readBlobTlv(Tlv.SignatureValue), copy));
+
+  return signatureHolder.getSignature();
+};
+
+/**
+ * Encode the signatureValue in the Signature object as an NDN-TLV
+ * SignatureValue (the signature bits) and return the encoding.
+ * @param {Signature} signature An object of a subclass of Signature with the
+ * signature value to encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeSignatureValue = function(signature)
+{
+  var encoder = new TlvEncoder(256);
+  encoder.writeBlobTlv(Tlv.SignatureValue, signature.getSignature().buf());
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object.
+ * @param {LpPacket} lpPacket The LpPacket object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ */
+Tlv0_2WireFormat.prototype.decodeLpPacket = function(lpPacket, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  lpPacket.clear();
+
+  var decoder = new TlvDecoder(input);
+  var endOffset = decoder.readNestedTlvsStart(Tlv.LpPacket_LpPacket);
+
+  while (decoder.getOffset() < endOffset) {
+    // Imitate TlvDecoder.readTypeAndLength.
+    var fieldType = decoder.readVarNumber();
+    var fieldLength = decoder.readVarNumber();
+    var fieldEndOffset = decoder.getOffset() + fieldLength;
+    if (fieldEndOffset > input.length)
+      throw new DecodingException(new Error("TLV length exceeds the buffer length"));
+
+    if (fieldType == Tlv.LpPacket_Fragment) {
+      // Set the fragment to the bytes of the TLV value.
+      lpPacket.setFragmentWireEncoding
+        (new Blob(decoder.getSlice(decoder.getOffset(), fieldEndOffset), copy));
+      decoder.seek(fieldEndOffset);
+
+      // The fragment is supposed to be the last field.
+      break;
+    }
+    else if (fieldType == Tlv.LpPacket_Nack) {
+      var networkNack = new NetworkNack();
+      var code = decoder.readOptionalNonNegativeIntegerTlv
+        (Tlv.LpPacket_NackReason, fieldEndOffset);
+      var reason;
+      // The enum numeric values are the same as this wire format, so use as is.
+      if (code < 0 || code == NetworkNack.Reason.NONE)
+        // This includes an omitted NackReason.
+        networkNack.setReason(NetworkNack.Reason.NONE);
+      else if (code == NetworkNack.Reason.CONGESTION ||
+               code == NetworkNack.Reason.DUPLICATE ||
+               code == NetworkNack.Reason.NO_ROUTE)
+        networkNack.setReason(code);
+      else {
+        // Unrecognized reason.
+        networkNack.setReason(NetworkNack.Reason.OTHER_CODE);
+        networkNack.setOtherReasonCode(code);
+      }
+
+      lpPacket.addHeaderField(networkNack);
+    }
+    else if (fieldType == Tlv.LpPacket_IncomingFaceId) {
+      var incomingFaceId = new IncomingFaceId();
+      incomingFaceId.setFaceId(decoder.readNonNegativeInteger(fieldLength));
+      lpPacket.addHeaderField(incomingFaceId);
+    }
+    else {
+      // Unrecognized field type. The conditions for ignoring are here:
+      // http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
+      var canIgnore =
+        (fieldType >= Tlv.LpPacket_IGNORE_MIN &&
+         fieldType <= Tlv.LpPacket_IGNORE_MAX &&
+         (fieldType & 0x01) === 1);
+      if  (!canIgnore)
+        throw new DecodingException(new Error("Did not get the expected TLV type"));
+
+      // Ignore.
+      decoder.seek(fieldEndOffset);
+    }
+
+    decoder.finishNestedTlvs(fieldEndOffset);
+  }
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * Encode delegationSet as a sequence of NDN-TLV Delegation, and return the
+ * encoding. Note that the sequence of Delegation does not have an outer TLV
+ * type and length because it is intended to use the type and length of a Data
+ * packet's Content.
+ * @param {DelegationSet} delegationSet The DelegationSet object to encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeDelegationSet = function(delegationSet)
+{
+  var encoder = new TlvEncoder(256);
+
+  // Encode backwards.
+  for (var i = delegationSet.size() - 1; i >= 0; --i) {
+    var saveLength = encoder.getLength();
+
+    Tlv0_2WireFormat.encodeName(delegationSet.get(i).getName(), encoder);
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.Link_Preference, delegationSet.get(i).getPreference());
+
+    encoder.writeTypeAndLength
+      (Tlv.Link_Delegation, encoder.getLength() - saveLength);
+  }
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode input as a sequence of NDN-TLV Delegation and set the fields of the
+ * delegationSet object. Note that the sequence of Delegation does not have an
+ * outer TLV type and length because it is intended to use the type and length
+ * of a Data packet's Content. This ignores any elements after the sequence
+ * of Delegation.
+ * @param {DelegationSet} delegationSet The DelegationSet object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ */
+Tlv0_2WireFormat.prototype.decodeDelegationSet = function
+  (delegationSet, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  var endOffset = input.length;
+
+  delegationSet.clear();
+  while (decoder.getOffset() < endOffset) {
+    decoder.readTypeAndLength(Tlv.Link_Delegation);
+    var preference = decoder.readNonNegativeIntegerTlv(Tlv.Link_Preference);
+    var name = new Name();
+    Tlv0_2WireFormat.decodeName(name, decoder, copy);
+
+    // Add unsorted to preserve the order so that Interest selected delegation
+    // index will work.
+    delegationSet.addUnsorted(preference, name);
+  }
+};
+
+/**
+ * Encode the EncryptedContent in NDN-TLV and return the encoding.
+ * @param {EncryptedContent} encryptedContent The EncryptedContent object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeEncryptedContent = function(encryptedContent)
+{
+  var encoder = new TlvEncoder(256);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  encoder.writeBlobTlv
+    (Tlv.Encrypt_EncryptedPayload, encryptedContent.getPayload().buf());
+  encoder.writeOptionalBlobTlv
+    (Tlv.Encrypt_InitialVector, encryptedContent.getInitialVector().buf());
+  // Assume the algorithmType value is the same as the TLV type.
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_EncryptionAlgorithm, encryptedContent.getAlgorithmType());
+  Tlv0_2WireFormat.encodeKeyLocator
+    (Tlv.KeyLocator, encryptedContent.getKeyLocator(), encoder);
+
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_EncryptedContent, encoder.getLength() - saveLength);
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode input as an EncryptedContent in NDN-TLV and set the fields of the
+ * encryptedContent object.
+ * @param {EncryptedContent} encryptedContent The EncryptedContent object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ */
+Tlv0_2WireFormat.prototype.decodeEncryptedContent = function
+  (encryptedContent, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  var endOffset = decoder.
+    readNestedTlvsStart(Tlv.Encrypt_EncryptedContent);
+
+  Tlv0_2WireFormat.decodeKeyLocator
+    (Tlv.KeyLocator, encryptedContent.getKeyLocator(), decoder, copy);
+  encryptedContent.setAlgorithmType
+    (decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_EncryptionAlgorithm));
+  encryptedContent.setInitialVector
+    (new Blob(decoder.readOptionalBlobTlv
+     (Tlv.Encrypt_InitialVector, endOffset), copy));
+  encryptedContent.setPayload
+    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_EncryptedPayload), copy));
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * Get a singleton instance of a Tlv0_2WireFormat.  To always use the
+ * preferred version NDN-TLV, you should use TlvWireFormat.get().
+ * @return {Tlv0_2WireFormat} The singleton instance.
+ */
+Tlv0_2WireFormat.get = function()
+{
+  if (Tlv0_2WireFormat.instance === null)
+    Tlv0_2WireFormat.instance = new Tlv0_2WireFormat();
+  return Tlv0_2WireFormat.instance;
+};
+
+/**
+ * Encode the name component to the encoder as NDN-TLV. This handles different
+ * component types such as ImplicitSha256DigestComponent.
+ * @param {Name.Component} component The name component to encode.
+ * @param {TlvEncoder} encoder The encoder to receive the encoding.
+ */
+Tlv0_2WireFormat.encodeNameComponent = function(component, encoder)
+{
+  var type = component.isImplicitSha256Digest() ?
+      Tlv.ImplicitSha256DigestComponent : Tlv.NameComponent;
+  encoder.writeBlobTlv(type, component.getValue().buf());
+};
+
+/**
+ * Decode the name component as NDN-TLV and return the component. This handles
+ * different component types such as ImplicitSha256DigestComponent.
+ * @param {TlvDecoder} decoder The decoder with the input.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {Name.Component} A new Name.Component.
+ */
+Tlv0_2WireFormat.decodeNameComponent = function(decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var savePosition = decoder.getOffset();
+  var type = decoder.readVarNumber();
+  // Restore the position.
+  decoder.seek(savePosition);
+
+  var value = new Blob(decoder.readBlobTlv(type), copy);
+  if (type === Tlv.ImplicitSha256DigestComponent)
+    return Name.Component.fromImplicitSha256Digest(value);
+  else
+    return new Name.Component(value);
+};
+
+/**
+ * Encode the name to the encoder.
+ * @param {Name} name The name to encode.
+ * @param {TlvEncoder} encoder The encoder to receive the encoding.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion. The signed portion starts from the first
+ * name component and ends just before the final name component (which is
+ * assumed to be a signature for a signed interest).
+ */
+Tlv0_2WireFormat.encodeName = function(name, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode the components backwards.
+  var signedPortionEndOffsetFromBack;
+  for (var i = name.size() - 1; i >= 0; --i) {
+    Tlv0_2WireFormat.encodeNameComponent(name.get(i), encoder);
+    if (i == name.size() - 1)
+      signedPortionEndOffsetFromBack = encoder.getLength();
+  }
+
+  var signedPortionBeginOffsetFromBack = encoder.getLength();
+  encoder.writeTypeAndLength(Tlv.Name, encoder.getLength() - saveLength);
+
+  var signedPortionBeginOffset =
+    encoder.getLength() - signedPortionBeginOffsetFromBack;
+  var signedPortionEndOffset;
+  if (name.size() == 0)
+    // There is no "final component", so set signedPortionEndOffset arbitrarily.
+    signedPortionEndOffset = signedPortionBeginOffset;
+  else
+    signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;
+
+  return { signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Clear the name, decode a Name from the decoder and set the fields of the name
+ * object.
+ * @param {Name} name The name object whose fields are updated.
+ * @param {TlvDecoder} decoder The decoder with the input.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion. The signed portion starts from the first
+ * name component and ends just before the final name component (which is
+ * assumed to be a signature for a signed interest).
+ */
+Tlv0_2WireFormat.decodeName = function(name, decoder, copy)
+{
+  name.clear();
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Name);
+  var signedPortionBeginOffset = decoder.getOffset();
+  // In case there are no components, set signedPortionEndOffset arbitrarily.
+  var signedPortionEndOffset = signedPortionBeginOffset;
+
+  while (decoder.getOffset() < endOffset) {
+    signedPortionEndOffset = decoder.getOffset();
+    name.append(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
+  }
+
+  decoder.finishNestedTlvs(endOffset);
+
+  return { signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Encode the interest selectors.  If no selectors are written, do not output a
+ * Selectors TLV.
+ */
+Tlv0_2WireFormat.encodeSelectors = function(interest, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  if (interest.getMustBeFresh())
+    encoder.writeTypeAndLength(Tlv.MustBeFresh, 0);
+  encoder.writeOptionalNonNegativeIntegerTlv(
+    Tlv.ChildSelector, interest.getChildSelector());
+  if (interest.getExclude().size() > 0)
+    Tlv0_2WireFormat.encodeExclude(interest.getExclude(), encoder);
+
+  if (interest.getKeyLocator().getType() != null)
+    Tlv0_2WireFormat.encodeKeyLocator
+      (Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), encoder);
+
+  encoder.writeOptionalNonNegativeIntegerTlv(
+    Tlv.MaxSuffixComponents, interest.getMaxSuffixComponents());
+  encoder.writeOptionalNonNegativeIntegerTlv(
+    Tlv.MinSuffixComponents, interest.getMinSuffixComponents());
+
+  // Only output the type and length if values were written.
+  if (encoder.getLength() != saveLength)
+    encoder.writeTypeAndLength(Tlv.Selectors, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeSelectors = function(interest, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Selectors);
+
+  interest.setMinSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.MinSuffixComponents, endOffset));
+  interest.setMaxSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.MaxSuffixComponents, endOffset));
+
+  if (decoder.peekType(Tlv.PublisherPublicKeyLocator, endOffset))
+    Tlv0_2WireFormat.decodeKeyLocator
+      (Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), decoder, copy);
+  else
+    interest.getKeyLocator().clear();
+
+  if (decoder.peekType(Tlv.Exclude, endOffset))
+    Tlv0_2WireFormat.decodeExclude(interest.getExclude(), decoder, copy);
+  else
+    interest.getExclude().clear();
+
+  interest.setChildSelector(decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.ChildSelector, endOffset));
+  interest.setMustBeFresh(decoder.readBooleanTlv(Tlv.MustBeFresh, endOffset));
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+Tlv0_2WireFormat.encodeExclude = function(exclude, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // TODO: Do we want to order the components (except for ANY)?
+  // Encode the entries backwards.
+  for (var i = exclude.size() - 1; i >= 0; --i) {
+    var entry = exclude.get(i);
+
+    if (entry == Exclude.ANY)
+      encoder.writeTypeAndLength(Tlv.Any, 0);
+    else
+      Tlv0_2WireFormat.encodeNameComponent(entry, encoder);
+  }
+
+  encoder.writeTypeAndLength(Tlv.Exclude, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeExclude = function(exclude, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Exclude);
+
+  exclude.clear();
+  while (decoder.getOffset() < endOffset) {
+    if (decoder.peekType(Tlv.Any, endOffset)) {
+      // Read past the Any TLV.
+      decoder.readBooleanTlv(Tlv.Any, endOffset);
+      exclude.appendAny();
+    }
+    else
+      exclude.appendComponent(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
+  }
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+Tlv0_2WireFormat.encodeKeyLocator = function(type, keyLocator, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  if (keyLocator.getType() != null) {
+    if (keyLocator.getType() == KeyLocatorType.KEYNAME)
+      Tlv0_2WireFormat.encodeName(keyLocator.getKeyName(), encoder);
+    else if (keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST &&
+             keyLocator.getKeyData().size() > 0)
+      encoder.writeBlobTlv(Tlv.KeyLocatorDigest, keyLocator.getKeyData().buf());
+    else
+      throw new Error("Unrecognized KeyLocatorType " + keyLocator.getType());
+  }
+
+  encoder.writeTypeAndLength(type, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeKeyLocator = function
+  (expectedType, keyLocator, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var endOffset = decoder.readNestedTlvsStart(expectedType);
+
+  keyLocator.clear();
+
+  if (decoder.getOffset() == endOffset)
+    // The KeyLocator is omitted, so leave the fields as none.
+    return;
+
+  if (decoder.peekType(Tlv.Name, endOffset)) {
+    // KeyLocator is a Name.
+    keyLocator.setType(KeyLocatorType.KEYNAME);
+    Tlv0_2WireFormat.decodeName(keyLocator.getKeyName(), decoder, copy);
+  }
+  else if (decoder.peekType(Tlv.KeyLocatorDigest, endOffset)) {
+    // KeyLocator is a KeyLocatorDigest.
+    keyLocator.setType(KeyLocatorType.KEY_LOCATOR_DIGEST);
+    keyLocator.setKeyData
+      (new Blob(decoder.readBlobTlv(Tlv.KeyLocatorDigest), copy));
+  }
+  else
+    throw new DecodingException(new Error
+      ("decodeKeyLocator: Unrecognized key locator type"));
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * An internal method to encode signature as the appropriate form of
+ * SignatureInfo in NDN-TLV.
+ * @param {Signature} signature An object of a subclass of Signature to encode.
+ * @param {TlvEncoder} encoder The encoder.
+ */
+Tlv0_2WireFormat.encodeSignatureInfo_ = function(signature, encoder)
+{
+  if (signature instanceof GenericSignature) {
+    // Handle GenericSignature separately since it has the entire encoding.
+    var encoding = signature.getSignatureInfoEncoding();
+
+    // Do a test decoding to sanity check that it is valid TLV.
+    try {
+      var decoder = new TlvDecoder(encoding.buf());
+      var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);
+      decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
+      decoder.finishNestedTlvs(endOffset);
+    } catch (ex) {
+      throw new Error
+        ("The GenericSignature encoding is not a valid NDN-TLV SignatureInfo: " +
+         ex.message);
+    }
+
+    encoder.writeBuffer(encoding.buf());
+    return;
+  }
+
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  if (signature instanceof Sha256WithRsaSignature) {
+    Tlv0_2WireFormat.encodeKeyLocator
+      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithRsa);
+  }
+  else if (signature instanceof Sha256WithEcdsaSignature) {
+    Tlv0_2WireFormat.encodeKeyLocator
+      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithEcdsa);
+  }
+  else if (signature instanceof HmacWithSha256Signature) {
+    Tlv0_2WireFormat.encodeKeyLocator
+      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.SignatureType, Tlv.SignatureType_SignatureHmacWithSha256);
+  }
+  else if (signature instanceof DigestSha256Signature)
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.SignatureType, Tlv.SignatureType_DigestSha256);
+  else
+    throw new Error("encodeSignatureInfo: Unrecognized Signature object type");
+
+  encoder.writeTypeAndLength(Tlv.SignatureInfo, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeSignatureInfo = function(data, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var beginOffset = decoder.getOffset();
+  var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);
+
+  var signatureType = decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
+  if (signatureType == Tlv.SignatureType_SignatureSha256WithRsa) {
+    data.setSignature(new Sha256WithRsaSignature());
+    // Modify data's signature object because if we create an object
+    //   and set it, then data will have to copy all the fields.
+    var signatureInfo = data.getSignature();
+    Tlv0_2WireFormat.decodeKeyLocator
+      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
+  }
+  else if (signatureType == Tlv.SignatureType_SignatureSha256WithEcdsa) {
+    data.setSignature(new Sha256WithEcdsaSignature());
+    var signatureInfo = data.getSignature();
+    Tlv0_2WireFormat.decodeKeyLocator
+      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
+  }
+  else if (signatureType == Tlv.SignatureType_SignatureHmacWithSha256) {
+    data.setSignature(new HmacWithSha256Signature());
+    var signatureInfo = data.getSignature();
+    Tlv0_2WireFormat.decodeKeyLocator
+      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
+  }
+  else if (signatureType == Tlv.SignatureType_DigestSha256)
+    data.setSignature(new DigestSha256Signature());
+  else {
+    data.setSignature(new GenericSignature());
+    var signatureInfo = data.getSignature();
+
+    // Get the bytes of the SignatureInfo TLV.
+    signatureInfo.setSignatureInfoEncoding
+      (new Blob(decoder.getSlice(beginOffset, endOffset), copy), signatureType);
+  }
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+Tlv0_2WireFormat.encodeMetaInfo = function(metaInfo, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  var finalBlockIdBuf = metaInfo.getFinalBlockId().getValue().buf();
+  if (finalBlockIdBuf != null && finalBlockIdBuf.length > 0) {
+    // FinalBlockId has an inner NameComponent.
+    var finalBlockIdSaveLength = encoder.getLength();
+    Tlv0_2WireFormat.encodeNameComponent(metaInfo.getFinalBlockId(), encoder);
+    encoder.writeTypeAndLength
+      (Tlv.FinalBlockId, encoder.getLength() - finalBlockIdSaveLength);
+  }
+
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.FreshnessPeriod, metaInfo.getFreshnessPeriod());
+  if (metaInfo.getType() != ContentType.BLOB) {
+    // Not the default, so we need to encode the type.
+    if (metaInfo.getType() == ContentType.LINK ||
+        metaInfo.getType() == ContentType.KEY ||
+        metaInfo.getType() == ContentType.NACK)
+      // The ContentType enum is set up with the correct integer for
+      // each NDN-TLV ContentType.
+      encoder.writeNonNegativeIntegerTlv(Tlv.ContentType, metaInfo.getType());
+    else if (metaInfo.getType() == ContentType.OTHER_CODE)
+      encoder.writeNonNegativeIntegerTlv
+        (Tlv.ContentType, metaInfo.getOtherTypeCode());
+    else
+      // We don't expect this to happen.
+      throw new Error("unrecognized TLV ContentType");
+  }
+
+  encoder.writeTypeAndLength(Tlv.MetaInfo, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeMetaInfo = function(metaInfo, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.MetaInfo);
+
+  var type = decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.ContentType, endOffset);
+  if (type == null || type < 0 || type === ContentType.BLOB)
+    metaInfo.setType(ContentType.BLOB);
+  else if (type === ContentType.LINK ||
+           type === ContentType.KEY ||
+           type === ContentType.NACK)
+    // The ContentType enum is set up with the correct integer for each NDN-TLV
+    // ContentType.
+    metaInfo.setType(type);
+  else {
+    // Unrecognized content type.
+    metaInfo.setType(ContentType.OTHER_CODE);
+    metaInfo.setOtherTypeCode(type);
+  }
+
+  metaInfo.setFreshnessPeriod
+    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod, endOffset));
+  if (decoder.peekType(Tlv.FinalBlockId, endOffset)) {
+    var finalBlockIdEndOffset = decoder.readNestedTlvsStart(Tlv.FinalBlockId);
+    metaInfo.setFinalBlockId(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
+    decoder.finishNestedTlvs(finalBlockIdEndOffset);
+  }
+  else
+    metaInfo.setFinalBlockId(null);
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+Tlv0_2WireFormat.encodeControlParameters = function(controlParameters, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_ExpirationPeriod,
+     controlParameters.getExpirationPeriod());
+
+  if (controlParameters.getStrategy().size() > 0){
+    var strategySaveLength = encoder.getLength();
+    Tlv0_2WireFormat.encodeName(controlParameters.getStrategy(), encoder);
+    encoder.writeTypeAndLength(Tlv.ControlParameters_Strategy,
+      encoder.getLength() - strategySaveLength);
+  }
+
+  var flags = controlParameters.getForwardingFlags().getNfdForwardingFlags();
+  if (flags != new ForwardingFlags().getNfdForwardingFlags())
+      // The flags are not the default value.
+      encoder.writeNonNegativeIntegerTlv
+        (Tlv.ControlParameters_Flags, flags);
+
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_Cost, controlParameters.getCost());
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_Origin, controlParameters.getOrigin());
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_LocalControlFeature,
+     controlParameters.getLocalControlFeature());
+
+  if (controlParameters.getUri().length != 0)
+    encoder.writeBlobTlv
+      (Tlv.ControlParameters_Uri, new Blob(controlParameters.getUri()).buf());
+
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_FaceId, controlParameters.getFaceId());
+  if (controlParameters.getName() != null)
+    Tlv0_2WireFormat.encodeName(controlParameters.getName(), encoder);
+
+  encoder.writeTypeAndLength
+    (Tlv.ControlParameters_ControlParameters, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeControlParameters = function
+  (controlParameters, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  controlParameters.clear();
+  var endOffset = decoder.
+    readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);
+
+  // decode name
+  if (decoder.peekType(Tlv.Name, endOffset)) {
+    var name = new Name();
+    Tlv0_2WireFormat.decodeName(name, decoder, copy);
+    controlParameters.setName(name);
+  }
+
+  // decode face ID
+  controlParameters.setFaceId(decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_FaceId, endOffset));
+
+  // decode URI
+  if (decoder.peekType(Tlv.ControlParameters_Uri, endOffset)) {
+    // Set copy false since we just immediately get the string.
+    var uri = new Blob
+      (decoder.readOptionalBlobTlv(Tlv.ControlParameters_Uri, endOffset), false);
+    controlParameters.setUri(uri.toString());
+  }
+
+  // decode integers
+  controlParameters.setLocalControlFeature(decoder.
+    readOptionalNonNegativeIntegerTlv(
+      Tlv.ControlParameters_LocalControlFeature, endOffset));
+  controlParameters.setOrigin(decoder.
+    readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin,
+      endOffset));
+  controlParameters.setCost(decoder.readOptionalNonNegativeIntegerTlv(
+    Tlv.ControlParameters_Cost, endOffset));
+
+  // set forwarding flags
+  if (decoder.peekType(Tlv.ControlParameters_Flags, endOffset)) {
+    var flags = new ForwardingFlags();
+    flags.setNfdForwardingFlags(decoder.
+      readNonNegativeIntegerTlv(Tlv.ControlParameters_Flags, endOffset));
+    controlParameters.setForwardingFlags(flags);
+  }
+
+  // decode strategy
+  if (decoder.peekType(Tlv.ControlParameters_Strategy, endOffset)) {
+    var strategyEndOffset = decoder.readNestedTlvsStart(Tlv.ControlParameters_Strategy);
+    Tlv0_2WireFormat.decodeName(controlParameters.getStrategy(), decoder, copy);
+    decoder.finishNestedTlvs(strategyEndOffset);
+  }
+
+  // decode expiration period
+  controlParameters.setExpirationPeriod(
+    decoder.readOptionalNonNegativeIntegerTlv(
+      Tlv.ControlParameters_ExpirationPeriod, endOffset));
+
+  decoder.finishNestedTlvs(endOffset);
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Tlv0_2WireFormat = require('./tlv-0_2-wire-format.js').Tlv0_2WireFormat;
+
+/**
+ * A Tlv0_1_1WireFormat extends Tlv0_2WireFormat so that it is an alias in case
+ * any applications use Tlv0_1_1WireFormat directly.  These two wire formats are
+ * the same except that Tlv0_2WireFormat adds support for the name component
+ * type ImplicitSha256Digest.
+ * @constructor
+ */
+var Tlv0_1_1WireFormat = function Tlv0_1_1WireFormat()
+{
+  // Inherit from Tlv0_2WireFormat.
+  Tlv0_2WireFormat.call(this);
+};
+
+Tlv0_1_1WireFormat.prototype = new Tlv0_2WireFormat();
+Tlv0_1_1WireFormat.prototype.name = "Tlv0_1_1WireFormat";
+
+exports.Tlv0_1_1WireFormat = Tlv0_1_1WireFormat;
+
+// Default object.
+Tlv0_1_1WireFormat.instance = null;
+
+/**
+ * Get a singleton instance of a Tlv0_1_1WireFormat.
+ * @return {Tlv0_1_1WireFormat} The singleton instance.
+ */
+Tlv0_1_1WireFormat.get = function()
+{
+  if (Tlv0_1_1WireFormat.instance === null)
+    Tlv0_1_1WireFormat.instance = new Tlv0_1_1WireFormat();
+  return Tlv0_1_1WireFormat.instance;
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
+var Tlv0_1_1WireFormat = require('./tlv-0_1_1-wire-format.js').Tlv0_1_1WireFormat;
+
+/**
+ * A Tlv0_1WireFormat extends Tlv0_1_1WireFormat so that it is an alias in case
+ * any applications use Tlv0_1WireFormat directly.  These two wire formats are
+ * the same except that Tlv0_1_1WireFormat adds support for
+ * Sha256WithEcdsaSignature.
+ * @constructor
+ */
+var Tlv0_1WireFormat = function Tlv0_1WireFormat()
+{
+  // Inherit from Tlv0_1_1WireFormat.
+  Tlv0_1_1WireFormat.call(this);
+};
+
+Tlv0_1WireFormat.prototype = new Tlv0_1_1WireFormat();
+Tlv0_1WireFormat.prototype.name = "Tlv0_1WireFormat";
+
+exports.Tlv0_1WireFormat = Tlv0_1WireFormat;
+
+// Default object.
+Tlv0_1WireFormat.instance = null;
+
+/**
+ * Get a singleton instance of a Tlv0_1WireFormat.
+ * @return {Tlv0_1WireFormat} The singleton instance.
+ */
+Tlv0_1WireFormat.get = function()
+{
+  if (Tlv0_1WireFormat.instance === null)
+    Tlv0_1WireFormat.instance = new Tlv0_1WireFormat();
+  return Tlv0_1WireFormat.instance;
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
+var Tlv0_2WireFormat = require('./tlv-0_2-wire-format.js').Tlv0_2WireFormat;
+
+/**
+ * A TlvWireFormat extends WireFormat to override its methods to
+ * implement encoding and decoding using the preferred implementation of NDN-TLV.
+ * @constructor
+ */
+var TlvWireFormat = function TlvWireFormat()
+{
+  // Inherit from Tlv0_2WireFormat.
+  Tlv0_2WireFormat.call(this);
+};
+
+TlvWireFormat.prototype = new Tlv0_2WireFormat();
+TlvWireFormat.prototype.name = "TlvWireFormat";
+
+exports.TlvWireFormat = TlvWireFormat;
+
+// Default object.
+TlvWireFormat.instance = null;
+
+/**
+ * Get a singleton instance of a TlvWireFormat.  Assuming that the default
+ * wire format was set with WireFormat.setDefaultWireFormat(TlvWireFormat.get()),
+ * you can check if this is the default wire encoding with
+ * if WireFormat.getDefaultWireFormat() == TlvWireFormat.get().
+ * @return {TlvWireFormat} The singleton instance.
+ */
+TlvWireFormat.get = function()
+{
+  if (TlvWireFormat.instance === null)
+    TlvWireFormat.instance = new TlvWireFormat();
+  return TlvWireFormat.instance;
+};
+
+// On loading this module, make this the default wire format.
+// This module will be loaded because WireFormat loads it.
+WireFormat.setDefaultWireFormat(TlvWireFormat.get());
+/**
+ * This file contains utilities to help encode and decode NDN objects.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * author: Meki Cheraoui
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DataUtils = require('./data-utils.js').DataUtils; /** @ignore */
+var KeyLocatorType = require('../key-locator.js').KeyLocatorType; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var Sha256WithRsaSignature = require('../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var Sha256WithEcdsaSignature = require('../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
+var HmacWithSha256Signature = require('../hmac-with-sha256-signature.js').HmacWithSha256Signature; /** @ignore */
+var DigestSha256Signature = require('../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
+var ContentType = require('../meta-info.js').ContentType; /** @ignore */
+var WireFormat = require('./wire-format.js').WireFormat;
+
+/**
+ * An EncodingUtils has static methods for encoding data.
+ * @constructor
+ */
+var EncodingUtils = function EncodingUtils()
+{
+};
+
+exports.EncodingUtils = EncodingUtils;
+
+EncodingUtils.encodeToHexInterest = function(interest, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return DataUtils.toHex(interest.wireEncode(wireFormat).buf());
+};
+
+EncodingUtils.encodeToHexData = function(data, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return DataUtils.toHex(data.wireEncode(wireFormat).buf());
+};
+
+EncodingUtils.decodeHexInterest = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  var interest = new Interest();
+  interest.wireDecode(DataUtils.toNumbers(input), wireFormat);
+  return interest;
+};
+
+EncodingUtils.decodeHexData = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  var data = new Data();
+  data.wireDecode(DataUtils.toNumbers(input), wireFormat);
+  return data;
+};
+
+/**
+ * Decode the Buffer array which holds SubjectPublicKeyInfo and return an RSAKey.
+ */
+EncodingUtils.decodeSubjectPublicKeyInfo = function(array)
+{
+  var hex = DataUtils.toHex(array).toLowerCase();
+  var a = _x509_getPublicKeyHexArrayFromCertHex(hex, _x509_getSubjectPublicKeyPosFromCertHex(hex, 0));
+  var rsaKey = new RSAKey();
+  rsaKey.setPublic(a[0], a[1]);
+  return rsaKey;
+}
+
+/**
+ * Return a user friendly HTML string with the contents of data.
+ */
+EncodingUtils.dataToHtml = function(/* Data */ data)
+{
+  if (data == -1)
+    return "NO CONTENT FOUND";
+  if (data == -2)
+    return "CONTENT NAME IS EMPTY";
+
+  var output = "";
+  function append(message) {
+    message = message.replace(/&/g, "&amp;");
+    message = message.replace(/</g, "&lt;");
+
+    output += message;
+    output += "<br/>";
+  }
+
+  // Imitate dumpData in examples/node/test-encode-decode-data.js
+
+  append("name: " + data.getName().toUri());
+  if (data.getContent().size() > 0) {
+    append("content (raw): " + data.getContent().buf().toString('binary'));
+    append("content (hex): " + data.getContent().toHex());
+  }
+  else
+    append("content: <empty>");
+
+  if (!(data.getMetaInfo().getType() == ContentType.BLOB)) {
+    if (data.getMetaInfo().getType() == ContentType.KEY)
+      append("metaInfo.type: KEY");
+    else if (data.getMetaInfo().getType() == ContentType.LINK)
+      append("metaInfo.type: LINK");
+    else if (data.getMetaInfo().getType() == ContentType.NACK)
+      append("metaInfo.type: NACK");
+    else if (data.getMetaInfo().getType() == ContentType.OTHER_CODE)
+      append("metaInfo.type: other code " + data.getMetaInfo().getOtherTypeCode());
+  }
+  append("metaInfo.freshnessPeriod (milliseconds): " +
+    (data.getMetaInfo().getFreshnessPeriod() >= 0 ?
+      "" + data.getMetaInfo().getFreshnessPeriod() : "<none>"));
+  append("metaInfo.finalBlockId: " +
+    (data.getMetaInfo().getFinalBlockId().getValue().size() > 0 ?
+     data.getMetaInfo().getFinalBlockId().getValue().toHex() : "<none>"));
+
+  var keyLocator = null;
+  var signature = data.getSignature();
+  if (signature instanceof Sha256WithRsaSignature) {
+    var signature = data.getSignature();
+    append("Sha256WithRsa signature.signature: " +
+      (signature.getSignature().size() > 0 ?
+       signature.getSignature().toHex() : "<none>"));
+    keyLocator = signature.getKeyLocator();
+  }
+  else if (signature instanceof Sha256WithEcdsaSignature) {
+    var signature = data.getSignature();
+    append("Sha256WithEcdsa signature.signature: " +
+      (signature.getSignature().size() > 0 ?
+       signature.getSignature().toHex() : "<none>"));
+    keyLocator = signature.getKeyLocator();
+  }
+  else if (signature instanceof HmacWithSha256Signature) {
+    var signature = data.getSignature();
+    append("HmacWithSha256 signature.signature: " +
+      (signature.getSignature().size() > 0 ?
+       signature.getSignature().toHex() : "<none>"));
+    keyLocator = signature.getKeyLocator();
+  }
+  else if (signature instanceof DigestSha256Signature) {
+    var signature = data.getSignature();
+    append("DigestSha256 signature.signature: " +
+      (signature.getSignature().size() > 0 ?
+       signature.getSignature().toHex() : "<none>"));
+  }
+  if (keyLocator !== null) {
+    if (keyLocator.getType() == null)
+      append("signature.keyLocator: <none>");
+    else if (keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST)
+      append("signature.keyLocator: KeyLocatorDigest: " + keyLocator.getKeyData().toHex());
+    else if (keyLocator.getType() == KeyLocatorType.KEYNAME)
+      append("signature.keyLocator: KeyName: " + keyLocator.getKeyName().toUri());
+    else
+      append("signature.keyLocator: <unrecognized ndn_KeyLocatorType>");
+  }
+
+  return output;
+};
+
+//
+// Deprecated: For the browser, define these in the global scope.  Applications should access as member of EncodingUtils.
+//
+
+var encodeToHexInterest = function(interest) { return EncodingUtils.encodeToHexInterest(interest); }
+var decodeHexInterest = function(input) { return EncodingUtils.decodeHexInterest(input); }
+var decodeSubjectPublicKeyInfo = function(input) { return EncodingUtils.decodeSubjectPublicKeyInfo(input); }
+
+/**
+ * @deprecated Use interest.wireEncode().
+ */
+function encodeToBinaryInterest(interest) { return interest.wireEncode().buf(); }
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/algo/aes https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// (This is ported from ndn::gep::algo::Aes, and named AesAlgorithm because
+// "Aes" is very short and not all the Common Client Libraries have namespaces.)
+
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DecryptKey = require('../decrypt-key.js').DecryptKey; /** @ignore */
+var EncryptKey = require('../encrypt-key.js').EncryptKey; /** @ignore */
+var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise;
+
+/**
+ * The AesAlgorithm class provides static methods to manipulate keys, encrypt
+ * and decrypt using the AES symmetric key cipher.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var AesAlgorithm = function AesAlgorithm()
+{
+};
+
+exports.AesAlgorithm = AesAlgorithm;
+
+/**
+ * Generate a new random decrypt key for AES based on the given params.
+ * @param {AesKeyParams} params The key params with the key size (in bits).
+ * @return {DecryptKey} The new decrypt key.
+ */
+AesAlgorithm.generateKey = function(params)
+{
+  // Convert the key bit size to bytes.
+  var key = Crypto.randomBytes(params.getKeySize() / 8);
+
+  var decryptKey = new DecryptKey(new Blob(key, false));
+  return decryptKey;
+};
+
+/**
+ * Derive a new encrypt key from the given decrypt key value.
+ * @param {Blob} keyBits The key value of the decrypt key.
+ * @return {EncryptKey} The new encrypt key.
+ */
+AesAlgorithm.deriveEncryptKey = function(keyBits)
+{
+  return new EncryptKey(keyBits);
+};
+
+/**
+ * Decrypt the encryptedData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value.
+ * @param {Blob} encryptedData The data to decrypt.
+ * @param {EncryptParams} params This decrypts according to
+ * params.getAlgorithmType() and other params as needed such as
+ * params.getInitialVector().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the decrypted Blob.
+ */
+AesAlgorithm.decryptPromise = function(keyBits, encryptedData, params, useSync)
+{
+  if (UseSubtleCrypto() && !useSync &&
+      // Crypto.subtle doesn't implement ECB.
+      params.getAlgorithmType() != EncryptAlgorithmType.AesEcb) {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      return crypto.subtle.importKey
+        ("raw", keyBits.buf(), { name: "AES-CBC" }, false,
+         ["encrypt", "decrypt"])
+      .then(function(key) {
+        return crypto.subtle.decrypt
+          ({ name: "AES-CBC", iv: params.getInitialVector().buf() },
+           key, encryptedData.buf());
+      })
+      .then(function(result) {
+        return Promise.resolve(new Blob(new Uint8Array(result), false));
+      });
+    }
+    else
+      return Promise.reject(new Error("unsupported encryption mode"));
+  }
+  else {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.AesEcb) {
+      try {
+        // ECB ignores the initial vector.
+        var cipher = Crypto.createDecipheriv("aes-128-ecb", keyBits.buf(), "");
+        return SyncPromise.resolve(new Blob
+          (Buffer.concat([cipher.update(encryptedData.buf()), cipher.final()]),
+           false));
+      } catch (err) {
+        return SyncPromise.reject(err);
+      }
+    }
+    else if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      try {
+        var cipher = Crypto.createDecipheriv
+          ("aes-128-cbc", keyBits.buf(), params.getInitialVector().buf());
+        return SyncPromise.resolve(new Blob
+          (Buffer.concat([cipher.update(encryptedData.buf()), cipher.final()]),
+           false));
+      } catch (err) {
+        return SyncPromise.reject(err);
+      }
+    }
+    else
+      return SyncPromise.reject(new Error("unsupported encryption mode"));
+  }
+};
+
+/**
+ * Decrypt the encryptedData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value.
+ * @param {Blob} encryptedData The data to decrypt.
+ * @param {EncryptParams} params This decrypts according to
+ * params.getAlgorithmType() and other params as needed such as
+ * params.getInitialVector().
+ * @return {Blob} The decrypted data.
+ * @throws Error If decryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+AesAlgorithm.decrypt = function(keyBits, encryptedData, params)
+{
+  return SyncPromise.getValue(this.decryptPromise
+    (keyBits, encryptedData, params, true));
+};
+
+/**
+ * Encrypt the plainData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value.
+ * @param {Blob} plainData The data to encrypt.
+ * @param {EncryptParams} params This encrypts according to
+ * params.getAlgorithmType() and other params as needed such as
+ * params.getInitialVector().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the encrypted Blob.
+ */
+AesAlgorithm.encryptPromise = function(keyBits, plainData, params, useSync)
+{
+  if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+    if (params.getInitialVector().size() != AesAlgorithm.BLOCK_SIZE)
+      return SyncPromise.reject(new Error("incorrect initial vector size"));
+  }
+
+  if (UseSubtleCrypto() && !useSync &&
+      // Crypto.subtle doesn't implement ECB.
+      params.getAlgorithmType() != EncryptAlgorithmType.AesEcb) {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      return crypto.subtle.importKey
+        ("raw", keyBits.buf(), { name: "AES-CBC" }, false,
+         ["encrypt", "decrypt"])
+      .then(function(key) {
+        return crypto.subtle.encrypt
+          ({ name: "AES-CBC", iv: params.getInitialVector().buf() },
+           key, plainData.buf());
+      })
+      .then(function(result) {
+        return Promise.resolve(new Blob(new Uint8Array(result), false));
+      });
+    }
+    else
+      return Promise.reject(new Error("unsupported encryption mode"));
+  }
+  else {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.AesEcb) {
+      // ECB ignores the initial vector.
+      var cipher = Crypto.createCipheriv("aes-128-ecb", keyBits.buf(), "");
+      return SyncPromise.resolve(new Blob
+        (Buffer.concat([cipher.update(plainData.buf()), cipher.final()]),
+         false));
+    }
+    else if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      var cipher = Crypto.createCipheriv
+        ("aes-128-cbc", keyBits.buf(), params.getInitialVector().buf());
+      return SyncPromise.resolve(new Blob
+        (Buffer.concat([cipher.update(plainData.buf()), cipher.final()]),
+         false));
+    }
+    else
+      return SyncPromise.reject(new Error("unsupported encryption mode"));
+  }
+};
+
+/**
+ * Encrypt the plainData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value.
+ * @param {Blob} plainData The data to encrypt.
+ * @param {EncryptParams} params This encrypts according to
+ * params.getAlgorithmType() and other params as needed such as
+ * params.getInitialVector().
+ * @return {Blob} The encrypted data.
+ * @throws Error If encryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+AesAlgorithm.encrypt = function(keyBits, plainData, params)
+{
+  return SyncPromise.getValue(this.encryptPromise
+    (keyBits, plainData, params, true));
+};
+
+AesAlgorithm.BLOCK_SIZE = 16;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/encrypt-params https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob;
+
+var EncryptAlgorithmType = function EncryptAlgorithmType()
+{
+}
+
+exports.EncryptAlgorithmType = EncryptAlgorithmType;
+
+// These correspond to the TLV codes.
+EncryptAlgorithmType.AesEcb = 0;
+EncryptAlgorithmType.AesCbc = 1;
+EncryptAlgorithmType.RsaPkcs = 2;
+EncryptAlgorithmType.RsaOaep = 3;
+
+/**
+ * An EncryptParams holds an algorithm type and other parameters used to
+ * encrypt and decrypt. Create an EncryptParams with the given parameters.
+ * @param {number} algorithmType The algorithm type from EncryptAlgorithmType,
+ * or null if not specified.
+ * @param {number} initialVectorLength (optional) The initial vector length, or
+ * 0 if the initial vector is not specified. If ommitted, the initial vector is
+ * not specified.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var EncryptParams = function EncryptParams(algorithmType, initialVectorLength)
+{
+  this.algorithmType_ = algorithmType;
+
+  if (initialVectorLength != null && initialVectorLength > 0) {
+    var initialVector = Crypto.randomBytes(initialVectorLength);
+    this.initialVector_ = new Blob(initialVector, false);
+  }
+  else
+    this.initialVector_ = new Blob();
+};
+
+exports.EncryptParams = EncryptParams;
+
+/**
+ * Get the algorithmType.
+ * @return {number} The algorithm type from EncryptAlgorithmType, or null if not
+ * specified.
+ */
+EncryptParams.prototype.getAlgorithmType = function()
+{
+  return this.algorithmType_;
+};
+
+/**
+ * Get the initial vector.
+ * @return {Blob} The initial vector. If not specified, isNull() is true.
+ */
+EncryptParams.prototype.getInitialVector = function()
+{
+  return this.initialVector_;
+};
+
+/**
+ * Set the algorithm type.
+ * @param {number} algorithmType The algorithm type from EncryptAlgorithmType.
+ * If not specified, set to null.
+ * @return {EncryptParams} This EncryptParams so that you can chain calls to
+ * update values.
+ */
+EncryptParams.prototype.setAlgorithmType = function(algorithmType)
+{
+  this.algorithmType_ = algorithmType;
+  return this;
+};
+
+/**
+ * Set the initial vector.
+ * @param {Blob} initialVector The initial vector. If not specified, set to the
+ * default Blob() where isNull() is true.
+ * @return {EncryptParams} This EncryptParams so that you can chain calls to
+ * update values.
+ */
+EncryptParams.prototype.setInitialVector = function(initialVector)
+{
+  this.initialVector_ =
+      typeof initialVector === 'object' && initialVector instanceof Blob ?
+    initialVector : new Blob(initialVector);
+  return this;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/encryptor https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
+var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
+var TlvWireFormat = require('../../encoding/tlv-wire-format.js').TlvWireFormat; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var AesAlgorithm = require('./aes-algorithm.js').AesAlgorithm; /** @ignore */
+var RsaAlgorithm = require('./rsa-algorithm.js').RsaAlgorithm; /** @ignore */
+var EncryptParams = require('./encrypt-params.js').EncryptParams; /** @ignore */
+var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var EncryptedContent = require('../encrypted-content.js').EncryptedContent; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise;
+
+/**
+ * Encryptor has static constants and utility methods for encryption, such as
+ * encryptData.
+ * @constructor
+ */
+var Encryptor = function Encryptor(value)
+{
+};
+
+exports.Encryptor = Encryptor;
+
+Encryptor.NAME_COMPONENT_FOR = new Name.Component("FOR");
+Encryptor.NAME_COMPONENT_READ = new Name.Component("READ");
+Encryptor.NAME_COMPONENT_SAMPLE = new Name.Component("SAMPLE");
+Encryptor.NAME_COMPONENT_ACCESS = new Name.Component("ACCESS");
+Encryptor.NAME_COMPONENT_E_KEY = new Name.Component("E-KEY");
+Encryptor.NAME_COMPONENT_D_KEY = new Name.Component("D-KEY");
+Encryptor.NAME_COMPONENT_C_KEY = new Name.Component("C-KEY");
+
+/**
+ * Prepare an encrypted data packet by encrypting the payload using the key
+ * according to the params. In addition, this prepares the encoded
+ * EncryptedContent with the encryption result using keyName and params. The
+ * encoding is set as the content of the data packet. If params defines an
+ * asymmetric encryption algorithm and the payload is larger than the maximum
+ * plaintext size, this encrypts the payload with a symmetric key that is
+ * asymmetrically encrypted and provided as a nonce in the content of the data
+ * packet. The packet's /<dataName>/ is updated to be <dataName>/FOR/<keyName>.
+ * @param {Data} data The data packet which is updated.
+ * @param {Blob} payload The payload to encrypt.
+ * @param {Name} keyName The key name for the EncryptedContent.
+ * @param {Blob} key The encryption key value.
+ * @param {EncryptParams} params The parameters for encryption.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the data packet
+ * is updated.
+ */
+Encryptor.encryptDataPromise = function
+  (data, payload, keyName, key, params, useSync)
+{
+  data.getName().append(Encryptor.NAME_COMPONENT_FOR).append(keyName);
+
+  var algorithmType = params.getAlgorithmType();
+
+  if (algorithmType == EncryptAlgorithmType.AesCbc ||
+      algorithmType == EncryptAlgorithmType.AesEcb) {
+    return Encryptor.encryptSymmetricPromise_
+      (payload, key, keyName, params, useSync)
+    .then(function(content) {
+      data.setContent(content.wireEncode(TlvWireFormat.get()));
+      return SyncPromise.resolve();
+    });
+  }
+  else if (algorithmType == EncryptAlgorithmType.RsaPkcs ||
+           algorithmType == EncryptAlgorithmType.RsaOaep) {
+    // Node.js doesn't have a direct way to get the maximum plain text size, so
+    // try to encrypt the payload first and catch the error if it is too big.
+    return Encryptor.encryptAsymmetricPromise_
+      (payload, key, keyName, params, useSync)
+    .then(function(content) {
+      data.setContent(content.wireEncode(TlvWireFormat.get()));
+      return SyncPromise.resolve();
+    }, function(err) {
+      if (err.message.indexOf("data too large for key size") < 0)
+        // Not the expected error.
+        throw err;
+
+      // The payload is larger than the maximum plaintext size.
+      // 128-bit nonce.
+      var nonceKeyBuffer = Crypto.randomBytes(16);
+      var nonceKey = new Blob(nonceKeyBuffer, false);
+
+      var nonceKeyName = new Name(keyName);
+      nonceKeyName.append("nonce");
+
+      var symmetricParams = new EncryptParams
+        (EncryptAlgorithmType.AesCbc, AesAlgorithm.BLOCK_SIZE);
+
+      var nonceContent;
+      return Encryptor.encryptSymmetricPromise_
+        (payload, nonceKey, nonceKeyName, symmetricParams, useSync)
+      .then(function(localNonceContent) {
+        nonceContent = localNonceContent;
+        return Encryptor.encryptAsymmetricPromise_
+          (nonceKey, key, keyName, params, useSync);
+      })
+      .then(function(payloadContent) {
+        var nonceContentEncoding = nonceContent.wireEncode();
+        var payloadContentEncoding = payloadContent.wireEncode();
+        var content = new Buffer
+          (nonceContentEncoding.size() + payloadContentEncoding.size());
+        payloadContentEncoding.buf().copy(content, 0);
+        nonceContentEncoding.buf().copy(content, payloadContentEncoding.size());
+
+        data.setContent(new Blob(content, false));
+        return SyncPromise.resolve();
+      });
+    });
+  }
+  else
+    return SyncPromise.reject(new Error("Unsupported encryption method"));
+};
+
+/**
+ * Prepare an encrypted data packet by encrypting the payload using the key
+ * according to the params. In addition, this prepares the encoded
+ * EncryptedContent with the encryption result using keyName and params. The
+ * encoding is set as the content of the data packet. If params defines an
+ * asymmetric encryption algorithm and the payload is larger than the maximum
+ * plaintext size, this encrypts the payload with a symmetric key that is
+ * asymmetrically encrypted and provided as a nonce in the content of the data
+ * packet.
+ * @param {Data} data The data packet which is updated.
+ * @param {Blob} payload The payload to encrypt.
+ * @param {Name} keyName The key name for the EncryptedContent.
+ * @param {Blob} key The encryption key value.
+ * @param {EncryptParams} params The parameters for encryption.
+ * @throws Error If encryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+Encryptor.encryptData = function(data, payload, keyName, key, params)
+{
+  return SyncPromise.getValue(Encryptor.encryptDataPromise
+    (data, payload, keyName, key, params, true));
+};
+
+/**
+ * Encrypt the payload using the symmetric key according to params, and return
+ * an EncryptedContent.
+ * @param {Blob} payload The data to encrypt.
+ * @param {Blob} key The key value.
+ * @param {Name} keyName The key name for the EncryptedContent key locator.
+ * @param {EncryptParams} params The parameters for encryption.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns a new EncryptedContent.
+ */
+Encryptor.encryptSymmetricPromise_ = function
+  (payload, key, keyName, params, useSync)
+{
+  var algorithmType = params.getAlgorithmType();
+  var initialVector = params.getInitialVector();
+  var keyLocator = new KeyLocator();
+  keyLocator.setType(KeyLocatorType.KEYNAME);
+  keyLocator.setKeyName(keyName);
+
+  if (algorithmType == EncryptAlgorithmType.AesCbc ||
+      algorithmType == EncryptAlgorithmType.AesEcb) {
+    if (algorithmType == EncryptAlgorithmType.AesCbc) {
+      if (initialVector.size() != AesAlgorithm.BLOCK_SIZE)
+        return SyncPromise.reject(new Error("incorrect initial vector size"));
+    }
+
+    return AesAlgorithm.encryptPromise(key, payload, params, useSync)
+    .then(function(encryptedPayload) {
+      var result = new EncryptedContent();
+      result.setAlgorithmType(algorithmType);
+      result.setKeyLocator(keyLocator);
+      result.setPayload(encryptedPayload);
+      result.setInitialVector(initialVector);
+      return SyncPromise.resolve(result);
+    });
+  }
+  else
+    return SyncPromise.reject(new Error("Unsupported encryption method"));
+};
+
+/**
+ * Encrypt the payload using the asymmetric key according to params, and
+ * return an EncryptedContent.
+ * @param {Blob} payload The data to encrypt. The size should be within range of
+ * the key.
+ * @param {Blob} key The key value.
+ * @param {Name} keyName The key name for the EncryptedContent key locator.
+ * @param {EncryptParams} params The parameters for encryption.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns a new EncryptedContent.
+ */
+Encryptor.encryptAsymmetricPromise_ = function
+  (payload, key, keyName, params, useSync)
+{
+  var algorithmType = params.getAlgorithmType();
+  var keyLocator = new KeyLocator();
+  keyLocator.setType(KeyLocatorType.KEYNAME);
+  keyLocator.setKeyName(keyName);
+
+  if (algorithmType == EncryptAlgorithmType.RsaPkcs ||
+      algorithmType == EncryptAlgorithmType.RsaOaep) {
+    return RsaAlgorithm.encryptPromise(key, payload, params, useSync)
+    .then(function(encryptedPayload) {
+      var result = new EncryptedContent();
+      result.setAlgorithmType(algorithmType);
+      result.setKeyLocator(keyLocator);
+      result.setPayload(encryptedPayload);
+      return SyncPromise.resolve(result);
+    });
+  }
+  else
+    return SyncPromise.reject(new Error("Unsupported encryption method"));
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/algo/rsa https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// (This is ported from ndn::gep::algo::Rsa, and named RsaAlgorithm because
+// "Rsa" is very short and not all the Common Client Libraries have namespaces.)
+
+/** @ignore */
+var constants = require('constants'); /** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DecryptKey = require('../decrypt-key.js').DecryptKey; /** @ignore */
+var EncryptKey = require('../encrypt-key.js').EncryptKey; /** @ignore */
+var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var OID = require('../../encoding/oid.js').OID; /** @ignore */
+var PrivateKeyStorage = require('../../security/identity/private-key-storage.js').PrivateKeyStorage; /** @ignore */
+var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var rsaKeygen = null;
+try {
+  // This should be installed with: sudo npm install rsa-keygen
+  rsaKeygen = require('rsa-keygen');
+}
+catch (e) {}
+
+/**
+ * The RsaAlgorithm class provides static methods to manipulate keys, encrypt
+ * and decrypt using RSA.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var RsaAlgorithm = function RsaAlgorithm()
+{
+};
+
+exports.RsaAlgorithm = RsaAlgorithm;
+
+/**
+ * Generate a new random decrypt key for RSA based on the given params.
+ * @param {RsaKeyParams} params The key params with the key size (in bits).
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the new DecryptKey
+ * (containing a PKCS8-encoded private key).
+ */
+RsaAlgorithm.generateKeyPromise = function(params, useSync)
+{
+  if (UseSubtleCrypto() && !useSync) {
+    return crypto.subtle.generateKey
+      ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
+         publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+         hash: {name: "SHA-256"} },
+       true, ["sign", "verify"])
+    .then(function(key) {
+      // Export the private key to DER.
+      return crypto.subtle.exportKey("pkcs8", key.privateKey);
+    })
+    .then(function(pkcs8Der) {
+      return Promise.resolve(new DecryptKey
+        (new Blob(new Uint8Array(pkcs8Der), false)));
+    });
+  }
+  else {
+    if (!rsaKeygen)
+      return SyncPromise.reject(new Error
+        ("Need to install rsa-keygen: sudo npm install rsa-keygen"));
+
+    try {
+      var keyPair = rsaKeygen.generate(params.getKeySize());
+      // Get the PKCS1 private key DER from the PEM string and encode as PKCS8.
+      var privateKeyBase64 = keyPair.private_key.toString().replace
+        ("-----BEGIN RSA PRIVATE KEY-----", "").replace
+        ("-----END RSA PRIVATE KEY-----", "");
+      var pkcs1PrivateKeyDer = new Buffer(privateKeyBase64, 'base64');
+      var privateKey = PrivateKeyStorage.encodePkcs8PrivateKey
+        (pkcs1PrivateKeyDer, new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),
+         new DerNode.DerNull()).buf();
+
+      return SyncPromise.resolve(new DecryptKey(privateKey));
+    } catch (err) {
+      return SyncPromise.reject(err);
+    }
+  }
+};
+
+/**
+ * Generate a new random decrypt key for RSA based on the given params.
+ * @param {RsaKeyParams} params The key params with the key size (in bits).
+ * @return {DecryptKey} The new decrypt key (containing a PKCS8-encoded private
+ * key).
+ * @throws Error If generateKeyPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+RsaAlgorithm.generateKey = function(params)
+{
+  return SyncPromise.getValue(this.generateKeyPromise(params, true));
+};
+
+/**
+ * Derive a new encrypt key from the given decrypt key value.
+ * @param {Blob} keyBits The key value of the decrypt key (PKCS8-encoded private
+ * key).
+ * @return {EncryptKey} The new encrypt key (DER-encoded public key).
+ */
+RsaAlgorithm.deriveEncryptKey = function(keyBits)
+{
+  var rsaPrivateKeyDer = RsaAlgorithm.getRsaPrivateKeyDer(keyBits);
+
+  // Decode the PKCS #1 RSAPrivateKey.
+  var parsedNode = DerNode.parse(rsaPrivateKeyDer.buf(), 0);
+  var rsaPrivateKeyChildren = parsedNode.getChildren();
+  var modulus = rsaPrivateKeyChildren[1];
+  var publicExponent = rsaPrivateKeyChildren[2];
+
+  // Encode the PKCS #1 RSAPublicKey.
+  var rsaPublicKey = new DerNode.DerSequence();
+  rsaPublicKey.addChild(modulus);
+  rsaPublicKey.addChild(publicExponent);
+  var rsaPublicKeyDer = rsaPublicKey.encode();
+
+  // Encode the SubjectPublicKeyInfo.
+  var algorithmIdentifier = new DerNode.DerSequence();
+  algorithmIdentifier.addChild(new DerNode.DerOid(new OID
+    (PrivateKeyStorage.RSA_ENCRYPTION_OID)));
+  algorithmIdentifier.addChild(new DerNode.DerNull());
+  var publicKey = new DerNode.DerSequence();
+  publicKey.addChild(algorithmIdentifier);
+  publicKey.addChild(new DerNode.DerBitString(rsaPublicKeyDer.buf(), 0));
+
+  return new EncryptKey(publicKey.encode());
+};
+
+/**
+ * Decrypt the encryptedData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value (PKCS8-encoded private key).
+ * @param {Blob} encryptedData The data to decrypt.
+ * @param {EncryptParams} params This decrypts according to
+ * params.getAlgorithmType().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the decrypted Blob.
+ */
+RsaAlgorithm.decryptPromise = function(keyBits, encryptedData, params, useSync)
+{
+  if (UseSubtleCrypto() && !useSync &&
+      // Crypto.subtle doesn't implement PKCS1 padding.
+      params.getAlgorithmType() != EncryptAlgorithmType.RsaPkcs) {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
+      return crypto.subtle.importKey
+        ("pkcs8", keyBits.buf(), { name: "RSA-OAEP", hash: {name: "SHA-1"} },
+         false, ["decrypt"])
+      .then(function(privateKey) {
+        return crypto.subtle.decrypt
+          ({ name: "RSA-OAEP" }, privateKey, encryptedData.buf());
+      })
+      .then(function(result) {
+        return Promise.resolve(new Blob(new Uint8Array(result), false));
+      });
+    }
+    else
+      return Promise.reject(new Error("unsupported padding scheme"));
+  }
+  else {
+    // keyBits is PKCS #8 but we need the inner RSAPrivateKey.
+    var rsaPrivateKeyDer = RsaAlgorithm.getRsaPrivateKeyDer(keyBits);
+
+    // Encode the key DER as a PEM private key as needed by Crypto.
+    var keyBase64 = rsaPrivateKeyDer.buf().toString('base64');
+    var keyPem = "-----BEGIN RSA PRIVATE KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END RSA PRIVATE KEY-----";
+
+    var padding;
+    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaPkcs)
+      padding = constants.RSA_PKCS1_PADDING;
+    else if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep)
+      padding = constants.RSA_PKCS1_OAEP_PADDING;
+    else
+      return SyncPromise.reject(new Error("unsupported padding scheme"));
+
+    try {
+      // In Node.js, privateDecrypt requires version v0.12.
+      return SyncPromise.resolve(new Blob
+        (Crypto.privateDecrypt({ key: keyPem, padding: padding }, encryptedData.buf()),
+         false));
+    } catch (err) {
+      return SyncPromise.reject(err);
+    }
+  }
+};
+
+/**
+ * Decrypt the encryptedData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value (PKCS8-encoded private key).
+ * @param {Blob} encryptedData The data to decrypt.
+ * @param {EncryptParams} params This decrypts according to
+ * params.getAlgorithmType().
+ * @return {Blob} The decrypted data.
+ * @throws Error If decryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+RsaAlgorithm.decrypt = function(keyBits, encryptedData, params)
+{
+  return SyncPromise.getValue(this.decryptPromise
+    (keyBits, encryptedData, params, true));
+};
+
+/**
+ * Encrypt the plainData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value (DER-encoded public key).
+ * @param {Blob} plainData The data to encrypt.
+ * @param {EncryptParams} params This encrypts according to
+ * params.getAlgorithmType().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the encrypted Blob.
+ */
+RsaAlgorithm.encryptPromise = function(keyBits, plainData, params, useSync)
+{
+  if (UseSubtleCrypto() && !useSync &&
+      // Crypto.subtle doesn't implement PKCS1 padding.
+      params.getAlgorithmType() != EncryptAlgorithmType.RsaPkcs) {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
+      return crypto.subtle.importKey
+        ("spki", keyBits.buf(), { name: "RSA-OAEP", hash: {name: "SHA-1"} },
+         false, ["encrypt"])
+      .then(function(publicKey) {
+        return crypto.subtle.encrypt
+          ({ name: "RSA-OAEP" }, publicKey, plainData.buf());
+      })
+      .then(function(result) {
+        return Promise.resolve(new Blob(new Uint8Array(result), false));
+      });
+    }
+    else
+      return Promise.reject(new Error("unsupported padding scheme"));
+  }
+  else {
+    // Encode the key DER as a PEM public key as needed by Crypto.
+    var keyBase64 = keyBits.buf().toString('base64');
+    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END PUBLIC KEY-----";
+
+    var padding;
+    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaPkcs)
+      padding = constants.RSA_PKCS1_PADDING;
+    else if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep)
+      padding = constants.RSA_PKCS1_OAEP_PADDING;
+    else
+      return SyncPromise.reject(new Error("unsupported padding scheme"));
+
+    try {
+      // In Node.js, publicEncrypt requires version v0.12.
+      return SyncPromise.resolve(new Blob
+        (Crypto.publicEncrypt({ key: keyPem, padding: padding }, plainData.buf()),
+         false));
+    } catch (err) {
+      return SyncPromise.reject(err);
+    }
+  }
+};
+
+/**
+ * Encrypt the plainData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value (DER-encoded public key).
+ * @param {Blob} plainData The data to encrypt.
+ * @param {EncryptParams} params This encrypts according to
+ * params.getAlgorithmType().
+ * @return {Blob} The encrypted data.
+ * @throws Error If encryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+RsaAlgorithm.encrypt = function(keyBits, plainData, params)
+{
+  return SyncPromise.getValue(this.encryptPromise
+    (keyBits, plainData, params, true));
+};
+
+/**
+ * Decode the PKCS #8 private key, check that the algorithm is RSA, and return
+ * the inner RSAPrivateKey DER.
+ * @param {Blob} The DER-encoded PKCS #8 private key.
+ * @param {Blob} The DER-encoded RSAPrivateKey.
+ */
+RsaAlgorithm.getRsaPrivateKeyDer = function(pkcs8PrivateKeyDer)
+{
+  var parsedNode = DerNode.parse(pkcs8PrivateKeyDer.buf(), 0);
+  var pkcs8Children = parsedNode.getChildren();
+  var algorithmIdChildren = DerNode.getSequence(pkcs8Children, 1).getChildren();
+  var oidString = algorithmIdChildren[0].toVal();
+
+  if (oidString != PrivateKeyStorage.RSA_ENCRYPTION_OID)
+    throw new Error("The PKCS #8 private key is not RSA_ENCRYPTION");
+
+  return pkcs8Children[2].getPayload();
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/consumer-db https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise;
+
+/**
+ * ConsumerDb is a base class the storage of decryption keys for the consumer. A
+ * subclass must implement the methods. For example, see Sqlite3ConsumerDb (for
+ * Nodejs) or IndexedDbConsumerDb (for the browser).
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var ConsumerDb = function ConsumerDb()
+{
+};
+
+exports.ConsumerDb = ConsumerDb;
+
+/**
+ * Create a new ConsumerDb.Error to report an error using ConsumerDb
+ * methods, wrapping the given error object.
+ * Call with: throw new ConsumerDb.Error(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+ConsumerDb.Error = function ConsumerDbError(error)
+{
+  if (error) {
+    error.__proto__ = ConsumerDb.Error.prototype;
+    return error;
+  }
+}
+
+ConsumerDb.Error.prototype = new Error();
+ConsumerDb.Error.prototype.name = "ConsumerDbError";
+
+/**
+ * Get the key with keyName from the database.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
+ * key (or an isNull Blob if cannot find the key with keyName), or that is
+ * rejected with ConsumerDb.Error for a database error.
+ */
+ConsumerDb.prototype.getKeyPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ConsumerDb.getKeyPromise is not implemented"));
+};
+
+/**
+ * Add the key with keyName and keyBlob to the database.
+ * @param {Name} keyName The key name.
+ * @param {Blob} keyBlob The encoded key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
+ * or that is rejected with ConsumerDb.Error if a key with the same keyName
+ * already exists, or other database error.
+ */
+ConsumerDb.prototype.addKeyPromise = function(keyName, keyBlob, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ConsumerDb.addKeyPromise is not implemented"));
+};
+
+/**
+ * Delete the key with keyName from the database. If there is no key with
+ * keyName, do nothing.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is deleted
+ * (or there is no such key), or that is rejected with ConsumerDb.Error for a
+ * database error.
+ */
+ConsumerDb.prototype.deleteKeyPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ConsumerDb.addKeyPromise is not implemented"));
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/consumer https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
+var Link = require('../link.js').Link; /** @ignore */
+var EncryptedContent = require('./encrypted-content.js').EncryptedContent; /** @ignore */
+var EncryptError = require('./encrypt-error.js').EncryptError; /** @ignore */
+var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
+var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var RsaAlgorithm = require('./algo/rsa-algorithm.js').RsaAlgorithm; /** @ignore */
+var AesAlgorithm = require('./algo/aes-algorithm.js').AesAlgorithm; /** @ignore */
+var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon;
+
+/**
+ * A Consumer manages fetched group keys used to decrypt a data packet in the
+ * group-based encryption protocol.
+ * Create a Consumer to use the given ConsumerDb, Face and other values.
+ * @param {Face} face The face used for data packet and key fetching.
+ * @param {KeyChain} keyChain The keyChain used to verify data packets.
+ * @param {Name} groupName The reading group name that the consumer belongs to.
+ * This makes a copy of the Name.
+ * @param {Name} consumerName The identity of the consumer. This makes a copy of
+ * the Name.
+ * @param {ConsumerDb} database The ConsumerDb database for storing decryption
+ * keys.
+ * @param {Link} cKeyLink (optional) The Link object to use in Interests for
+ * C-KEY retrieval. This makes a copy of the Link object. If the Link object's
+ * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
+ * object.
+ * @param {Link} dKeyLink (optional) The Link object to use in Interests for
+ * D-KEY retrieval. This makes a copy of the Link object. If the Link object's
+ * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
+ * object.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var Consumer = function Consumer
+  (face, keyChain, groupName, consumerName, database, cKeyLink, dKeyLink)
+{
+  this.database_ = database;
+  this.keyChain_ = keyChain;
+  this.face_ = face;
+  this.groupName_ = new Name(groupName);
+  this.consumerName_ = new Name(consumerName);
+  this.cKeyLink_ =
+    (cKeyLink == undefined ? Consumer.NO_LINK : new Link(cKeyLink));
+  this.dKeyLink_ =
+    (dKeyLink == undefined ? Consumer.NO_LINK : new Link(dKeyLink));
+
+  // The map key is the C-KEY name URI string. The value is the encoded key Blob.
+  // (Use a string because we can't use the Name object as the key in JavaScript.)
+  this.cKeyMap_ = {};
+  // The map key is the D-KEY name URI string. The value is the encoded key Blob.
+  this.dKeyMap_ = {};
+};
+
+exports.Consumer = Consumer;
+
+/**
+ * Express an Interest to fetch the content packet with contentName, and
+ * decrypt it, fetching keys as needed.
+ * @param {Name} contentName The name of the content packet.
+ * @param {function} onConsumeComplete When the content packet is fetched and
+ * decrypted, this calls onConsumeComplete(contentData, result) where
+ * contentData is the fetched Data packet and result is the decrypted plain
+ * text Blob.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param link {Link} (optional) The Link object to use in Interests for data
+ * retrieval. This makes a copy of the Link object. If the Link object's
+ * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
+ * object.
+ */
+Consumer.prototype.consume = function
+  (contentName, onConsumeComplete, onError, link)
+{
+  if (link == undefined)
+    link = Consumer.NO_LINK;
+
+  var interest = new Interest(contentName);
+  var thisConsumer = this;
+  // Copy the Link object since the passed link may become invalid.
+  this.sendInterest_
+    (interest, 1, new Link(link),
+     function(validData) {
+       // Decrypt the content.
+       thisConsumer.decryptContent_(validData, function(plainText) {
+         try {
+           onConsumeComplete(validData, plainText);
+         } catch (ex) {
+           console.log("Error in onConsumeComplete: " + NdnCommon.getErrorWithStackTrace(ex));
+         }
+       }, onError);
+     },
+     onError);
+};
+
+/**
+ * Set the group name.
+ * @param {Name} groupName The reading group name that the consumer belongs to.
+ * This makes a copy of the Name.
+ */
+Consumer.prototype.setGroup = function(groupName)
+{
+  this.groupName_ = new Name(groupName);
+};
+
+/**
+ * Add a new decryption key with keyName and keyBlob to the database.
+ * @param {Name} keyName The key name.
+ * @param {Blob} keyBlob The encoded key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
+ * or that is rejected with Error if the consumer name is not a prefix of the
+ * key name, or ConsumerDb.Error if a key with the same keyName already exists,
+ * or other database error.
+ */
+Consumer.prototype.addDecryptionKeyPromise = function(keyName, keyBlob, useSync)
+{
+  if (!(this.consumerName_.match(keyName)))
+    return SyncPromise.reject(new Error
+      ("addDecryptionKey: The consumer name must be a prefix of the key name"));
+
+  return this.database_.addKeyPromise(keyName, keyBlob, useSync);
+};
+
+/**
+ * Add a new decryption key with keyName and keyBlob to the database.
+ * @param {Name} keyName The key name.
+ * @param {Blob} keyBlob The encoded key.
+ * @param {function} onComplete (optional) This calls onComplete() when the key
+ * is added. (Some database libraries only use a callback, so onComplete is
+ * required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * where exception is Error if the consumer name is not a prefix of the key
+ * name, or ConsumerDb.Error if a key with the same keyName already exists,
+ * or other database error. If onComplete is defined but onError is undefined,
+ * then this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+Consumer.prototype.addDecryptionKey = function
+  (keyName, keyBlob, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.addDecryptionKeyPromise(keyName, keyBlob, !onComplete));
+};
+
+/**
+ * Consume.Error is used internally from promised-based methods to reject with
+ * an error object that has the errorCode and message returned through the
+ * onError callback.
+ * @param {number} errorCode An error code from EncryptError.ErrorCode.
+ * @param {string} message The error message.
+ */
+Consumer.Error = function ConsumerError(errorCode, message)
+{
+  this.errorCode = errorCode;
+  this.message = message;
+};
+
+/**
+ * If exception is a ConsumerError, then call onError with the errorCode and
+ * message, otherwise call onError with ErrorCode.General.
+ */
+Consumer.Error.callOnError = function(onError, exception, messagePrefix)
+{
+  if (!messagePrefix)
+    messagePrefix = "";
+
+  if (exception instanceof Consumer.Error) {
+    try {
+      onError(exception.errorCode, exception.message);
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+  else {
+    try {
+      onError(EncryptError.ErrorCode.General, messagePrefix + exception);
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+}
+
+/**
+ * Decrypt encryptedContent using keyBits.
+ * @param {Blob|EncryptedContent} encryptedContent The EncryptedContent to
+ * decrypt, or a Blob which is first decoded as an EncryptedContent.
+ * @param {Blob} keyBits The key value.
+ * @return {Promise|SyncPromise} A promise that returns the decrypted Blob, or
+ * that is rejected with Consumer.Error or other error.
+ */
+Consumer.decryptPromise_ = function(encryptedContent, keyBits)
+{
+  return SyncPromise.resolve()
+  .then(function() {
+    if (typeof encryptedContent == 'object' && encryptedContent instanceof Blob) {
+      // Decode as EncryptedContent.
+      var encryptedBlob = encryptedContent;
+      encryptedContent = new EncryptedContent();
+      encryptedContent.wireDecode(encryptedBlob);
+    }
+
+    var payload = encryptedContent.getPayload();
+
+    if (encryptedContent.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      // Prepare the parameters.
+      var decryptParams = new EncryptParams(EncryptAlgorithmType.AesCbc);
+      decryptParams.setInitialVector(encryptedContent.getInitialVector());
+
+      // Decrypt the content.
+      return AesAlgorithm.decryptPromise(keyBits, payload, decryptParams);
+    }
+    else if (encryptedContent.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
+      // Prepare the parameters.
+      var decryptParams = new EncryptParams(EncryptAlgorithmType.RsaOaep);
+
+      // Decrypt the content.
+      return RsaAlgorithm.decryptPromise(keyBits, payload, decryptParams);
+    }
+    else
+      return SyncPromise.reject(new Consumer.Error
+        (EncryptError.ErrorCode.UnsupportedEncryptionScheme,
+          "" + encryptedContent.getAlgorithmType()));
+  });
+};
+
+/**
+ * Decrypt encryptedContent using keyBits.
+ * @param {Blob|EncryptedContent} encryptedContent The EncryptedContent to
+ * decrypt, or a Blob which is first decoded as an EncryptedContent.
+ * @param {Blob} keyBits The key value.
+ * @param {function} onPlainText When the data packet is decrypted, this calls
+ * onPlainText(decryptedBlob) with the decrypted Blob.
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ */
+Consumer.decrypt_ = function(encryptedContent, keyBits, onPlainText, onError)
+{
+  Consumer.decryptPromise_(encryptedContent, keyBits)
+  .then(function(decryptedBlob) {
+    onPlainText(decryptedBlob);
+  }, function(ex) {
+    Consumer.Error.callOnError(onError, ex);
+  });
+};
+
+/**
+ * Decrypt the data packet.
+ * @param {Data} data The data packet. This does not verify the packet.
+ * @param {function} onPlainText When the data packet is decrypted, this calls
+ * onPlainText(decryptedBlob) with the decrypted Blob.
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ */
+Consumer.prototype.decryptContent_ = function(data, onPlainText, onError)
+{
+  // Get the encrypted content.
+  var dataEncryptedContent = new EncryptedContent();
+  try {
+    dataEncryptedContent.wireDecode(data.getContent());
+  } catch (ex) {
+    Consumer.Error.callOnError(onError, ex, "Error decoding EncryptedContent: ");
+    return;
+  }
+  var cKeyName = dataEncryptedContent.getKeyLocator().getKeyName();
+
+  // Check if the content key is already in the store.
+  var cKey = this.cKeyMap_[cKeyName.toUri()];
+  if (cKey)
+    this.decrypt_(dataEncryptedContent, cKey, onPlainText, onError);
+  else {
+    // Retrieve the C-KEY Data from the network.
+    var interestName = new Name(cKeyName);
+    interestName.append(Encryptor.NAME_COMPONENT_FOR).append(this.groupName_);
+    var interest = new Interest(interestName);
+    var thisConsumer = this;
+    this.sendInterest_
+      (interest, 1, this.cKeyLink_,
+       function(validCKeyData) {
+         thisConsumer.decryptCKey_(validCKeyData, function(cKeyBits) {
+           thisConsumer.cKeyMap_[cKeyName.toUri()] = cKeyBits;
+           Consumer.decrypt_
+             (dataEncryptedContent, cKeyBits, onPlainText, onError);
+         }, onError);
+       },
+       onError);
+  }
+};
+
+/**
+ * Decrypt cKeyData.
+ * @param {Data} cKeyData The C-KEY data packet.
+ * @param {function} onPlainText When the data packet is decrypted, this calls
+ * onPlainText(decryptedBlob) with the decrypted Blob.
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ */
+Consumer.prototype.decryptCKey_ = function(cKeyData, onPlainText, onError)
+{
+  // Get the encrypted content.
+  var cKeyContent = cKeyData.getContent();
+  var cKeyEncryptedContent = new EncryptedContent();
+  try {
+    cKeyEncryptedContent.wireDecode(cKeyContent);
+  } catch (ex) {
+    Consumer.Error.callOnError(onError, ex, "Error decoding EncryptedContent: ");
+    return;
+  }
+  var eKeyName = cKeyEncryptedContent.getKeyLocator().getKeyName();
+  var dKeyName = eKeyName.getPrefix(-3);
+  dKeyName.append(Encryptor.NAME_COMPONENT_D_KEY).append(eKeyName.getSubName(-2));
+
+  // Check if the decryption key is already in the store.
+  var dKey = this.dKeyMap_[dKeyName.toUri()];
+  if (dKey)
+    this.decrypt_(cKeyEncryptedContent, dKey, onPlainText, onError);
+  else {
+    // Get the D-Key Data.
+    var interestName = new Name(dKeyName);
+    interestName.append(Encryptor.NAME_COMPONENT_FOR).append(this.consumerName_);
+    var interest = new Interest(interestName);
+    var thisConsumer = this;
+    this.sendInterest_
+      (interest, 1, this.dKeyLink_,
+       function(validDKeyData) {
+         thisConsumer.decryptDKeyPromise_(validDKeyData)
+         .then(function(dKeyBits) {
+           thisConsumer.dKeyMap_[dKeyName.toUri()] = dKeyBits;
+           Consumer.decrypt_
+             (cKeyEncryptedContent, dKeyBits, onPlainText, onError);
+         }, function(ex) {
+           Consumer.Error.callOnError(onError, ex, "decryptDKey error: ");
+         });
+       },
+       onError);
+  }
+};
+
+/**
+ * Decrypt dKeyData.
+ * @param {Data} dKeyData The D-KEY data packet.
+ * @return {Promise|SyncPromise} A promise that returns the decrypted Blob, or
+ * that is rejected with Consumer.Error or other error.
+ */
+Consumer.prototype.decryptDKeyPromise_ = function(dKeyData)
+{
+  var dataContent;
+  var encryptedNonce;
+  var encryptedPayloadBlob;
+  var thisConsumer = this;
+
+  return SyncPromise.resolve()
+  .then(function() {
+    // Get the encrypted content.
+    dataContent = dKeyData.getContent();
+
+    // Process the nonce.
+    // dataContent is a sequence of the two EncryptedContent.
+    encryptedNonce = new EncryptedContent();
+    encryptedNonce.wireDecode(dataContent);
+    var consumerKeyName = encryptedNonce.getKeyLocator().getKeyName();
+
+    // Get consumer decryption key.
+    return thisConsumer.getDecryptionKeyPromise_(consumerKeyName);
+  })
+  .then(function(consumerKeyBlob) {
+    if (consumerKeyBlob.size() == 0)
+      return SyncPromise.reject(new Consumer.Error
+        (EncryptError.ErrorCode.NoDecryptKey,
+         "The desired consumer decryption key in not in the database"));
+
+    // Process the D-KEY.
+    // Use the size of encryptedNonce to find the start of encryptedPayload.
+    var encryptedPayloadBuffer = dataContent.buf().slice
+      (encryptedNonce.wireEncode().size());
+    encryptedPayloadBlob = new Blob(encryptedPayloadBuffer, false);
+    if (encryptedPayloadBlob.size() == 0)
+      return SyncPromise.reject(new Consumer.Error
+        (EncryptError.ErrorCode.InvalidEncryptedFormat,
+         "The data packet does not satisfy the D-KEY packet format"));
+
+    // Decrypt the D-KEY.
+    return Consumer.decryptPromise_(encryptedNonce, consumerKeyBlob);
+  })
+  .then(function(nonceKeyBits) {
+    return Consumer.decryptPromise_(encryptedPayloadBlob, nonceKeyBits);
+  });
+};
+
+/**
+ * Express the interest, call verifyData for the fetched Data packet and call
+ * onVerified if verify succeeds. If verify fails, call
+ * onError(EncryptError.ErrorCode.Validation, "verifyData failed"). If the
+ * interest times out, re-express nRetrials times. If the interest times out
+ * nRetrials times, or for a network Nack, call
+ * onError(EncryptError.ErrorCode.DataRetrievalFailure, interest.getName().toUri()).
+ * @param {Interest} interest The Interest to express.
+ * @param {number} nRetrials The number of retrials left after a timeout.
+ * @param {Link} link The Link object to use in the Interest. This does not make
+ * a copy of the Link object. If the Link object's getDelegations().size() is
+ * zero, don't use it.
+ * @param {function} onVerified When the fetched Data packet validation
+ * succeeds, this calls onVerified(data).
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ */
+Consumer.prototype.sendInterest_ = function
+  (interest, nRetrials, link, onVerified, onError)
+{
+  // Prepare the callback functions.
+  var thisConsumer = this;
+  var onData = function(contentInterest, contentData) {
+    try {
+      thisConsumer.keyChain_.verifyData
+        (contentData, onVerified,
+         function(d, reason) {
+           try {
+             onError
+               (EncryptError.ErrorCode.Validation, "verifyData failed. Reason: " +
+                reason);
+           } catch (ex) {
+             console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+           }
+         });
+    } catch (ex) {
+      Consumer.Error.callOnError(onError, ex, "verifyData error: ");
+    }
+  };
+
+  function onNetworkNack(interest, networkNack) {
+    // We have run out of options. Report a retrieval failure.
+    try {
+      onError(EncryptError.ErrorCode.DataRetrievalFailure,
+              interest.getName().toUri());
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+
+  var onTimeout = function(interest) {
+    if (nRetrials > 0)
+      thisConsumer.sendInterest_(interest, nRetrials - 1, link, onVerified, onError);
+    else
+      onNetworkNack(interest, new NetworkNack());
+  };
+
+  var request;
+  if (link.getDelegations().size() === 0)
+    // We can use the supplied interest without copying.
+    request = interest;
+  else {
+    // Copy the supplied interest and add the Link.
+    request = new Interest(interest);
+    // This will use a cached encoding if available.
+    request.setLinkWireEncoding(link.wireEncode());
+  }
+
+  try {
+    this.face_.expressInterest(request, onData, onTimeout, onNetworkNack);
+  } catch (ex) {
+    Consumer.Error.callOnError(onError, ex, "expressInterest error: ");
+  }
+};
+
+/**
+ * Get the encoded blob of the decryption key with decryptionKeyName from the
+ * database.
+ * @param {Name} decryptionKeyName The key name.
+ * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
+ * key (or an isNull Blob if cannot find the key with decryptionKeyName), or
+ * that is rejected with ConsumerDb.Error for a database error.
+ */
+Consumer.prototype.getDecryptionKeyPromise_ = function(decryptionKeyName)
+{
+  return this.database_.getKeyPromise(decryptionKeyName);
+};
+
+Consumer.NO_LINK = new Link();
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/decrypt-key https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * A DecryptKey supplies the key for decrypt.
+ * Create a DecryptKey with the given key value.
+ * @param {Blob|DecryptKey} value If value is another DecryptKey then copy it.
+ * Otherwise, value is the key value.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var DecryptKey = function DecryptKey(value)
+{
+  if (typeof value === 'object' && value instanceof DecryptKey) {
+    // Make a deep copy.
+    this.keyBits_ = value.keyBits_;
+  }
+  else {
+    var keyBits = value;
+    this.keyBits_ = typeof keyBits === 'object' && keyBits instanceof Blob ?
+      keyBits : new Blob(keyBits);
+  }
+};
+
+exports.DecryptKey = DecryptKey;
+
+/**
+ * Get the key value.
+ * @return {Blob} The key value.
+ */
+DecryptKey.prototype.getKeyBits = function() { return this.keyBits_; };
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/error-code https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * EncryptError holds the ErrorCode enum for errors from the encrypt library.
+ */
+var EncryptError = function EncryptError()
+{
+};
+
+exports.EncryptError = EncryptError;
+
+EncryptError.ErrorCode = {
+  Timeout:                     1,
+  Validation:                  2,
+  UnsupportedEncryptionScheme: 32,
+  InvalidEncryptedFormat:      33,
+  NoDecryptKey:                34,
+  EncryptionFailure:           35,
+  DataRetrievalFailure:        36,
+  General:                     100
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/encrypt-key https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * An EncryptKey supplies the key for encrypt.
+ * Create an EncryptKey with the given key value.
+ * @param {Blob|EncryptKey} value If value is another EncryptKey then copy it.
+ * Otherwise, value is the key value.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var EncryptKey = function EncryptKey(value)
+{
+  if (typeof value === 'object' && value instanceof EncryptKey) {
+    // Make a deep copy.
+    this.keyBits_ = value.keyBits_;
+  }
+  else {
+    var keyBits = value;
+    this.keyBits_ = typeof keyBits === 'object' && keyBits instanceof Blob ?
+      keyBits : new Blob(keyBits);
+  }
+};
+
+exports.EncryptKey = EncryptKey;
+
+/**
+ * Get the key value.
+ * @return {Blob} The key value.
+ */
+EncryptKey.prototype.getKeyBits = function() { return this.keyBits_; };
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/encrypted-content https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var KeyLocator = require('../key-locator.js').KeyLocator; /** @ignore */
+var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * An EncryptedContent holds an encryption type, a payload and other fields
+ * representing encrypted content.
+ * @param {EncryptedContent} (optional) If value is another EncryptedContent
+ * then copy it. If value is omitted then create an EncryptedContent with
+ * unspecified values.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var EncryptedContent = function EncryptedContent(value)
+{
+  if (typeof value === 'object' && value instanceof EncryptedContent) {
+    // Make a deep copy.
+    this.algorithmType_ = value.algorithmType_;
+    this.keyLocator_ = new KeyLocator(value.keyLocator_);
+    this.initialVector_ = value.initialVector_;
+    this.payload_ = value.payload_;
+  }
+  else {
+    this.algorithmType_ = null;
+    this.keyLocator_ = new KeyLocator();
+    this.initialVector_ = new Blob();
+    this.payload_ = new Blob();
+  }
+};
+
+exports.EncryptedContent = EncryptedContent;
+
+/**
+ * Get the algorithm type from EncryptAlgorithmType.
+ * @return {number} The algorithm type from EncryptAlgorithmType, or null if
+ * not specified.
+ */
+EncryptedContent.prototype.getAlgorithmType = function()
+{
+  return this.algorithmType_;
+};
+
+/**
+ * Get the key locator.
+ * @return {KeyLocator} The key locator. If not specified, getType() is null.
+ */
+EncryptedContent.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_;
+};
+
+/**
+ * Get the initial vector.
+ * @return {Blob} The initial vector. If not specified, isNull() is true.
+ */
+EncryptedContent.prototype.getInitialVector = function()
+{
+  return this.initialVector_;
+};
+
+/**
+ * Get the payload.
+ * @return {Blob} The payload. If not specified, isNull() is true.
+ */
+EncryptedContent.prototype.getPayload = function()
+{
+  return this.payload_;
+};
+
+/**
+ * Set the algorithm type.
+ * @param {number} algorithmType The algorithm type from EncryptAlgorithmType.
+ * If not specified, set to null.
+ * @return {EncryptedContent} This EncryptedContent so that you can chain calls
+ * to update values.
+ */
+EncryptedContent.prototype.setAlgorithmType = function(algorithmType)
+{
+  this.algorithmType_ = algorithmType;
+  return this;
+};
+
+/**
+ * Set the key locator.
+ * @param {KeyLocator} keyLocator The key locator. This makes a copy of the
+ * object. If not specified, set to the default KeyLocator().
+ * @return {EncryptedContent} This EncryptedContent so that you can chain calls
+ * to update values.
+ */
+EncryptedContent.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_ = typeof keyLocator === 'object' &&
+                       keyLocator instanceof KeyLocator ?
+    new KeyLocator(keyLocator) : new KeyLocator();
+  return this;
+};
+
+/**
+ * Set the initial vector.
+ * @param {Blob} initialVector The initial vector. If not specified, set to the
+ * default Blob() where isNull() is true.
+ * @return {EncryptedContent} This EncryptedContent so that you can chain calls
+ * to update values.
+ */
+EncryptedContent.prototype.setInitialVector = function(initialVector)
+{
+  this.initialVector_ =
+      typeof initialVector === 'object' && initialVector instanceof Blob ?
+    initialVector : new Blob(initialVector);
+  return this;
+};
+
+/**
+ * Set the encrypted payload.
+ * @param {Blob} payload The payload. If not specified, set to the default Blob()
+ * where isNull() is true.
+ * @return {EncryptedContent} This EncryptedContent so that you can chain calls
+ * to update values.
+ */
+EncryptedContent.prototype.setPayload = function(payload)
+{
+  this.payload_ = typeof payload === 'object' && payload instanceof Blob ?
+    payload : new Blob(payload);
+  return this;
+};
+
+/**
+ * Encode this EncryptedContent for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+EncryptedContent.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeEncryptedContent(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this
+ * EncryptedContent.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+EncryptedContent.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeEncryptedContent(this, input.buf(), false);
+  else
+    wireFormat.decodeEncryptedContent(this, input, true);
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/group-manager-db https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise;
+
+/**
+ * GroupManagerDb is a base class for the storage of data used by the
+ * GroupManager. It contains two tables to store Schedules and Members.
+ * This is an abstract base class. A subclass must implement the methods.
+ * For example, see Sqlite3GroupManagerDb (for Nodejs) or IndexedDbGroupManagerDb
+ * (for the browser).
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var GroupManagerDb = function GroupManagerDb()
+{
+};
+
+exports.GroupManagerDb = GroupManagerDb;
+
+/**
+ * Create a new GroupManagerDb.Error to report an error using GroupManagerDb
+ * methods, wrapping the given error object.
+ * Call with: throw new GroupManagerDb.Error(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+GroupManagerDb.Error = function GroupManagerDbError(error)
+{
+  if (error) {
+    error.__proto__ = GroupManagerDb.Error.prototype;
+    return error;
+  }
+}
+
+GroupManagerDb.Error.prototype = new Error();
+GroupManagerDb.Error.prototype.name = "GroupManagerDbError";
+
+////////////////////////////////////////////////////// Schedule management.
+
+/**
+ * Check if there is a schedule with the given name.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns true if there is a
+ * schedule (else false), or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+GroupManagerDb.prototype.hasSchedulePromise = function(name, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.hasSchedulePromise is not implemented"));
+};
+
+/**
+ * List all the names of the schedules.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new array of string
+ * with the names of all schedules, or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManagerDb.prototype.listAllScheduleNamesPromise = function(useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.listAllScheduleNamesPromise is not implemented"));
+};
+
+/**
+ * Get a schedule with the given name.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new Schedule object,
+ * or that is rejected with GroupManagerDb.Error if the schedule does not exist
+ * or other database error.
+ */
+GroupManagerDb.prototype.getSchedulePromise = function(name, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.getSchedulePromise is not implemented"));
+};
+
+/**
+ * For each member using the given schedule, get the name and public key DER
+ * of the member's key.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new array of object
+ * (where "keyName" is the Name of the public key and "publicKey" is the Blob of
+ * the public key DER), or that is rejected with GroupManagerDb.Error for a
+ * database error. Note that the member's identity name is keyName.getPrefix(-1).
+ * If the schedule name is not found, the list is empty.
+ */
+GroupManagerDb.prototype.getScheduleMembersPromise = function
+  (name, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.getScheduleMembersPromise is not implemented"));
+};
+
+/**
+ * Add a schedule with the given name.
+ * @param {string} name The name of the schedule. The name cannot be empty.
+ * @param {Schedule} schedule The Schedule to add.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * added, or that is rejected with GroupManagerDb.Error if a schedule with the
+ * same name already exists, if the name is empty, or other database error.
+ */
+GroupManagerDb.prototype.addSchedulePromise = function(name, schedule, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.addSchedulePromise is not implemented"));
+};
+
+/**
+ * Delete the schedule with the given name. Also delete members which use this
+ * schedule. If there is no schedule with the name, then do nothing.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * deleted (or there is no such schedule), or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManagerDb.prototype.deleteSchedulePromise = function(name, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.deleteSchedulePromise is not implemented"));
+};
+
+/**
+ * Rename a schedule with oldName to newName.
+ * @param {string} oldName The name of the schedule to be renamed.
+ * @param {string} newName The new name of the schedule. The name cannot be empty.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * renamed, or that is rejected with GroupManagerDb.Error if a schedule with
+ * newName already exists, if the schedule with oldName does not exist, if
+ * newName is empty, or other database error.
+ */
+GroupManagerDb.prototype.renameSchedulePromise = function
+  (oldName, newName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.renameSchedulePromise is not implemented"));
+};
+
+/**
+ * Update the schedule with name and replace the old object with the given
+ * schedule. Otherwise, if no schedule with name exists, a new schedule
+ * with name and the given schedule will be added to database.
+ * @param {string} name The name of the schedule. The name cannot be empty.
+ * @param {Schedule} schedule The Schedule to update or add.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * updated, or that is rejected with GroupManagerDb.Error if the name is empty,
+ * or other database error.
+ */
+GroupManagerDb.prototype.updateSchedulePromise = function
+  (name, schedule, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.updateSchedulePromise is not implemented"));
+};
+
+////////////////////////////////////////////////////// Member management.
+
+/**
+ * Check if there is a member with the given identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns true if there is a
+ * member (else false), or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+GroupManagerDb.prototype.hasMemberPromise = function(identity, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.hasMemberPromise is not implemented"));
+};
+
+/**
+ * List all the members.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new array of Name with
+ * the names of all members, or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+GroupManagerDb.prototype.listAllMembersPromise = function(useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.listAllMembersPromise is not implemented"));
+};
+
+/**
+ * Get the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the string schedule name,
+ * or that is rejected with GroupManagerDb.Error if there's no member with the
+ * given identity name in the database, or other database error.
+ */
+GroupManagerDb.prototype.getMemberSchedulePromise = function(identity, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.getMemberSchedulePromise is not implemented"));
+};
+
+/**
+ * Add a new member with the given key named keyName into a schedule named
+ * scheduleName. The member's identity name is keyName.getPrefix(-1).
+ * @param {string} scheduleName The schedule name.
+ * @param {Name} keyName The name of the key.
+ * @param {Blob} key A Blob of the public key DER.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * added, or that is rejected with GroupManagerDb.Error if there's no schedule
+ * named scheduleName, if the member's identity name already exists, or other
+ * database error.
+ */
+GroupManagerDb.prototype.addMemberPromise = function
+  (scheduleName, keyName, key, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.addMemberPromise is not implemented"));
+};
+
+/**
+ * Change the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {string} scheduleName The new schedule name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * updated, or that is rejected with GroupManagerDb.Error if there's no member
+ * with the given identity name in the database, or there's no schedule named
+ * scheduleName, or other database error.
+ */
+GroupManagerDb.prototype.updateMemberSchedulePromise = function
+  (identity, scheduleName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.updateMemberSchedulePromise is not implemented"));
+};
+
+/**
+ * Delete a member with the given identity name. If there is no member with
+ * the identity name, then do nothing.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * deleted (or there is no such member), or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManagerDb.prototype.deleteMemberPromise = function(identity, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.deleteMemberPromise is not implemented"));
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/group-manager https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
+var IdentityCertificate = require('../security/certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var SecurityException = require('../security/security-exception.js').SecurityException; /** @ignore */
+var RsaKeyParams = require('../security/key-params.js').RsaKeyParams; /** @ignore */
+var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
+var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
+var RsaAlgorithm = require('./algo/rsa-algorithm.js').RsaAlgorithm; /** @ignore */
+var Interval = require('./interval.js').Interval; /** @ignore */
+var Schedule = require('./schedule.js').Schedule;
+
+/**
+ * A GroupManager manages keys and schedules for group members in a particular
+ * namespace.
+ * Create a group manager with the given values. The group manager namespace
+ * is <prefix>/read/<dataType> .
+ * @param {Name} prefix The prefix for the group manager namespace.
+ * @param {Name} dataType The data type for the group manager namespace.
+ * @param {GroupManagerDb} database The GroupManagerDb for storing the group
+ * management information (including user public keys and schedules).
+ * @param {number} keySize The group key will be an RSA key with keySize bits.
+ * @param {number} freshnessHours The number of hours of the freshness period of
+ *   data packets carrying the keys.
+ * @param {KeyChain} keyChain The KeyChain to use for signing data packets. This
+ * signs with the default identity.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var GroupManager = function GroupManager
+  (prefix, dataType, database, keySize, freshnessHours, keyChain)
+{
+  this.namespace_ = new Name(prefix).append(Encryptor.NAME_COMPONENT_READ)
+    .append(dataType);
+  this.database_ = database;
+  this.keySize_ = keySize;
+  this.freshnessHours_ = freshnessHours;
+
+  this.keyChain_ = keyChain;
+};
+
+exports.GroupManager = GroupManager;
+
+/**
+ * Create a group key for the interval into which timeSlot falls. This creates
+ * a group key if it doesn't exist, and encrypts the key using the public key of
+ * each eligible member.
+ * @param {number} timeSlot The time slot to cover as milliseconds since
+ * Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a List of Data packets
+ * (where the first is the E-KEY data packet with the group's public key and the
+ * rest are the D-KEY data packets with the group's private key encrypted with
+ * the public key of each eligible member), or that is rejected with
+ * GroupManagerDb.Error for a database error or SecurityException for an error
+ * using the security KeyChain.
+ */
+GroupManager.prototype.getGroupKeyPromise = function(timeSlot, useSync)
+{
+  var memberKeys = [];
+  var result = [];
+  var thisManager = this;
+  var privateKeyBlob;
+  var publicKeyBlob;
+  var startTimeStamp;
+  var endTimeStamp;
+
+  // Get the time interval.
+  return this.calculateIntervalPromise_(timeSlot, memberKeys, useSync)
+  .then(function(finalInterval) {
+    if (finalInterval.isValid() == false)
+      return SyncPromise.resolve(result);
+
+    startTimeStamp = Schedule.toIsoString(finalInterval.getStartTime());
+    endTimeStamp = Schedule.toIsoString(finalInterval.getEndTime());
+
+    // Generate the private and public keys.
+    return thisManager.generateKeyPairPromise_(useSync)
+    .then(function(keyPair) {
+      privateKeyBlob = keyPair.privateKeyBlob;
+      publicKeyBlob = keyPair.publicKeyBlob;
+
+      // Add the first element to the result.
+      // The E-KEY (public key) data packet name convention is:
+      // /<data_type>/E-KEY/[start-ts]/[end-ts]
+      return thisManager.createEKeyDataPromise_
+        (startTimeStamp, endTimeStamp, publicKeyBlob, useSync);
+    })
+    .then(function(data) {
+      result.push(data);
+
+      // Encrypt the private key with the public key from each member's certificate.
+
+      // Process the memberKeys entry at i, and recursively call to process the
+      // next entry. Return a promise which is resolved when all are processed.
+      // (We have to make a recursive function to use Promises.)
+      function processMemberKey(i) {
+        if (i >= memberKeys.length)
+          // Finished.
+          return SyncPromise.resolve();
+
+        var keyName = memberKeys[i].keyName;
+        var certificateKey = memberKeys[i].publicKey;
+
+        return thisManager.createDKeyDataPromise_
+          (startTimeStamp, endTimeStamp, keyName, privateKeyBlob, certificateKey,
+           useSync)
+        .then(function(data) {
+          result.push(data);
+
+          return processMemberKey(i + 1);
+        });
+      }
+
+      return processMemberKey(0);
+    })
+    .then(function() {
+      return SyncPromise.resolve(result);
+    });
+  });
+};
+
+/**
+ * Add a schedule with the given scheduleName.
+ * @param {string} scheduleName The name of the schedule. The name cannot be
+ * empty.
+ * @param {Schedule} schedule The Schedule to add.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * added, or that is rejected with GroupManagerDb.Error if a schedule with the
+ * same name already exists, if the name is empty, or other database error.
+ */
+GroupManager.prototype.addSchedulePromise = function
+  (scheduleName, schedule, useSync)
+{
+  return this.database_.addSchedulePromise(scheduleName, schedule, useSync);
+};
+
+/**
+ * Delete the schedule with the given scheduleName. Also delete members which
+ * use this schedule. If there is no schedule with the name, then do nothing.
+ * @param {string} scheduleName The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * deleted (or there is no such schedule), or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManager.prototype.deleteSchedulePromise = function(scheduleName, useSync)
+{
+  return this.database_.deleteSchedulePromise(scheduleName, useSync);
+};
+
+/**
+ * Update the schedule with scheduleName and replace the old object with the
+ * given schedule. Otherwise, if no schedule with name exists, a new schedule
+ * with name and the given schedule will be added to database.
+ * @param {string} scheduleName The name of the schedule. The name cannot be
+ * empty.
+ * @param {Schedule} schedule The Schedule to update or add.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * updated, or that is rejected with GroupManagerDb.Error if the name is empty,
+ * or other database error.
+ */
+GroupManager.prototype.updateSchedulePromise = function
+  (name, scheduleName, useSync)
+{
+  return this.database_.updateSchedulePromise(scheduleName, schedule, useSync);
+};
+
+/**
+ * Add a new member with the given memberCertificate into a schedule named
+ * scheduleName. If cert is an IdentityCertificate made from memberCertificate,
+ * then the member's identity name is cert.getPublicKeyName().getPrefix(-1).
+ * @param {string} scheduleName The schedule name.
+ * @param {Data} memberCertificate The member's certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * added, or that is rejected with GroupManagerDb.Error if there's no schedule
+ * named scheduleName, if the member's identity name already exists, or other
+ * database error. Or a promise that is rejected with DerDecodingException for
+ * an error decoding memberCertificate as a certificate.
+ */
+GroupManager.prototype.addMemberPromise = function
+  (scheduleName, memberCertificate, useSync)
+{
+  var cert = new IdentityCertificate(memberCertificate);
+  return this.database_.addMemberPromise
+    (scheduleName, cert.getPublicKeyName(), cert.getPublicKeyInfo().getKeyDer(),
+     useSync);
+};
+
+/**
+ * Remove a member with the given identity name. If there is no member with
+ * the identity name, then do nothing.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * removed (or there is no such member), or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManager.prototype.removeMemberPromise = function(identity, useSync)
+{
+  return this.database_.deleteMemberPromise(identity, useSync);
+};
+
+/**
+ * Change the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {string} scheduleName The new schedule name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * updated, or that is rejected with GroupManagerDb.Error if there's no member
+ * with the given identity name in the database, or there's no schedule named
+ * scheduleName.
+ */
+GroupManager.prototype.updateMemberSchedulePromise = function
+  (identity, scheduleName, useSync)
+{
+  return this.database_.updateMemberSchedulePromise
+    (identity, scheduleName, useSync);
+};
+
+/**
+ * Calculate an Interval that covers the timeSlot.
+ * @param {number} timeSlot The time slot to cover as milliseconds since
+ * Jan 1, 1970 UTC.
+ * @param {Array<object>} memberKeys First clear memberKeys then fill it with
+ * the info of members who are allowed to access the interval. memberKeys is an
+ * array of object where "keyName" is the Name of the public key and "publicKey"
+ * is the Blob of the public key DER. The memberKeys entries are sorted by
+ * the entry keyName.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new nterval covering
+ * the time slot, or that is rejected with GroupManagerDb.Error for a database
+ * error.
+ */
+GroupManager.prototype.calculateIntervalPromise_ = function
+  (timeSlot, memberKeys, useSync)
+{
+  // Prepare.
+  var positiveResult = new Interval();
+  var negativeResult = new Interval();
+  // Clear memberKeys.
+  memberKeys.splice(0, memberKeys.length);
+  var thisManager = this;
+
+  // Get the all intervals from the schedules.
+  return this.database_.listAllScheduleNamesPromise(useSync)
+  .then(function(scheduleNames) {
+    // Process the scheduleNames entry at i, and recursively call to process the
+    // next entry. Return a promise which is resolved when all are processed.
+    // (We have to make a recursive function to use Promises.)
+    function processSchedule(i) {
+      if (i >= scheduleNames.length)
+        // Finished.
+        return SyncPromise.resolve();
+
+      var scheduleName = scheduleNames[i];
+
+      return thisManager.database_.getSchedulePromise(scheduleName, useSync)
+      .then(function(schedule) {
+        var result = schedule.getCoveringInterval(timeSlot);
+        var tempInterval = result.interval;
+
+        if (result.isPositive) {
+          if (!positiveResult.isValid())
+            positiveResult = tempInterval;
+          positiveResult.intersectWith(tempInterval);
+
+          return thisManager.database_.getScheduleMembersPromise
+            (scheduleName, useSync)
+          .then(function(map) {
+            // Add each entry in map to memberKeys.
+            for (var iMap = 0; iMap < map.length; ++iMap)
+              GroupManager.memberKeysAdd_(memberKeys, map[iMap]);
+
+            return processSchedule(i + 1);
+          });
+        }
+        else {
+          if (!negativeResult.isValid())
+            negativeResult = tempInterval;
+          negativeResult.intersectWith(tempInterval);
+
+          return processSchedule(i + 1);
+        }
+      });
+    }
+
+    return processSchedule(0);
+  })
+  .then(function() {
+    if (!positiveResult.isValid())
+      // Return an invalid interval when there is no member which has an
+      // interval covering the time slot.
+      return SyncPromise.resolve(new Interval(false));
+
+    // Get the final interval result.
+    var finalInterval;
+    if (negativeResult.isValid())
+      finalInterval = positiveResult.intersectWith(negativeResult);
+    else
+      finalInterval = positiveResult;
+
+    return SyncPromise.resolve(finalInterval);
+  });
+};
+
+/**
+ * Add entry to memberKeys, sorted by entry.keyName. If there is already an
+ * entry with keyName, then don't add.
+ */
+GroupManager.memberKeysAdd_ = function(memberKeys, entry)
+{
+  // Find the index of the first node where the keyName is not less than
+  // entry.keyName.
+  var i = 0;
+  while (i < memberKeys.length) {
+    var comparison = memberKeys[i].keyName.compare(entry.keyName);
+    if (comparison == 0)
+      // A duplicate, so don't add.
+      return;
+
+    if (comparison > 0)
+      break;
+    i += 1;
+  }
+
+  memberKeys.splice(i, 0, entry);
+};
+
+/**
+ * Generate an RSA key pair according to keySize_.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns an object where
+ * "privateKeyBlob" is the encoding Blob of the private key and "publicKeyBlob"
+ * is the encoding Blob of the public key.
+ */
+GroupManager.prototype.generateKeyPairPromise_ = function(useSync)
+{
+  var params = new RsaKeyParams(this.keySize_);
+
+  return RsaAlgorithm.generateKeyPromise(params)
+  .then(function(privateKey) {
+    var privateKeyBlob = privateKey.getKeyBits();
+    var publicKey = RsaAlgorithm.deriveEncryptKey(privateKeyBlob);
+    var publicKeyBlob = publicKey.getKeyBits();
+
+    return SyncPromise.resolve
+      ({ privateKeyBlob: privateKeyBlob, publicKeyBlob: publicKeyBlob });
+  });
+};
+
+/**
+ * Create an E-KEY Data packet for the given public key.
+ * @param {string} startTimeStamp The start time stamp string to put in the name.
+ * @param {string} endTimeStamp The end time stamp string to put in the name.
+ * @param {Blob} publicKeyBlob A Blob of the public key DER.
+ * @return The Data packet.
+ * @throws SecurityException for an error using the security KeyChain.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the Data packet, or that
+ * is rejected with SecurityException for an error using the security KeyChain.
+ */
+GroupManager.prototype.createEKeyDataPromise_ = function
+  (startTimeStamp, endTimeStamp, publicKeyBlob, useSync)
+{
+  var name = new Name(this.namespace_);
+  name.append(Encryptor.NAME_COMPONENT_E_KEY).append(startTimeStamp)
+    .append(endTimeStamp);
+
+  var data = new Data(name);
+  data.getMetaInfo().setFreshnessPeriod
+    (this.freshnessHours_ * GroupManager.MILLISECONDS_IN_HOUR);
+  data.setContent(publicKeyBlob);
+
+  return this.keyChain_.signPromise(data);
+};
+
+/**
+ * Create a D-KEY Data packet with an EncryptedContent for the given private
+ * key, encrypted with the certificate key.
+ * @param {string} startTimeStamp The start time stamp string to put in the name.
+ * @param {string} endTimeStamp The end time stamp string to put in the name.
+ * @param {Name} keyName The key name to put in the data packet name and the
+ * EncryptedContent key locator.
+ * @param {Blob} privateKeyBlob A Blob of the encoded private key.
+ * @param {Blob} certificateKey The certificate key encoding, used to encrypt
+ * the private key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the Data packet, or that
+ * is rejected with SecurityException for an error using the security KeyChain.
+ */
+GroupManager.prototype.createDKeyDataPromise_ = function
+  (startTimeStamp, endTimeStamp, keyName, privateKeyBlob, certificateKey,
+   useSync)
+{
+  var name = new Name(this.namespace_);
+  name.append(Encryptor.NAME_COMPONENT_D_KEY);
+  name.append(startTimeStamp).append(endTimeStamp);
+  var data = new Data(name);
+  data.getMetaInfo().setFreshnessPeriod
+    (this.freshnessHours_ * GroupManager.MILLISECONDS_IN_HOUR);
+  var encryptParams = new EncryptParams(EncryptAlgorithmType.RsaOaep);
+  var thisManager = this;
+
+  return Encryptor.encryptDataPromise
+    (data, privateKeyBlob, keyName, certificateKey, encryptParams, useSync)
+  .catch(function(ex) {
+    // Consolidate errors such as InvalidKeyException.
+    return SyncPromise.reject(SecurityException(new Error
+      ("createDKeyData: Error in encryptData: " + ex)));
+  })
+  .then(function() {
+    return thisManager.keyChain_.signPromise(data);
+  });
+};
+
+GroupManager.MILLISECONDS_IN_HOUR = 3600 * 1000;
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/interval https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * An Interval defines a time duration which contains a start timestamp and an
+ * end timestamp. Create an Interval with one of these forms:
+ * Interval(isValid).
+ * Interval(startTime, endTime).
+ * Interval(interval).
+ * @param {boolean} isValid True to create a valid empty interval, false to
+ * create an invalid interval.
+ * @param {number} startTime The start time as milliseconds since Jan 1, 1970 UTC.
+ * The start time must be less than the end time. To create an empty interval
+ * (start time equals end time), use the constructor Interval(true).
+ * @param {number} endTime The end time as milliseconds since Jan 1, 1970 UTC.
+ * @param {Interval} interval The other interval with values to copy.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var Interval = function Interval(value, endTime)
+{
+  if (typeof value === 'object' && value instanceof Interval) {
+    // Make a copy.
+    this.startTime_ = value.startTime_;
+    this.endTime_ = value.endTime_;
+    this.isValid_ = value.isValid_;
+  }
+  else if (typeof value === 'number') {
+    var startTime = value;
+
+    if (!(startTime < endTime))
+      throw new Error("Interval start time must be less than the end time");
+
+    this.startTime_ = startTime;
+    this.endTime_ = endTime;
+    this.isValid_ = true;
+  }
+  else {
+    var isValid = (value ? true : false);
+
+    this.startTime_ = -Number.MAX_VALUE;
+    this.endTime_ = -Number.MAX_VALUE;
+    this.isValid_ = isValid;
+  }
+};
+
+exports.Interval = Interval;
+
+/**
+ * Set this interval to have the same values as the other interval.
+ * @param {Interval} other The other Interval with values to copy.
+ */
+Interval.prototype.set = function(other)
+{
+  this.startTime_ = other.startTime_;
+  this.endTime_ = other.endTime_;
+  this.isValid_ = other.isValid_;
+};
+
+/**
+ * Check if the time point is in this interval.
+ * @param {number} timePoint The time point to check as milliseconds since
+ * Jan 1, 1970 UTC.
+ * @return {boolean} True if timePoint is in this interval.
+ * @throws Error if this Interval is invalid.
+ */
+Interval.prototype.covers = function(timePoint)
+{
+  if (!this.isValid_)
+    throw new Error("Interval.covers: This Interval is invalid");
+
+  if (this.isEmpty())
+    return false;
+  else
+    return this.startTime_ <= timePoint && timePoint < this.endTime_;
+};
+
+/**
+ * Set this Interval to the intersection of this and the other interval.
+ * This and the other interval should be valid but either can be empty.
+ * @param {Interval} interval The other Interval to intersect with.
+ * @return {Interval} This Interval.
+ * @throws Error if this Interval or the other interval is invalid.
+ */
+Interval.prototype.intersectWith = function(interval)
+{
+  if (!this.isValid_)
+    throw new Error("Interval.intersectWith: This Interval is invalid");
+  if (!interval.isValid_)
+    throw new Error("Interval.intersectWith: The other Interval is invalid");
+
+  if (this.isEmpty() || interval.isEmpty()) {
+    // If either is empty, the result is empty.
+    this.startTime_ = this.endTime_;
+    return this;
+  }
+
+  if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_) {
+    // The two intervals don't have an intersection, so the result is empty.
+    this.startTime_ = this.endTime_;
+    return this;
+  }
+
+  // Get the start time.
+  if (this.startTime_ <= interval.startTime_)
+    this.startTime_ = interval.startTime_;
+
+  // Get the end time.
+  if (this.endTime_ > interval.endTime_)
+    this.endTime_ = interval.endTime_;
+
+  return this;
+};
+
+/**
+ * Set this Interval to the union of this and the other interval.
+ * This and the other interval should be valid but either can be empty.
+ * This and the other interval should have an intersection. (Contiguous
+ * intervals are not allowed.)
+ * @param {Interval} interval The other Interval to union with.
+ * @return {Interval} This Interval.
+ * @throws Error if this Interval or the other interval is invalid, or if the
+ * two intervals do not have an intersection.
+ */
+Interval.prototype.unionWith = function(interval)
+{
+  if (!this.isValid_)
+    throw new Error("Interval.intersectWith: This Interval is invalid");
+  if (!interval.isValid_)
+    throw new Error("Interval.intersectWith: The other Interval is invalid");
+
+  if (this.isEmpty()) {
+    // This interval is empty, so use the other.
+    this.startTime_ = interval.startTime_;
+    this.endTime_ = interval.endTime_;
+    return this;
+  }
+
+  if (interval.isEmpty())
+    // The other interval is empty, so keep using this one.
+    return this;
+
+  if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_)
+    throw new Error
+      ("Interval.unionWith: The two intervals do not have an intersection");
+
+  // Get the start time.
+  if (this.startTime_ > interval.startTime_)
+    this.startTime_ = interval.startTime_;
+
+  // Get the end time.
+  if (this.endTime_ < interval.endTime_)
+    this.endTime_ = interval.endTime_;
+
+  return this;
+};
+
+/**
+ * Get the start time.
+ * @return {number} The start time as milliseconds since Jan 1, 1970 UTC.
+ * @throws Error if this Interval is invalid.
+ */
+Interval.prototype.getStartTime = function()
+{
+  if (!this.isValid_)
+    throw new Error("Interval.getStartTime: This Interval is invalid");
+  return this.startTime_;
+};
+
+/**
+ * Get the end time.
+ * @return {number} The end time as milliseconds since Jan 1, 1970 UTC.
+ * @throws Error if this Interval is invalid.
+ */
+Interval.prototype.getEndTime = function()
+{
+  if (!this.isValid_)
+    throw new Error("Interval.getEndTime: This Interval is invalid");
+  return this.endTime_;
+};
+
+/**
+ * Check if this Interval is valid.
+ * @return {boolean} True if this interval is valid, false if invalid.
+ */
+Interval.prototype.isValid = function() { return this.isValid_; };
+
+/**
+ * Check if this Interval is empty.
+ * @return {boolean} True if this Interval is empty (start time equals end time),
+ * false if not.
+ * @throws Error if this Interval is invalid.
+ */
+Interval.prototype.isEmpty = function()
+{
+  if (!this.isValid_)
+    throw new Error("Interval.isEmpty: This Interval is invalid");
+  return this.startTime_ == this.endTime_;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/producer-db https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise;
+
+/**
+ * ProducerDb is a base class for the storage of keys for the producer. It contains
+ * one table that maps time slots (to the nearest hour) to the content key
+ * created for that time slot. A subclass must implement the methods. For
+ * example, see Sqlite3ProducerDb (for Nodejs) or IndexedDbProducerDb (for the
+ * browser).
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var ProducerDb = function ProducerDb()
+{
+};
+
+exports.ProducerDb = ProducerDb;
+
+/**
+ * Create a new ProducerDb.Error to report an error using ProducerDb
+ * methods, wrapping the given error object.
+ * Call with: throw new ProducerDb.Error(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+ProducerDb.Error = function ProducerDbError(error)
+{
+  if (error) {
+    error.__proto__ = ProducerDb.Error.prototype;
+    return error;
+  }
+}
+
+ProducerDb.Error.prototype = new Error();
+ProducerDb.Error.prototype.name = "ProducerDbError";
+
+/**
+ * Check if a content key exists for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns true if there is a
+ * content key for timeSlot (else false), or that is rejected with
+ * ProducerDb.Error for a database error.
+ */
+ProducerDb.prototype.hasContentKeyPromise = function(timeSlot, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ProducerDb.hasContentKeyPromise is not implemented"));
+};
+
+/**
+ * Get the content key for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
+ * key, or that is rejected with ProducerDb.Error if there is no key covering
+ * timeSlot, or other database error
+ */
+ProducerDb.prototype.getContentKeyPromise = function(timeSlot, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ProducerDb.getContentKeyPromise is not implemented"));
+};
+
+/**
+ * Add key as the content key for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {Blob} key The encoded key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
+ * or that is rejected with ProducerDb.Error if a key for the same hour already
+ * exists in the database, or other database error.
+ */
+ProducerDb.prototype.addContentKeyPromise = function
+  (timeSlot, key, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ProducerDb.addContentKeyPromise is not implemented"));
+};
+
+/**
+ * Delete the content key for the hour covering timeSlot. If there is no key for
+ * the time slot, do nothing.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is deleted
+ * (or there is no such key), or that is rejected with ProducerDb.Error for a
+ * database error.
+ */
+ProducerDb.prototype.deleteContentKeyPromise = function(timeSlot, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ProducerDb.deleteContentKeyPromise is not implemented"));
+};
+
+/**
+ * Get the hour-based time slot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @return {number} The hour-based time slot as hours since Jan 1, 1970 UTC.
+ */
+ProducerDb.getFixedTimeSlot = function(timeSlot)
+{
+  return Math.floor(Math.round(timeSlot) / 3600000.0);
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/producer https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var Link = require('../link.js').Link; /** @ignore */
+var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
+var Exclude = require('../exclude.js').Exclude; /** @ignore */
+var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
+var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
+var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var AesKeyParams = require('../security/key-params.js').AesKeyParams; /** @ignore */
+var AesAlgorithm = require('./algo/aes-algorithm.js').AesAlgorithm; /** @ignore */
+var Schedule = require('./schedule.js').Schedule; /** @ignore */
+var EncryptError = require('./encrypt-error.js').EncryptError; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise;
+
+/**
+ * A Producer manages content keys used to encrypt a data packet in the
+ * group-based encryption protocol.
+ * Create a Producer to use the given ProducerDb, Face and other values.
+ *
+ * A producer can produce data with a naming convention:
+ *   /<prefix>/SAMPLE/<dataType>/[timestamp]
+ *
+ * The produced data packet is encrypted with a content key,
+ * which is stored in the ProducerDb database.
+ *
+ * A producer also needs to produce data containing a content key
+ * encrypted with E-KEYs. A producer can retrieve E-KEYs through the face,
+ * and will re-try for at most repeatAttemps times when E-KEY retrieval fails.
+ *
+ * @param {Name} prefix The producer name prefix. This makes a copy of the Name.
+ * @param {Name} dataType The dataType portion of the producer name. This makes
+ * a copy of the Name.
+ * @param {Face} face The face used to retrieve keys.
+ * @param {KeyChain} keyChain The keyChain used to sign data packets.
+ * @param {ProducerDb} database The ProducerDb database for storing keys.
+ * @param {number} repeatAttempts (optional) The maximum retry for retrieving
+ * keys. If omitted, use a default value of 3.
+ * @param {Link} keyRetrievalLink (optional) The Link object to use in Interests
+ * for key retrieval. This makes a copy of the Link object. If the Link object's
+ * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
+ * object.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var Producer = function Producer
+  (prefix, dataType, face, keyChain, database, repeatAttempts, keyRetrievalLink)
+{
+  this.face_ = face;
+  this.keyChain_ = keyChain;
+  this.database_ = database;
+  this.maxRepeatAttempts_ = (repeatAttempts == undefined ? 3 : repeatAttempts);
+  this.keyRetrievalLink_ =
+    (keyRetrievalLink == undefined ? Producer.NO_LINK : new Link(keyRetrievalLink));
+
+  // The map key is the key name URI string. The value is an object with fields
+  // "keyName" and "keyInfo" where "keyName" is the same Name used for the key
+  // name URI string, and "keyInfo" is the Producer.KeyInfo_.
+  // (Use a string because we can't use the Name object as the key in JavaScript.)
+  // (Also put the original Name in the value because we need to iterate over
+  // eKeyInfo_ and we don't want to rebuild the Name from the name URI string.)
+  this.eKeyInfo_ = {};
+  // The map key is the time stamp. The value is a Producer.KeyRequest_.
+  this.keyRequests_ = {};
+
+  var fixedPrefix = new Name(prefix);
+  var fixedDataType = new Name(dataType);
+
+  // Fill ekeyInfo_ with all permutations of dataType, including the 'E-KEY'
+  // component of the name. This will be used in createContentKey to send
+  // interests without reconstructing names every time.
+  fixedPrefix.append(Encryptor.NAME_COMPONENT_READ);
+  while (fixedDataType.size() > 0) {
+    var nodeName = new Name(fixedPrefix);
+    nodeName.append(fixedDataType);
+    nodeName.append(Encryptor.NAME_COMPONENT_E_KEY);
+
+    this.eKeyInfo_[nodeName.toUri()] =
+      { keyName: nodeName, keyInfo: new Producer.KeyInfo_() };
+    fixedDataType = fixedDataType.getPrefix(-1);
+  }
+  fixedPrefix.append(dataType);
+  this.namespace_ = new Name(prefix);
+  this.namespace_.append(Encryptor.NAME_COMPONENT_SAMPLE);
+  this.namespace_.append(dataType);
+};
+
+exports.Producer = Producer;
+
+/**
+ * Create the content key corresponding to the timeSlot. This first checks if
+ * the content key exists. For an existing content key, this returns the
+ * content key name directly. If the key does not exist, this creates one and
+ * encrypts it using the corresponding E-KEYs. The encrypted content keys are
+ * passed to the onEncryptedKeys callback.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys If this creates a content key, then this
+ * calls onEncryptedKeys(keys) where keys is a list of encrypted content key
+ * Data packets. If onEncryptedKeys is null, this does not use it.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onContentKeyName This calls onContentKeyName(contentKeyName)
+ * with the content key name for the time slot. If onContentKeyName is null,
+ * this does not use it. (A callback is needed because of async database
+ * operations.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) This calls onError(errorCode, message)
+ * for an error, where errorCode is from EncryptError.ErrorCode and message is a
+ * string. If omitted, use a default callback which does nothing.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+Producer.prototype.createContentKey = function
+  (timeSlot, onEncryptedKeys, onContentKeyName, onError)
+{
+  if (!onError)
+    onError = Producer.defaultOnError;
+
+  var hourSlot = Producer.getRoundedTimeSlot_(timeSlot);
+
+  // Create the content key name.
+  var contentKeyName = new Name(this.namespace_);
+  contentKeyName.append(Encryptor.NAME_COMPONENT_C_KEY);
+  contentKeyName.append(Schedule.toIsoString(hourSlot));
+
+  var contentKeyBits;
+  var thisProducer = this;
+
+  // Check if we have created the content key before.
+  this.database_.hasContentKeyPromise(timeSlot)
+  .then(function(exists) {
+    if (exists) {
+      if (onContentKeyName != null)
+        onContentKeyName(contentKeyName);
+      return;
+    }
+
+    // We haven't created the content key. Create one and add it into the database.
+    var aesParams = new AesKeyParams(128);
+    contentKeyBits = AesAlgorithm.generateKey(aesParams).getKeyBits();
+    thisProducer.database_.addContentKeyPromise(timeSlot, contentKeyBits)
+    .then(function() {
+      // Now we need to retrieve the E-KEYs for content key encryption.
+      var timeCount = Math.round(timeSlot);
+      thisProducer.keyRequests_[timeCount] =
+        new Producer.KeyRequest_(thisProducer.getEKeyInfoSize_());
+      var keyRequest = thisProducer.keyRequests_[timeCount];
+
+      // Check if the current E-KEYs can cover the content key.
+      var timeRange = new Exclude();
+      Producer.excludeAfter
+        (timeRange, new Name.Component(Schedule.toIsoString(timeSlot)));
+      for (var keyNameUri in thisProducer.eKeyInfo_) {
+         // For each current E-KEY.
+        var entry = thisProducer.eKeyInfo_[keyNameUri];
+        var keyInfo = entry.keyInfo;
+        if (timeSlot < keyInfo.beginTimeSlot || timeSlot >= keyInfo.endTimeSlot) {
+          // The current E-KEY cannot cover the content key, so retrieve one.
+          keyRequest.repeatAttempts[keyNameUri] = 0;
+          thisProducer.sendKeyInterest_
+            (new Interest(entry.keyName).setExclude(timeRange).setChildSelector(1),
+             timeSlot, onEncryptedKeys, onError);
+        }
+        else {
+          // The current E-KEY can cover the content key.
+          // Encrypt the content key directly.
+          var eKeyName = new Name(entry.keyName);
+          eKeyName.append(Schedule.toIsoString(keyInfo.beginTimeSlot));
+          eKeyName.append(Schedule.toIsoString(keyInfo.endTimeSlot));
+          thisProducer.encryptContentKeyPromise_
+            (keyInfo.keyBits, eKeyName, timeSlot, onEncryptedKeys, onError);
+        }
+      }
+
+      if (onContentKeyName != null)
+        onContentKeyName(contentKeyName);
+    });
+  });
+};
+
+/**
+ * Encrypt the given content with the content key that covers timeSlot, and
+ * update the data packet with the encrypted content and an appropriate data
+ * name.
+ * @param {Data} data An empty Data object which is updated.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {Blob} content The content to encrypt.
+ * @param {function} onComplete This calls onComplete() when the data packet has
+ * been updated.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) This calls onError(errorCode, message)
+ * for an error, where errorCode is from EncryptError.ErrorCode and message is a
+ * string. If omitted, use a default callback which does nothing.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+Producer.prototype.produce = function
+  (data, timeSlot, content, onComplete, onError)
+{
+  if (!onError)
+    onError = Producer.defaultOnError;
+
+  var thisProducer = this;
+
+  // Get a content key.
+  this.createContentKey(timeSlot, null, function(contentKeyName) {
+    thisProducer.database_.getContentKeyPromise(timeSlot)
+    .then(function(contentKey) {
+      // Produce data.
+      var dataName = new Name(thisProducer.namespace_);
+      dataName.append(Schedule.toIsoString(timeSlot));
+
+      data.setName(dataName);
+      var params = new EncryptParams(EncryptAlgorithmType.AesCbc, 16);
+      return Encryptor.encryptData
+        (data, content, contentKeyName, contentKey, params);
+    })
+    .then(function() {
+      return thisProducer.keyChain_.signPromise(data);
+    })
+    .then(function() {
+      try {
+        onComplete();
+      } catch (ex) {
+        console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }, function(error) {
+      try {
+        onError(EncryptError.ErrorCode.General, "" + error);
+      } catch (ex) {
+        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    });
+  }, onError);
+};
+
+/**
+ * The default onError callback which does nothing.
+ */
+Producer.defaultOnError = function(errorCode, message)
+{
+  // Do nothing.
+};
+
+Producer.KeyInfo_ = function ProducerKeyInfo()
+{
+  this.beginTimeSlot = 0.0;
+  this.endTimeSlot = 0.0;
+  this.keyBits = null; // Blob
+};
+
+Producer.KeyRequest_ = function ProducerKeyRequest(interests)
+{
+  this.interestCount = interests; // number
+  // The map key is the name URI string. The value is an int count.
+  // (Use a string because we can't use the Name object as the key in JavaScript.)
+  this.repeatAttempts = {};
+  this.encryptedKeys = []; // of Data
+};
+
+/**
+ * Round timeSlot to the nearest whole hour, so that we can store content keys
+ * uniformly (by start of the hour).
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @return {number} The start of the hour as milliseconds since Jan 1, 1970 UTC.
+ */
+Producer.getRoundedTimeSlot_ = function(timeSlot)
+{
+  return Math.round(Math.floor(Math.round(timeSlot) / 3600000.0) * 3600000.0);
+}
+
+/**
+ * Send an interest with the given name through the face with callbacks to
+ * handleCoveringKey_, handleTimeout_ and handleNetworkNack_.
+ * @param {Interest} interest The interest to send.
+ * @param {number} timeSlot The time slot, passed to handleCoveringKey_,
+ * handleTimeout_ and handleNetworkNack_.
+ * @param {function} onEncryptedKeys The OnEncryptedKeys callback, passed to
+ * handleCoveringKey_, handleTimeout_ and handleNetworkNack_.
+ * @param {function} onError This calls onError(errorCode, message) for an error.
+ */
+Producer.prototype.sendKeyInterest_ = function
+  (interest, timeSlot, onEncryptedKeys, onError)
+{
+  var thisProducer = this;
+
+  function onKey(interest, data) {
+    thisProducer.handleCoveringKey_
+      (interest, data, timeSlot, onEncryptedKeys, onError);
+  }
+
+  function onTimeout(interest) {
+    thisProducer.handleTimeout_(interest, timeSlot, onEncryptedKeys, onError);
+  }
+
+  function onNetworkNack(interest, networkNack) {
+    thisProducer.handleNetworkNack_
+      (interest, networkNack, timeSlot, onEncryptedKeys, onError);
+  }
+
+  var request;
+  if (this.keyRetrievalLink_.getDelegations().size() === 0)
+    // We can use the supplied interest without copying.
+    request = interest;
+  else {
+    // Copy the supplied interest and add the Link.
+    request = new Interest(interest);
+    // This will use a cached encoding if available.
+    request.setLinkWireEncoding(this.keyRetrievalLink_.wireEncode());
+  }
+
+  this.face_.expressInterest(request, onKey, onTimeout, onNetworkNack);
+};
+
+/**
+ * This is called from an expressInterest timeout to update the state of
+ * keyRequest. Re-express the interest if the number of retrials is less than
+ * the max limit.
+ * @param {Interest} interest The timed-out interest.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys When there are no more interests to process,
+ * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
+ * key Data packets. If onEncryptedKeys is null, this does not use it.
+ * @param {function} onError This calls onError(errorCode, message) for an error.
+ */
+Producer.prototype.handleTimeout_ = function
+  (interest, timeSlot, onEncryptedKeys, onError)
+{
+  var timeCount = Math.round(timeSlot);
+  var keyRequest = this.keyRequests_[timeCount];
+
+  var interestName = interest.getName();
+  var interestNameUri = interestName.toUri();
+
+  if (keyRequest.repeatAttempts[interestNameUri] < this.maxRepeatAttempts_) {
+    // Increase the retrial count.
+    ++keyRequest.repeatAttempts[interestNameUri];
+    this.sendKeyInterest_(interest, timeSlot, onEncryptedKeys, onError);
+  }
+  else
+    // Treat an eventual timeout as a network Nack.
+    this.handleNetworkNack_
+      (interest, new NetworkNack(), timeSlot, onEncryptedKeys, onError);
+};
+
+/**
+ * This is called from an expressInterest OnNetworkNack to handle a network
+ * Nack for the E-KEY requested through the Interest. Decrease the outstanding
+ * E-KEY interest count for the C-KEY corresponding to the timeSlot.
+ * @param {Interest} interest The interest given to expressInterest.
+ * @param {NetworkNack} networkNack The returned NetworkNack (unused).
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys When there are no more interests to process,
+ * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
+ * key Data packets. If onEncryptedKeys is null, this does not use it.
+ */
+Producer.prototype.handleNetworkNack_ = function
+  (interest, networkNack, timeSlot, onEncryptedKeys, onError)
+{
+  // We have run out of options....
+  var timeCount = Math.round(timeSlot);
+  this.updateKeyRequest_
+    (this.keyRequests_[timeCount], timeCount, onEncryptedKeys);
+};
+
+/**
+ * Decrease the count of outstanding E-KEY interests for the C-KEY for
+ * timeCount. If the count decreases to 0, invoke onEncryptedKeys.
+ * @param {Producer.KeyRequest_} keyRequest The KeyRequest with the
+ * interestCount to update.
+ * @param {number} timeCount The time count for indexing keyRequests_.
+ * @param {function} onEncryptedKeys When there are no more interests to
+ * process, this calls onEncryptedKeys(keys) where keys is a list of encrypted
+ * content key Data packets. If onEncryptedKeys is null, this does not use it.
+ */
+Producer.prototype.updateKeyRequest_ = function
+  (keyRequest, timeCount, onEncryptedKeys)
+{
+  --keyRequest.interestCount;
+  if (keyRequest.interestCount == 0 && onEncryptedKeys != null) {
+    try {
+      onEncryptedKeys(keyRequest.encryptedKeys);
+    } catch (ex) {
+      console.log("Error in onEncryptedKeys: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    delete this.keyRequests_[timeCount];
+  }
+};
+
+/**
+ * This is called from an expressInterest OnData to check that the encryption
+ * key contained in data fits the timeSlot. This sends a refined interest if
+ * required.
+ * @param {Interest} interest The interest given to expressInterest.
+ * @param {Data} data The fetched Data packet.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys When there are no more interests to process,
+ * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
+ * key Data packets. If onEncryptedKeys is null, this does not use it.
+ * @param {function} onError This calls onError(errorCode, message) for an error.
+ */
+Producer.prototype.handleCoveringKey_ = function
+  (interest, data, timeSlot, onEncryptedKeys, onError)
+{
+  var timeCount = Math.round(timeSlot);
+  var keyRequest = this.keyRequests_[timeCount];
+
+  var interestName = interest.getName();
+  var interestNameUrl = interestName.toUri();
+  var keyName = data.getName();
+
+  var begin = Schedule.fromIsoString
+    (keyName.get(Producer.START_TIME_STAMP_INDEX).getValue().toString());
+  var end = Schedule.fromIsoString
+    (keyName.get(Producer.END_TIME_STAMP_INDEX).getValue().toString());
+
+  if (timeSlot >= end) {
+    // If the received E-KEY covers some earlier period, try to retrieve an
+    // E-KEY covering a later one.
+    var timeRange = new Exclude(interest.getExclude());
+    Producer.excludeBefore(timeRange, keyName.get(Producer.START_TIME_STAMP_INDEX));
+    keyRequest.repeatAttempts[interestNameUrl] = 0;
+    this.sendKeyInterest_
+      (new Interest(interestName).setExclude(timeRange).setChildSelector(1),
+       timeSlot, onEncryptedKeys, onError);
+  }
+  else {
+    // If the received E-KEY covers the content key, encrypt the content.
+    var encryptionKey = data.getContent();
+    var thisProducer = this;
+    this.encryptContentKeyPromise_
+      (encryptionKey, keyName, timeSlot, onEncryptedKeys, onError)
+    .then(function(success) {
+      if (success) {
+        var keyInfo = thisProducer.eKeyInfo_[interestNameUrl].keyInfo;
+        keyInfo.beginTimeSlot = begin;
+        keyInfo.endTimeSlot = end;
+        keyInfo.keyBits = encryptionKey;
+      }
+    });
+  }
+};
+
+/**
+ * Get the content key from the database_ and encrypt it for the timeSlot
+ * using encryptionKey.
+ * @param {Blob} encryptionKey The encryption key value.
+ * @param {Name} eKeyName The key name for the EncryptedContent.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys When there are no more interests to process,
+ * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
+ * key Data packets. If onEncryptedKeys is null, this does not use it.
+ * @param {function} onError This calls onError(errorCode, message) for an error.
+ * @return {Promise} A promise that returns true if encryption succeeds,
+ * otherwise false.
+ */
+Producer.prototype.encryptContentKeyPromise_ = function
+  (encryptionKey, eKeyName, timeSlot, onEncryptedKeys, onError)
+{
+  var timeCount = Math.round(timeSlot);
+  var keyRequest = this.keyRequests_[timeCount];
+
+  var keyName = new Name(this.namespace_);
+  keyName.append(Encryptor.NAME_COMPONENT_C_KEY);
+  keyName.append(Schedule.toIsoString(Producer.getRoundedTimeSlot_(timeSlot)));
+
+  var cKeyData;
+  var thisProducer = this;
+
+  return this.database_.getContentKeyPromise(timeSlot)
+  .then(function(contentKey) {
+    cKeyData = new Data();
+    cKeyData.setName(keyName);
+    var params = new EncryptParams(EncryptAlgorithmType.RsaOaep);
+    return Encryptor.encryptDataPromise
+      (cKeyData, contentKey, eKeyName, encryptionKey, params);
+  })
+  .then(function() {
+    return SyncPromise.resolve(true);
+  }, function(error) {
+    try {
+      onError(EncryptError.ErrorCode.EncryptionFailure,
+              "encryptData failed: " + error);
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return SyncPromise.resolve(false);
+  })
+  .then(function(success) {
+    if (success) {
+      return thisProducer.keyChain_.signPromise(cKeyData)
+      .then(function() {
+        keyRequest.encryptedKeys.push(cKeyData);
+        thisProducer.updateKeyRequest_(keyRequest, timeCount, onEncryptedKeys);
+        return SyncPromise.resolve(true);
+      });
+    }
+    else
+      return SyncPromise.resolve(false);
+  });
+};
+
+Producer.prototype.getEKeyInfoSize_ = function()
+{
+  // Note: This is really a method to find the key count in any object, but we
+  // don't want to claim that it is a tested and general utility method.
+  var size = 0;
+  for (key in this.eKeyInfo_) {
+    if (this.eKeyInfo_.hasOwnProperty(key))
+      ++size;
+  }
+
+  return size;
+};
+
+// TODO: Move this to be the main representation inside the Exclude object.
+/**
+ * Create a new ExcludeEntry.
+ * @param {Name.Component} component
+ * @param {boolean} anyFollowsComponent
+ */
+Producer.ExcludeEntry = function ExcludeEntry(component, anyFollowsComponent)
+{
+  this.component_ = component;
+  this.anyFollowsComponent_ = anyFollowsComponent;
+};
+
+/**
+ * Create a list of ExcludeEntry from the Exclude object.
+ * @param {Exclude} exclude The Exclude object to read.
+ * @return {Array<ExcludeEntry>} A new array of ExcludeEntry.
+ */
+Producer.getExcludeEntries = function(exclude)
+{
+  var entries = [];
+
+  for (var i = 0; i < exclude.size(); ++i) {
+    if (exclude.get(i) == Exclude.ANY) {
+      if (entries.length == 0)
+        // Add a "beginning ANY".
+        entries.push(new Producer.ExcludeEntry(new Name.Component(), true));
+      else
+        // Set anyFollowsComponent of the final component.
+        entries[entries.length - 1].anyFollowsComponent_ = true;
+    }
+    else
+      entries.push(new Producer.ExcludeEntry(exclude.get(i), false));
+  }
+
+  return entries;
+};
+
+/**
+ * Set the Exclude object from the array of ExcludeEntry.
+ * @param {Exclude} exclude The Exclude object to update.
+ * @param {Array<ExcludeEntry>} entries The array of ExcludeEntry.
+ */
+Producer.setExcludeEntries = function(exclude, entries)
+{
+  exclude.clear();
+
+  for (var i = 0; i < entries.length; ++i) {
+    var entry = entries[i];
+
+    if (i == 0 && entry.component_.getValue().size() == 0 &&
+        entry.anyFollowsComponent_)
+      // This is a "beginning ANY".
+      exclude.appendAny();
+    else {
+      exclude.appendComponent(entry.component_);
+      if (entry.anyFollowsComponent_)
+        exclude.appendAny();
+    }
+  }
+};
+
+/**
+ * Get the latest entry in the array whose component_ is less than or equal to
+ * component.
+ * @param {Array<ExcludeEntry>} entries The array of ExcludeEntry.
+ * @param {Name.Component} component The component to compare.
+ * @return {number} The index of the found entry, or -1 if not found.
+ */
+Producer.findEntryBeforeOrAt = function(entries, component)
+{
+  var i = entries.length - 1;
+  while (i >= 0) {
+    if (entries[i].component_.compare(component) <= 0)
+      break;
+    --i;
+  }
+
+  return i;
+};
+
+/**
+ * Exclude all components in the range beginning at "from".
+ * @param {Exclude} exclude The Exclude object to update.
+ * @param {Name.Component} from The first component in the exclude range.
+ */
+Producer.excludeAfter = function(exclude, from)
+{
+  var entries = Producer.getExcludeEntries(exclude);
+
+  var iNewFrom;
+  var iFoundFrom = Producer.findEntryBeforeOrAt(entries, from);
+  if (iFoundFrom < 0) {
+    // There is no entry before "from" so insert at the beginning.
+    entries.splice(0, 0, new Producer.ExcludeEntry(from, true));
+    iNewFrom = 0;
+  }
+  else {
+    var foundFrom = entries[iFoundFrom];
+
+    if (!foundFrom.anyFollowsComponent_) {
+      if (foundFrom.component_.equals(from)) {
+        // There is already an entry with "from", so just set the "ANY" flag.
+        foundFrom.anyFollowsComponent_ = true;
+        iNewFrom = iFoundFrom;
+      }
+      else {
+        // Insert following the entry before "from".
+        entries.splice(iFoundFrom + 1, 0, new Producer.ExcludeEntry(from, true));
+        iNewFrom = iFoundFrom + 1;
+      }
+    }
+    else
+      // The entry before "from" already has an "ANY" flag, so do nothing.
+      iNewFrom = iFoundFrom;
+  }
+
+  // Remove intermediate entries since they are inside the range.
+  var iRemoveBegin = iNewFrom + 1;
+  var nRemoveNeeded = entries.length - iRemoveBegin;
+  entries.splice(iRemoveBegin, nRemoveNeeded);
+
+  Producer.setExcludeEntries(exclude, entries);
+};
+
+/**
+ * Exclude all components in the range ending at "to".
+ * @param {Exclude} exclude The Exclude object to update.
+ * @param {Name.Component} to The last component in the exclude range.
+ */
+Producer.excludeBefore = function(exclude, to)
+{
+  Producer.excludeRange(exclude, new Name.Component(), to);
+};
+
+/**
+ * Exclude all components in the range beginning at "from" and ending at "to".
+ * @param {Exclude} exclude The Exclude object to update.
+ * @param {Name.Component} from The first component in the exclude range.
+ * @param {Name.Component} to The last component in the exclude range.
+ */
+Producer.excludeRange = function(exclude, from, to)
+{
+  if (from.compare(to) >= 0) {
+    if (from.compare(to) == 0)
+      throw new Error
+        ("excludeRange: from == to. To exclude a single component, sue excludeOne.");
+    else
+      throw new Error
+        ("excludeRange: from must be less than to. Invalid range: [" +
+         from.toEscapedString() + ", " + to.toEscapedString() + "]");
+  }
+
+  var entries = Producer.getExcludeEntries(exclude);
+
+  var iNewFrom;
+  var iFoundFrom = Producer.findEntryBeforeOrAt(entries, from);
+  if (iFoundFrom < 0) {
+    // There is no entry before "from" so insert at the beginning.
+    entries.splice(0, 0, new Producer.ExcludeEntry(from, true));
+    iNewFrom = 0;
+  }
+  else {
+    var foundFrom = entries[iFoundFrom];
+
+    if (!foundFrom.anyFollowsComponent_) {
+      if (foundFrom.component_.equals(from)) {
+        // There is already an entry with "from", so just set the "ANY" flag.
+        foundFrom.anyFollowsComponent_ = true;
+        iNewFrom = iFoundFrom;
+      }
+      else {
+        // Insert following the entry before "from".
+        entries.splice(iFoundFrom + 1, 0, new Producer.ExcludeEntry(from, true));
+        iNewFrom = iFoundFrom + 1;
+      }
+    }
+    else
+      // The entry before "from" already has an "ANY" flag, so do nothing.
+      iNewFrom = iFoundFrom;
+  }
+
+  // We have at least one "from" before "to", so we know this will find an entry.
+  var iFoundTo = Producer.findEntryBeforeOrAt(entries, to);
+  var foundTo = entries[iFoundTo];
+  if (iFoundTo == iNewFrom)
+    // Insert the "to" immediately after the "from".
+    entries.splice(iNewFrom + 1, 0, new Producer.ExcludeEntry(to, false));
+  else {
+    var iRemoveEnd;
+    if (!foundTo.anyFollowsComponent_) {
+      if (foundTo.component_.equals(to))
+        // The "to" entry already exists. Remove up to it.
+        iRemoveEnd = iFoundTo;
+      else {
+        // Insert following the previous entry, which will be removed.
+        entries.splice(iFoundTo + 1, 0, new Producer.ExcludeEntry(to, false));
+        iRemoveEnd = iFoundTo + 1;
+      }
+    }
+    else
+      // "to" follows a component which is already followed by "ANY", meaning
+      // the new range now encompasses it, so remove the component.
+      iRemoveEnd = iFoundTo + 1;
+
+    // Remove intermediate entries since they are inside the range.
+    var iRemoveBegin = iNewFrom + 1;
+    var nRemoveNeeded = iRemoveEnd - iRemoveBegin;
+    entries.splice(iRemoveBegin, nRemoveNeeded);
+  }
+
+  Producer.setExcludeEntries(exclude, entries);
+};
+
+Producer.START_TIME_STAMP_INDEX = -2;
+Producer.END_TIME_STAMP_INDEX = -1;
+Producer.NO_LINK = new Link();
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/repetitive-interval https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Interval = require('./interval.js').Interval;
+
+/**
+ * A RepetitiveInterval is an advanced interval which can repeat and can be used
+ * to find a simple Interval that a time point falls in. Create a
+ * RepetitiveInterval with one of these forms:
+ * RepetitiveInterval() A RepetitiveInterval with one day duration, non-repeating..
+ * RepetitiveInterval(startDate, endDate, intervalStartHour, intervalEndHour, nRepeats, repeatUnit).
+ * RepetitiveInterval(repetitiveInterval).
+ * @param {number} startDate The start date as milliseconds since Jan 1, 1970 UTC.
+ * startDate must be earlier than or same as endDate. Or if repeatUnit is
+ * RepetitiveInterval.RepeatUnit.NONE, then it must equal endDate.
+ * @param {number} endDate The end date as milliseconds since Jan 1, 1970 UTC.
+ * @param {number} intervalStartHour The start hour in the day, from 0 to 23.
+ * intervalStartHour must be less than intervalEndHour.
+ * @param {number} intervalEndHour The end hour in the day from 1 to 24.
+ * @param {number} nRepeats (optional) Repeat the interval nRepeats repetitions,
+ * every unit, until endDate. If ommitted, use 0.
+ * @param {number} repeatUnit (optional) The unit of the repetition, from
+ * RepetitiveInterval.RepeatUnit. If ommitted, use NONE. If this is NONE or
+ * ommitted, then startDate must equal endDate.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var RepetitiveInterval = function RepetitiveInterval
+  (startDate, endDate, intervalStartHour, intervalEndHour, nRepeats, repeatUnit)
+{
+  if (typeof startDate === 'object' && startDate instanceof RepetitiveInterval) {
+    // Make a copy.
+    repetitiveInterval = startDate;
+
+    this.startDate_ = repetitiveInterval.startDate_;
+    this.endDate_ = repetitiveInterval.endDate_;
+    this.intervalStartHour_ = repetitiveInterval.intervalStartHour_;
+    this.intervalEndHour_ = repetitiveInterval.intervalEndHour_;
+    this.nRepeats_ = repetitiveInterval.nRepeats_;
+    this.repeatUnit_ = repetitiveInterval.repeatUnit_;
+  }
+  else if (typeof startDate === 'number') {
+    if (nRepeats == undefined)
+      nRepeats = 0;
+    if (repeatUnit == undefined)
+      repeatUnit = RepetitiveInterval.RepeatUnit.NONE;
+
+    this.startDate_ = RepetitiveInterval.toDateOnlyMilliseconds_(startDate);
+    this.endDate_ = RepetitiveInterval.toDateOnlyMilliseconds_(endDate);
+    this.intervalStartHour_ = Math.round(intervalStartHour);
+    this.intervalEndHour_ = Math.round(intervalEndHour);
+    this.nRepeats_ = Math.round(nRepeats);
+    this.repeatUnit_ = repeatUnit;
+
+    // Validate.
+    if (!(this.intervalStartHour_ < this.intervalEndHour_))
+      throw new Error("ReptitiveInterval: startHour must be less than endHour");
+    if (!(this.startDate_ <= this.endDate_))
+      throw new Error
+        ("ReptitiveInterval: startDate must be earlier than or same as endDate");
+    if (!(this.intervalStartHour_ >= 0))
+      throw new Error("ReptitiveInterval: intervalStartHour must be non-negative");
+    if (!(this.intervalEndHour_ >= 1 && this.intervalEndHour_ <= 24))
+      throw new Error("ReptitiveInterval: intervalEndHour must be from 1 to 24");
+    if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.NONE) {
+      if (!(this.startDate_ == this.endDate_))
+        throw new Error
+          ("ReptitiveInterval: With RepeatUnit.NONE, startDate must equal endDate");
+    }
+  }
+  else {
+    // The default constructor.
+    this.startDate_ = -Number.MAX_VALUE;
+    this.endDate_ = -Number.MAX_VALUE;
+    this.intervalStartHour_ = 0;
+    this.intervalEndHour_ = 24;
+    this.nRepeats_ = 0;
+    this.repeatUnit_ = RepetitiveInterval.RepeatUnit.NONE;
+  }
+};
+
+exports.RepetitiveInterval = RepetitiveInterval;
+
+RepetitiveInterval.RepeatUnit = {
+  NONE:  0,
+  DAY:   1,
+  MONTH: 2,
+  YEAR:  3
+};
+
+/**
+ * Get an interval that covers the time point. If there is no interval
+ * covering the time point, this returns false for isPositive and returns a
+ * negative interval.
+ * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
+ * @return {object} An associative array with fields
+ * (isPositive, interval) where
+ * isPositive is true if the returned interval is
+ * positive or false if negative, and interval is the Interval covering the time
+ * point or a negative interval if not found.
+ */
+RepetitiveInterval.prototype.getInterval = function(timePoint)
+{
+  var isPositive;
+  var startTime;
+  var endTime;
+
+  if (!this.hasIntervalOnDate_(timePoint)) {
+    // There is no interval on the date of timePoint.
+    startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);
+    endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
+      24 * RepetitiveInterval.MILLISECONDS_IN_HOUR;
+    isPositive = false;
+  }
+  else {
+    // There is an interval on the date of timePoint.
+    startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
+      this.intervalStartHour_ * RepetitiveInterval.MILLISECONDS_IN_HOUR;
+    endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
+      this.intervalEndHour_ * RepetitiveInterval.MILLISECONDS_IN_HOUR;
+
+    // check if in the time duration
+    if (timePoint < startTime) {
+      endTime = startTime;
+      startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);
+      isPositive = false;
+    }
+    else if (timePoint > endTime) {
+      startTime = endTime;
+      endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
+        RepetitiveInterval.MILLISECONDS_IN_DAY;
+      isPositive = false;
+    }
+    else
+      isPositive = true;
+  }
+
+  return { isPositive: isPositive, interval: new Interval(startTime, endTime) };
+};
+
+/**
+ * Compare this to the other RepetitiveInterval.
+ * @param {RepetitiveInterval} other The other RepetitiveInterval to compare to.
+ * @return {number} -1 if this is less than the other, 1 if greater and 0 if equal.
+ */
+RepetitiveInterval.prototype.compare = function(other)
+{
+  if (this.startDate_ < other.startDate_)
+    return -1;
+  if (this.startDate_ > other.startDate_)
+    return 1;
+
+  if (this.endDate_ < other.endDate_)
+    return -1;
+  if (this.endDate_ > other.endDate_)
+    return 1;
+
+  if (this.intervalStartHour_ < other.intervalStartHour_)
+    return -1;
+  if (this.intervalStartHour_ > other.intervalStartHour_)
+    return 1;
+
+  if (this.intervalEndHour_ < other.intervalEndHour_)
+    return -1;
+  if (this.intervalEndHour_ > other.intervalEndHour_)
+    return 1;
+
+  if (this.nRepeats_ < other.nRepeats_)
+    return -1;
+  if (this.nRepeats_ > other.nRepeats_)
+    return 1;
+
+  if (this.repeatUnit_ < other.repeatUnit_)
+    return -1;
+  if (this.repeatUnit_ > other.repeatUnit_)
+    return 1;
+
+  return 0;
+};
+
+/**
+ * Get the start date.
+ * @return {number} The start date as milliseconds since Jan 1, 1970 UTC.
+ */
+RepetitiveInterval.prototype.getStartDate = function()
+{
+  return this.startDate_;
+};
+
+/**
+ * Get the end date.
+ * @return {number} The end date as milliseconds since Jan 1, 1970 UTC.
+ */
+RepetitiveInterval.prototype.getEndDate = function()
+{
+  return this.endDate_;
+};
+
+/**
+ * Get the interval start hour.
+ * @return {number} The interval start hour.
+ */
+RepetitiveInterval.prototype.getIntervalStartHour = function()
+{
+  return this.intervalStartHour_;
+}
+
+/**
+ * Get the interval end hour.
+ * @return {number} The interval end hour.
+ */
+RepetitiveInterval.prototype.getIntervalEndHour = function()
+{
+  return this.intervalEndHour_;
+};
+
+/**
+ * Get the number of repeats.
+ * @return {number} The number of repeats.
+ */
+RepetitiveInterval.prototype.getNRepeats = function()
+{
+  return this.nRepeats_;
+};
+
+/**
+ * Get the repeat unit.
+ * @return {number} The repeat unit, from RepetitiveInterval.RepeatUnit.
+ */
+RepetitiveInterval.prototype.getRepeatUnit = function()
+{
+  return this.repeatUnit_;
+};
+
+/**
+ * Check if the date of the time point is in any interval.
+ * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
+ * @return {boolean} True if the date of the time point is in any interval.
+ */
+RepetitiveInterval.prototype.hasIntervalOnDate_ = function(timePoint)
+{
+  var timePointDateMilliseconds = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);
+
+  if (timePointDateMilliseconds < this.startDate_ ||
+      timePointDateMilliseconds > this.endDate_)
+    return false;
+
+  if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.NONE)
+    return true;
+  else if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.DAY) {
+    var durationDays = (timePointDateMilliseconds - this.startDate_) /
+                        RepetitiveInterval.MILLISECONDS_IN_DAY;
+    if (durationDays % this.nRepeats_ == 0)
+      return true;
+  }
+  else {
+    var timePointDate = new Date(timePointDateMilliseconds);
+    var startDate = new Date(this.startDate_);
+
+    if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.MONTH &&
+             timePointDate.getUTCDate() == startDate.getUTCDate()) {
+      var yearDifference =
+        timePointDate.getUTCFullYear() - startDate.getUTCFullYear();
+      var monthDifference = 12 * yearDifference +
+        timePointDate.getUTCMonth() - startDate.getUTCMonth();
+      if (monthDifference % this.nRepeats_ == 0)
+        return true;
+    }
+    else if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.YEAR &&
+             timePointDate.getUTCDate() == startDate.getUTCDate() &&
+             timePointDate.getUTCMonth() == startDate.getUTCMonth()) {
+      var difference = timePointDate.getUTCFullYear() - startDate.getUTCFullYear();
+      if (difference % this.nRepeats_ == 0)
+        return true;
+    }
+  }
+
+  return false;
+};
+
+/**
+ * Return a time point on the beginning of the date (without hours, minutes, etc.)
+ * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
+ * @return {number} A time point as milliseconds since Jan 1, 1970 UTC.
+ */
+RepetitiveInterval.toDateOnlyMilliseconds_ = function(timePoint)
+{
+  var result = Math.round(timePoint);
+  result -= result % RepetitiveInterval.MILLISECONDS_IN_DAY;
+  return result;
+};
+
+RepetitiveInterval.MILLISECONDS_IN_HOUR = 3600 * 1000;
+RepetitiveInterval.MILLISECONDS_IN_DAY = 24 * 3600 * 1000;
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/schedule https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Interval = require('./interval.js').Interval; /** @ignore */
+var RepetitiveInterval = require('./repetitive-interval.js').RepetitiveInterval; /** @ignore */
+var Tlv = require('../encoding/tlv/tlv.js').Tlv; /** @ignore */
+var TlvEncoder = require('../encoding/tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
+var TlvDecoder = require('../encoding/tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * Schedule is used to manage the times when a member can access data using two
+ * sets of RepetitiveInterval as follows. whiteIntervalList is an ordered
+ * set for the times a member is allowed to access to data, and
+ * blackIntervalList is for the times a member is not allowed.
+ * Create a Schedule with one of these forms:
+ * Schedule() A Schedule with empty whiteIntervalList and blackIntervalList.
+ * Schedule(schedule). A copy of the given schedule.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var Schedule = function Schedule(value)
+{
+  if (typeof value === 'object' && value instanceof Schedule) {
+    // Make a copy.
+    var schedule = value;
+
+    // RepetitiveInterval is immutable, so we don't need to make a deep copy.
+    this.whiteIntervalList_ = schedule.whiteIntervalList_.slice(0);
+    this.blackIntervalList_ = schedule.blackIntervalList_.slice(0);
+  }
+  else {
+    // The default constructor.
+    this.whiteIntervalList_ = [];
+    this.blackIntervalList_ = [];
+  }
+};
+
+exports.Schedule = Schedule;
+
+/**
+ * Add the repetitiveInterval to the whiteIntervalList.
+ * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to add.
+ * If the list already contains the same RepetitiveInterval, this does nothing.
+ * @return {Schedule} This Schedule so you can chain calls to add.
+ */
+Schedule.prototype.addWhiteInterval = function(repetitiveInterval)
+{
+  // RepetitiveInterval is immutable, so we don't need to make a copy.
+  Schedule.sortedSetAdd_(this.whiteIntervalList_, repetitiveInterval);
+  return this;
+};
+
+/**
+ * Add the repetitiveInterval to the blackIntervalList.
+ * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to add.
+ * If the list already contains the same RepetitiveInterval, this does nothing.
+ * @return {Schedule} This Schedule so you can chain calls to add.
+ */
+Schedule.prototype.addBlackInterval = function(repetitiveInterval)
+{
+  // RepetitiveInterval is immutable, so we don't need to make a copy.
+  Schedule.sortedSetAdd_(this.blackIntervalList_, repetitiveInterval);
+  return this;
+};
+
+/**
+ * Get the interval that covers the time stamp. This iterates over the two
+ * repetitive interval sets and find the shortest interval that allows a group
+ * member to access the data. If there is no interval covering the time stamp,
+ * this returns false for isPositive and a negative interval.
+ * @param {number} timeStamp The time stamp as milliseconds since Jan 1, 1970 UTC.
+ * @return {object} An associative array with fields
+ * (isPositive, interval) where
+ * isPositive is true if the returned interval is positive or false if negative,
+ * and interval is the Interval covering the time stamp, or a negative interval
+ * if not found.
+ */
+Schedule.prototype.getCoveringInterval = function(timeStamp)
+{
+  var blackPositiveResult = new Interval(true);
+  var whitePositiveResult = new Interval(true);
+
+  var blackNegativeResult = new Interval();
+  var whiteNegativeResult = new Interval();
+
+  // Get the black result.
+  Schedule.calculateIntervalResult_
+    (this.blackIntervalList_, timeStamp, blackPositiveResult, blackNegativeResult);
+
+  // If the black positive result is not empty, then isPositive must be false.
+  if (!blackPositiveResult.isEmpty())
+    return { isPositive: false, interval: blackPositiveResult };
+
+  // Get the whiteResult.
+  Schedule.calculateIntervalResult_
+    (this.whiteIntervalList_, timeStamp, whitePositiveResult, whiteNegativeResult);
+
+  if (whitePositiveResult.isEmpty() && !whiteNegativeResult.isValid()) {
+    // There is no white interval covering the time stamp.
+    // Return false and a 24-hour interval.
+    var timeStampDateOnly =
+      RepetitiveInterval.toDateOnlyMilliseconds_(timeStamp);
+    return { isPositive: false,
+             interval:  new Interval
+               (timeStampDateOnly,
+                timeStampDateOnly + RepetitiveInterval.MILLISECONDS_IN_DAY) };
+  }
+
+  if (!whitePositiveResult.isEmpty()) {
+    // There is white interval covering the time stamp.
+    // Return true and calculate the intersection.
+    if (blackNegativeResult.isValid())
+      return { isPositive: true,
+               interval: whitePositiveResult.intersectWith(blackNegativeResult) };
+    else
+      return  { isPositive: true, interval: whitePositiveResult };
+  }
+  else
+    // There is no white interval covering the time stamp.
+    // Return false.
+    return { isPositive: false, interval: whiteNegativeResult };
+};
+
+/**
+ * Encode this Schedule.
+ * @return {Blob} The encoded buffer.
+ */
+Schedule.prototype.wireEncode = function()
+{
+  // For now, don't use WireFormat and hardcode to use TLV since the encoding
+  // doesn't go out over the wire, only into the local SQL database.
+  var encoder = new TlvEncoder(256);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  // Encode the blackIntervalList.
+  var saveLengthForList = encoder.getLength();
+  for (var i = this.blackIntervalList_.length - 1; i >= 0; i--)
+    Schedule.encodeRepetitiveInterval_(this.blackIntervalList_[i], encoder);
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_BlackIntervalList, encoder.getLength() - saveLengthForList);
+
+  // Encode the whiteIntervalList.
+  saveLengthForList = encoder.getLength();
+  for (var i = this.whiteIntervalList_.length - 1; i >= 0; i--)
+    Schedule.encodeRepetitiveInterval_(this.whiteIntervalList_[i], encoder);
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_WhiteIntervalList, encoder.getLength() - saveLengthForList);
+
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_Schedule, encoder.getLength() - saveLength);
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode the input and update this Schedule object.
+ * @param {Blob|Buffer} input The input buffer to decode. For Buffer, this reads
+ * from position() to limit(), but does not change the position.
+ * @throws DecodingException For invalid encoding.
+ */
+Schedule.prototype.wireDecode = function(input)
+{
+  // If input is a blob, get its buf().
+  var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
+    input.buf() : input;
+
+  // For now, don't use WireFormat and hardcode to use TLV since the encoding
+  // doesn't go out over the wire, only into the local SQL database.
+  var decoder = new TlvDecoder(decodeBuffer);
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_Schedule);
+
+  // Decode the whiteIntervalList.
+  this.whiteIntervalList_ = [];
+  var listEndOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_WhiteIntervalList);
+  while (decoder.getOffset() < listEndOffset)
+    Schedule.sortedSetAdd_
+      (this.whiteIntervalList_, Schedule.decodeRepetitiveInterval_(decoder));
+  decoder.finishNestedTlvs(listEndOffset);
+
+  // Decode the blackIntervalList.
+  this.blackIntervalList_ = [];
+  listEndOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_BlackIntervalList);
+  while (decoder.getOffset() < listEndOffset)
+    Schedule.sortedSetAdd_
+      (this.blackIntervalList_, Schedule.decodeRepetitiveInterval_(decoder));
+  decoder.finishNestedTlvs(listEndOffset);
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * Insert element into the list, sorted using element.compare(). If it is a
+ * duplicate of an existing list element, don't add it.
+ */
+Schedule.sortedSetAdd_ = function(list, element)
+{
+  // Find the index of the first element where it is not less than element.
+  var i = 0;
+  while (i < list.length) {
+    var comparison = list[i].compare(element);
+    if (comparison == 0)
+      // Don't add a duplicate.
+      return;
+    if (!(comparison < 0))
+      break;
+
+    ++i;
+  }
+
+  list.splice(i, 0, element);
+};
+
+/**
+ * Encode the RepetitiveInterval as NDN-TLV to the encoder.
+ * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to encode.
+ * @param {TlvEncoder} encoder The TlvEncoder to receive the encoding.
+ */
+Schedule.encodeRepetitiveInterval_ = function(repetitiveInterval, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  // The RepeatUnit enum has the same values as the encoding.
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_RepeatUnit, repetitiveInterval.getRepeatUnit());
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_NRepeats, repetitiveInterval.getNRepeats());
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_IntervalEndHour, repetitiveInterval.getIntervalEndHour());
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_IntervalStartHour, repetitiveInterval.getIntervalStartHour());
+  // Use Blob to convert the string to UTF8 encoding.
+  encoder.writeBlobTlv(Tlv.Encrypt_EndDate,
+    new Blob(Schedule.toIsoString(repetitiveInterval.getEndDate())).buf());
+  encoder.writeBlobTlv(Tlv.Encrypt_StartDate,
+    new Blob(Schedule.toIsoString(repetitiveInterval.getStartDate())).buf());
+
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_RepetitiveInterval, encoder.getLength() - saveLength);
+};
+
+/**
+ * Decode the input as an NDN-TLV RepetitiveInterval.
+ * @param {TlvDecoder} decoder The decoder with the input to decode.
+ * @return {RepetitiveInterval} A new RepetitiveInterval with the decoded result.
+ */
+Schedule.decodeRepetitiveInterval_ = function(decoder)
+{
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_RepetitiveInterval);
+
+  // Use Blob to convert UTF8 to a string.
+  var startDate = Schedule.fromIsoString
+    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_StartDate), true).toString());
+  var endDate = Schedule.fromIsoString
+    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_EndDate), true).toString());
+  var startHour = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalStartHour);
+  var endHour = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalEndHour);
+  var nRepeats = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_NRepeats);
+
+  // The RepeatUnit enum has the same values as the encoding.
+  var repeatUnit = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_RepeatUnit);
+
+  decoder.finishNestedTlvs(endOffset);
+  return new RepetitiveInterval
+    (startDate, endDate, startHour, endHour, nRepeats, repeatUnit);
+};
+
+/**
+ * A helper function to calculate black interval results or white interval
+ * results.
+ * @param {Array} list The set of RepetitiveInterval, which can be the white
+ * list or the black list.
+ * @param {number} timeStamp The time stamp as milliseconds since Jan 1, 1970 UTC.
+ * @param {Interval} positiveResult The positive result which is updated.
+ * @param {Interval} negativeResult The negative result which is updated.
+ */
+Schedule.calculateIntervalResult_ = function
+  (list, timeStamp, positiveResult, negativeResult)
+{
+  for (var i = 0; i < list.length; ++i) {
+    var element = list[i];
+
+    var result = element.getInterval(timeStamp);
+    var tempInterval = result.interval;
+    if (result.isPositive == true)
+      positiveResult.unionWith(tempInterval);
+    else {
+      if (!negativeResult.isValid())
+        negativeResult.set(tempInterval);
+      else
+        negativeResult.intersectWith(tempInterval);
+    }
+  }
+};
+
+/**
+ * Convert a UNIX timestamp to ISO time representation with the "T" in the middle.
+ * @param {number} msSince1970 Timestamp as milliseconds since Jan 1, 1970 UTC.
+ * @return {string} The string representation.
+ */
+Schedule.toIsoString = function(msSince1970)
+{
+  var utcTime = new Date(Math.round(msSince1970));
+  return utcTime.getUTCFullYear() +
+         Schedule.to2DigitString(utcTime.getUTCMonth() + 1) +
+         Schedule.to2DigitString(utcTime.getUTCDate()) +
+         "T" +
+         Schedule.to2DigitString(utcTime.getUTCHours()) +
+         Schedule.to2DigitString(utcTime.getUTCMinutes()) +
+         Schedule.to2DigitString(utcTime.getUTCSeconds());
+};
+
+/**
+ * A private method to zero pad an integer to 2 digits.
+ * @param {number} x The number to pad.  Assume it is a non-negative integer.
+ * @return {string} The padded string.
+ */
+Schedule.to2DigitString = function(x)
+{
+  var result = x.toString();
+  return result.length === 1 ? "0" + result : result;
+};
+
+/**
+ * Convert an ISO time representation with the "T" in the middle to a UNIX
+ * timestamp.
+ * @param {string} timeString The ISO time representation.
+ * @return {number} The timestamp as milliseconds since Jan 1, 1970 UTC.
+ */
+Schedule.fromIsoString = function(timeString)
+{
+  if (timeString.length != 15 || timeString.substr(8, 1) != 'T')
+    throw new Error("fromIsoString: Format is not the expected yyyymmddThhmmss");
+
+  return Date.UTC
+    (parseInt(timeString.substr(0, 4)),
+     parseInt(timeString.substr(4, 2) - 1),
+     parseInt(timeString.substr(6, 2)),
+     parseInt(timeString.substr(9, 2)),
+     parseInt(timeString.substr(11, 2)),
+     parseInt(timeString.substr(13, 2)));
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Don't require modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbConsumerDb extends ConsumerDb to implement the storage of decryption
+ * keys for the consumer using the browser's IndexedDB service.
+ * Create an IndexedDbConsumerDb to use the given IndexedDB database name.
+ * @param {string} databaseName IndexedDB database name.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var IndexedDbConsumerDb = function IndexedDbConsumerDb(databaseName)
+{
+  ConsumerDb.call(this);
+
+  this.database = new Dexie(databaseName);
+  this.database.version(1).stores({
+    // "keyName" is the key name URI // string
+    //   (Note: In SQLite3, the key name is the TLV encoded bytes, but we can't
+    //   index on a byte array in IndexedDb.)
+    // "key" is the key bytes // Uint8Array
+    decryptionKeys: "keyName"
+  });
+  this.database.open();
+};
+
+IndexedDbConsumerDb.prototype = new ConsumerDb();
+IndexedDbConsumerDb.prototype.name = "IndexedDbConsumerDb";
+
+/**
+ * Get the key with keyName from the database.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a Blob with the encoded key (or an
+ * isNull Blob if cannot find the key with keyName), or that is
+ * rejected with ConsumerDb.Error for a database error.
+ */
+IndexedDbConsumerDb.prototype.getKeyPromise = function(keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.getKeyPromise is only supported for async")));
+
+  return this.database.decryptionKeys.get(keyName.toUri())
+  .then(function(decryptionKeysEntry) {
+    if (decryptionKeysEntry)
+      return Promise.resolve(new Blob(decryptionKeysEntry.key));
+    else
+      return Promise.resolve(new Blob());
+  })
+  .catch(function(ex) {
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.getKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Add the key with keyName and keyBlob to the database.
+ * @param {Name} keyName The key name.
+ * @param {Blob} keyBlob The encoded key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key is added, or that
+ * is rejected with ConsumerDb.Error if a key with the same keyName already
+ * exists, or other database error.
+ */
+IndexedDbConsumerDb.prototype.addKeyPromise = function(keyName, keyBlob, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.addKeyPromise is only supported for async")));
+
+  // Add rejects if the primary key already exists.
+  return this.database.decryptionKeys.add
+    ({ keyName: keyName.toUri(), key: keyBlob.buf() })
+  .catch(function(ex) {
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.addKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Delete the key with keyName from the database. If there is no key with
+ * keyName, do nothing.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key is deleted (or there
+ * is no such key), or that is rejected with ConsumerDb.Error for a database
+ * error.
+ */
+IndexedDbConsumerDb.prototype.deleteKeyPromise = function(keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.deleteKeyPromise is only supported for async")));
+
+  return this.database.decryptionKeys.delete(keyName.toUri())
+  .catch(function(ex) {
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.deleteKeyPromise: Error: " + ex)));
+  });
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Don't require modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbGroupManagerDb extends GroupManagerDb to implement the storage of
+ * data used by the GroupManager using the browser's IndexedDB service.
+ * Create an IndexedDbGroupManagerDb to use the given IndexedDB database name.
+ * @param {string} databaseName IndexedDB database name.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var IndexedDbGroupManagerDb = function IndexedDbGroupManagerDb(databaseName)
+{
+  GroupManagerDb.call(this);
+
+  this.database = new Dexie(databaseName);
+  this.database.version(1).stores({
+    // "scheduleId" is the schedule ID, auto incremented // number
+    // "scheduleName" is the schedule name, unique // string
+    // "schedule" is the TLV-encoded schedule // Uint8Array
+    schedules: "++scheduleId, &scheduleName",
+
+    // "memberNameUri" is the member name URI // string
+    //   (Note: In SQLite3, the member name index is the TLV encoded bytes, but
+    //   we can't index on a byte array in IndexedDb.)
+    //   (Note: The SQLite3 table also has an auto-incremented member ID primary
+    //   key, but is not used so we omit it to simplify.)
+    // "memberName" is the TLV-encoded member name (same as memberNameUri // Uint8Array
+    // "scheduleId" is the schedule ID, linked to the schedules table // number
+    //   (Note: The SQLite3 table has a foreign key to the schedules table with
+    //   cascade update and delete, but we have to handle it manually.)
+    // "keyName" is the TLV-encoded key name // Uint8Array
+    // "publicKey" is the encoded key bytes // Uint8Array
+    members: "memberNameUri, scheduleId"
+  });
+  this.database.open();
+};
+
+IndexedDbGroupManagerDb.prototype = new GroupManagerDb();
+IndexedDbGroupManagerDb.prototype.name = "IndexedDbGroupManagerDb";
+
+////////////////////////////////////////////////////// Schedule management.
+
+/**
+ * Check if there is a schedule with the given name.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns true if there is a schedule (else
+ * false), or that is rejected with GroupManagerDb.Error for a database error.
+ */
+IndexedDbGroupManagerDb.prototype.hasSchedulePromise = function(name, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.hasSchedulePromise is only supported for async")));
+
+  return this.getScheduleIdPromise_(name)
+  .then(function(scheduleId) {
+    return Promise.resolve(scheduleId != -1);
+  });
+};
+
+/**
+ * List all the names of the schedules.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a new array of string with the names
+ * of all schedules, or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.listAllScheduleNamesPromise = function(useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.listAllScheduleNamesPromise is only supported for async")));
+
+  var list = [];
+  return this.database.schedules.each(function(entry) {
+    list.push(entry.scheduleName);
+  })
+  .then(function() {
+    return Promise.resolve(list);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.listAllScheduleNamesPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Get a schedule with the given name.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a new Schedule object, or that is
+ * rejected with GroupManagerDb.Error if the schedule does not exist or other
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.getSchedulePromise = function(name, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getSchedulePromise is only supported for async")));
+
+  var thisManager = this;
+  // Use getScheduleIdPromise_ to handle the search on the non-primary key.
+  return this.getScheduleIdPromise_(name)
+  .then(function(scheduleId) {
+    if (scheduleId != -1) {
+      return thisManager.database.schedules.get(scheduleId)
+      .then(function(entry) {
+        // We expect entry to be found, and don't expect an error decoding.
+        var schedule = new Schedule();
+        schedule.wireDecode(new Blob(entry.schedule, false));
+        return Promise.resolve(schedule);
+      })
+      .catch(function(ex) {
+        return Promise.reject(new GroupManagerDb.Error(new Error
+          ("IndexedDbGroupManagerDb.getSchedulePromise: Error: " + ex)));
+      });
+    }
+    else
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.getSchedulePromise: Cannot get the result from the database")));
+  });
+};
+
+/**
+ * For each member using the given schedule, get the name and public key DER
+ * of the member's key.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a new array of object (where
+ * "keyName" is the Name of the public key and "publicKey" is the Blob of the
+ * public key DER), or that is rejected with GroupManagerDb.Error for a database
+ * error. Note that the member's identity name is keyName.getPrefix(-1). If the
+ * schedule name is not found, the list is empty.
+ */
+IndexedDbGroupManagerDb.prototype.getScheduleMembersPromise = function
+  (name, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getScheduleMembersPromise is only supported for async")));
+
+  var list = [];
+  var thisManager = this;
+  // There is only one matching schedule ID, so we can just look it up instead
+  // of doing a more complicated join.
+  return this.getScheduleIdPromise_(name)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      // Return the empty list.
+      return Promise.resolve(list);
+
+    var onEntryError = null;
+    return thisManager.database.members.where("scheduleId").equals(scheduleId)
+    .each(function(entry) {
+      try {
+        var keyName = new Name();
+        keyName.wireDecode(new Blob(entry.keyName, false), TlvWireFormat.get());
+
+        list.push({ keyName: keyName, publicKey: new Blob(entry.publicKey, false) });
+      } catch (ex) {
+        // We don't expect this to happen.
+        onEntryError = new GroupManagerDb.Error(new Error
+          ("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error decoding name: " + ex));
+      }
+    })
+    .then(function() {
+      if (onEntryError)
+        // We got an error decoding.
+        return Promise.reject(onEntryError);
+      else
+        return Promise.resolve(list);
+    }, function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error: " + ex)));
+    });
+  });
+};
+
+/**
+ * Add a schedule with the given name.
+ * @param {string} name The name of the schedule. The name cannot be empty.
+ * @param {Schedule} schedule The Schedule to add.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the schedule is added, or that
+ * is rejected with GroupManagerDb.Error if a schedule with the same name
+ * already exists, if the name is empty, or other database error.
+ */
+IndexedDbGroupManagerDb.prototype.addSchedulePromise = function
+  (name, schedule, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.addSchedulePromise is only supported for async")));
+
+  if (name.length == 0)
+    return Promise.reject(new GroupManagerDb.Error
+      ("IndexedDbGroupManagerDb.addSchedulePromise: The schedule name cannot be empty"));
+
+  // Add rejects if the primary key already exists.
+  return this.database.schedules.add
+    ({ scheduleName: name, schedule: schedule.wireEncode().buf() })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.addContentKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Delete the schedule with the given name. Also delete members which use this
+ * schedule. If there is no schedule with the name, then do nothing.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the schedule is deleted (or
+ * there is no such schedule), or that is rejected with GroupManagerDb.Error for
+ * a database error.
+ */
+IndexedDbGroupManagerDb.prototype.deleteSchedulePromise = function
+  (name, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.deleteSchedulePromise is only supported for async")));
+
+  var scheduleId;
+  var thisManager = this;
+  return this.getScheduleIdPromise_(name)
+  .then(function(localScheduleId) {
+    scheduleId = localScheduleId;
+
+    // Get the members which use this schedule.
+    return thisManager.database.members.where("scheduleId").equals(scheduleId).toArray();
+  })
+  .then(function(membersEntries) {
+    // Delete the members.
+    var promises = membersEntries.map(function(entry) {
+      return thisManager.database.members.delete(entry.memberNameUri);
+    });
+    return Promise.all(promises);
+  })
+  .then(function() {
+    // Now delete the schedule.
+    return thisManager.database.schedules.delete(scheduleId);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.deleteSchedulePromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Rename a schedule with oldName to newName.
+ * @param {string} oldName The name of the schedule to be renamed.
+ * @param {string} newName The new name of the schedule. The name cannot be empty.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the schedule is renamed, or
+ * that is rejected with GroupManagerDb.Error if a schedule with newName already
+ * exists, if the schedule with oldName does not exist, if newName is empty, or
+ * other database error.
+ */
+IndexedDbGroupManagerDb.prototype.renameSchedulePromise = function
+  (oldName, newName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.renameSchedulePromise is only supported for async")));
+
+  if (newName.length == 0)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.renameSchedule: The schedule newName cannot be empty")));
+
+  var thisManager = this;
+  return this.getScheduleIdPromise_(oldName)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.renameSchedule: The schedule oldName does not exist")));
+
+    return thisManager.database.schedules.update
+      (scheduleId, { scheduleName: newName })
+    .catch(function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.renameSchedulePromise: Error: " + ex)));
+    });
+  });
+};
+
+/**
+ * Update the schedule with name and replace the old object with the given
+ * schedule. Otherwise, if no schedule with name exists, a new schedule
+ * with name and the given schedule will be added to database.
+ * @param {string} name The name of the schedule. The name cannot be empty.
+ * @param {Schedule} schedule The Schedule to update or add.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the schedule is updated, or
+ * that is rejected with GroupManagerDb.Error if the name is empty, or other
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.updateSchedulePromise = function
+  (name, schedule, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.updateSchedulePromise is only supported for async")));
+
+  var thisManager = this;
+  return this.getScheduleIdPromise_(name)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      return thisManager.addSchedulePromise(name, schedule);
+
+    return thisManager.database.schedules.update
+      (scheduleId, { schedule: schedule.wireEncode().buf() })
+    .catch(function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.updateSchedulePromise: Error: " + ex)));
+    });
+  });
+};
+
+////////////////////////////////////////////////////// Member management.
+
+/**
+ * Check if there is a member with the given identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns true if there is a member (else
+ * false), or that is rejected with GroupManagerDb.Error for a database error.
+ */
+IndexedDbGroupManagerDb.prototype.hasMemberPromise = function(identity, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.hasMemberPromise is only supported for async")));
+
+  return this.database.members.get(identity.toUri())
+  .then(function(entry) {
+    return Promise.resolve(entry != undefined);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.hasMemberPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * List all the members.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a new array of Name with the names
+ * of all members, or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.listAllMembersPromise = function(useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.listAllMembersPromise is only supported for async")));
+
+  var list = [];
+  var onEntryError = null;
+  return this.database.members.each(function(entry) {
+    try {
+      var identity = new Name();
+      identity.wireDecode(new Blob(entry.memberName, false), TlvWireFormat.get());
+      list.push(identity);
+    } catch (ex) {
+      // We don't expect this to happen.
+      onEntryError = new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.listAllMembersPromise: Error decoding name: " + ex));
+    }
+  })
+  .then(function() {
+    if (onEntryError)
+      // We got an error decoding.
+      return Promise.reject(onEntryError);
+    else
+      return Promise.resolve(list);
+  }, function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.listAllMembersPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Get the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns the string schedule name, or that is
+ * rejected with GroupManagerDb.Error if there's no member with the given
+ * identity name in the database, or other database error.
+ */
+IndexedDbGroupManagerDb.prototype.getMemberSchedulePromise = function
+  (identity, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getMemberSchedulePromise is only supported for async")));
+
+  var thisManager = this;
+  return this.database.members.get(identity.toUri())
+  .then(function(membersEntry) {
+    if (!membersEntry)
+      throw new Error("The member identity name does not exist in the database");
+
+    return thisManager.database.schedules.get(membersEntry.scheduleId);
+  })
+  .then(function(schedulesEntry) {
+    if (!schedulesEntry)
+      throw new Error
+        ("The schedule ID for the member identity name does not exist in the database");
+
+    return Promise.resolve(schedulesEntry.scheduleName);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: " + ex)));
+  });
+};
+
+/**
+ * Add a new member with the given key named keyName into a schedule named
+ * scheduleName. The member's identity name is keyName.getPrefix(-1).
+ * @param {string} scheduleName The schedule name.
+ * @param {Name} keyName The name of the key.
+ * @param {Blob} key A Blob of the public key DER.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the member is added, or that
+ * is rejected with GroupManagerDb.Error if there's no schedule named
+ * scheduleName, if the member's identity name already exists, or other database
+ * error.
+ */
+IndexedDbGroupManagerDb.prototype.addMemberPromise = function
+  (scheduleName, keyName, key, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.addMemberPromise is only supported for async")));
+
+  var thisManager = this;
+  return this.getScheduleIdPromise_(scheduleName)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.addMemberPromise: The schedule does not exist")));
+
+    // Needs to be changed in the future.
+    var memberName = keyName.getPrefix(-1);
+
+    // Add rejects if the primary key already exists.
+    return thisManager.database.members.add
+      ({ memberNameUri: memberName.toUri(),
+         memberName: memberName.wireEncode(TlvWireFormat.get()).buf(),
+         scheduleId: scheduleId,
+         keyName: keyName.wireEncode(TlvWireFormat.get()).buf(),
+         publicKey: key.buf() })
+    .catch(function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.addMemberPromise: Error: " + ex)));
+    });
+  });
+};
+
+/**
+ * Change the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {string} scheduleName The new schedule name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the member is updated, or that
+ * is rejected with GroupManagerDb.Error if there's no member with the given
+ * identity name in the database, or there's no schedule named scheduleName, or
+ * other database error.
+ */
+IndexedDbGroupManagerDb.prototype.updateMemberSchedulePromise = function
+  (identity, scheduleName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.updateMemberSchedulePromise is only supported for async")));
+
+  var thisManager = this;
+  return this.getScheduleIdPromise_(scheduleName)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.updateMemberSchedulePromise: The schedule does not exist")));
+
+    return thisManager.database.members.update
+      (identity.toUri(), { scheduleId: scheduleId })
+    .catch(function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.updateMemberSchedulePromise: Error: " + ex)));
+    });
+  });
+};
+
+/**
+ * Delete a member with the given identity name. If there is no member with
+ * the identity name, then do nothing.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the member is deleted (or
+ * there is no such member), or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.deleteMemberPromise = function
+  (identity, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.deleteMemberPromise is only supported for async")));
+
+  return this.database.members.delete(identity.toUri())
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.deleteMemberPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Get the ID for the schedule.
+ * @param {string} name The schedule name.
+ * @return {Promise} A promise that returns the ID (or -1 if not found), or that
+ * is rejected with GroupManagerDb.Error for a database error.
+ */
+IndexedDbGroupManagerDb.prototype.getScheduleIdPromise_ = function(name)
+{
+  // The scheduleName is not the primary key, so use 'where' instead of 'get'.
+  var id = -1;
+  return this.database.schedules.where("scheduleName").equals(name)
+  .each(function(entry) {
+    id = entry.scheduleId;
+  })
+  .then(function() {
+    return Promise.resolve(id);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: " + ex)));
+  });
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Don't require modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbProducerDb extends ProducerDb to implement storage of keys for the
+ * producer using the browser's IndexedDB service. It contains one table that
+ * maps time slots (to the nearest hour) to the content key created for that
+ * time slot.
+ * Create an IndexedDbProducerDb to use the given IndexedDB database name.
+ * @param {string} databaseName IndexedDB database name.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var IndexedDbProducerDb = function IndexedDbProducerDb(databaseName)
+{
+  ProducerDb.call(this);
+
+  this.database = new Dexie(databaseName);
+  this.database.version(1).stores({
+    // "timeSlot" is the hour-based time slot as hours since Jan 1, 1970 UTC. // number
+    // "key" is the encoded key // Uint8Array
+    contentKeys: "timeSlot"
+  });
+  this.database.open();
+};
+
+IndexedDbProducerDb.prototype = new ProducerDb();
+IndexedDbProducerDb.prototype.name = "IndexedDbProducerDb";
+
+/**
+ * Check if a content key exists for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns true if there is a content key for
+ * timeSlot (else false), or that is rejected with ProducerDb.Error for a
+ * database error.
+ */
+IndexedDbProducerDb.prototype.hasContentKeyPromise = function(timeSlot, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.hasContentKeyPromise is only supported for async")));
+
+  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
+
+  return this.database.contentKeys.get(fixedTimeSlot)
+  .then(function(contentKeysEntry) {
+    return Promise.resolve(contentKeysEntry != undefined);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.hasContentKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Get the content key for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a Blob with the encoded key, or that
+ * is rejected with ProducerDb.Error if there is no key covering timeSlot, or
+ * other database error
+ */
+IndexedDbProducerDb.prototype.getContentKeyPromise = function(timeSlot, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.getContentKeyPromise is only supported for async")));
+
+  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
+
+  return this.database.contentKeys.get(fixedTimeSlot)
+  .then(function(contentKeysEntry) {
+    if (contentKeysEntry)
+      return Promise.resolve(new Blob(contentKeysEntry.key));
+    else
+      return Promise.reject(new ProducerDb.Error(new Error
+        ("IndexedDbProducerDb.getContentKeyPromise: Cannot get the key from the database")));
+  }, function(ex) {
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.getContentKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Add key as the content key for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {Blob} key The encoded key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key is added, or that
+ * is rejected with ProducerDb.Error if a key for the same hour already exists
+ * in the database, or other database error.
+ */
+IndexedDbProducerDb.prototype.addContentKeyPromise = function
+  (timeSlot, key, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.addContentKeyPromise is only supported for async")));
+
+  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
+
+  // Add rejects if the primary key already exists.
+  return this.database.contentKeys.add
+    ({ timeSlot: fixedTimeSlot, key: key.buf() })
+  .catch(function(ex) {
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.addContentKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Delete the content key for the hour covering timeSlot. If there is no key for
+ * the time slot, do nothing.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key is deleted (or there
+ * is no such key), or that is rejected with ProducerDb.Error for a database
+ * error.
+ */
+IndexedDbProducerDb.prototype.deleteContentKeyPromise = function(timeSlot, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.deleteContentKeyPromise is only supported for async")));
+
+  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
+
+  return this.database.contentKeys.delete(fixedTimeSlot)
+  .catch(function(ex) {
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.deleteContentKeyPromise: Error: " + ex)));
+  });
+};
+/**
+ * This class represents the digest tree for chrono-sync2013.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Zhehao Wang, based on Jeff T.'s implementation in ndn-cpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DigestTree = require('./digest-tree.js').DigestTree; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var MemoryContentCache = require('../util/memory-content-cache.js').MemoryContentCache; /** @ignore */
+var SyncStateProto = require('./sync-state.js').SyncStateProto; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon;
+
+/**
+ * ChronoSync2013 implements the NDN ChronoSync protocol as described in the
+ * 2013 paper "Let's ChronoSync: Decentralized Dataset State Synchronization in
+ * Named Data Networking". http://named-data.net/publications/chronosync .
+ * @note The support for ChronoSync is experimental and the API is not finalized.
+ * See the API docs for more detail at
+ * http://named-data.net/doc/ndn-ccl-api/chrono-sync2013.html .
+ *
+ * Create a new ChronoSync2013 to communicate using the given face. Initialize
+ * the digest log with a digest of "00" and and empty content. Register the
+ * applicationBroadcastPrefix to receive interests for sync state messages and
+ * express an interest for the initial root digest "00".
+ * @param {function} onReceivedSyncState When ChronoSync receives a sync state message,
+ * this calls onReceivedSyncState(syncStates, isRecovery) where syncStates is the
+ * list of SyncState messages and isRecovery is true if this is the initial
+ * list of SyncState messages or from a recovery interest. (For example, if
+ * isRecovery is true, a chat application would not want to re-display all
+ * the associated chat messages.) The callback should send interests to fetch
+ * the application data for the sequence numbers in the sync state.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onInitialized This calls onInitialized() when the first sync data
+ * is received (or the interest times out because there are no other
+ * publishers yet).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {Name} applicationDataPrefix The prefix used by this application instance
+ * for application data. For example, "/my/local/prefix/ndnchat4/0K4wChff2v".
+ * This is used when sending a sync message for a new sequence number.
+ * In the sync message, this uses applicationDataPrefix.toUri().
+ * @param {Name} applicationBroadcastPrefix The broadcast name prefix including the
+ * application name. For example, "/ndn/broadcast/ChronoChat-0.3/ndnchat1".
+ * This makes a copy of the name.
+ * @param {int} sessionNo The session number used with the applicationDataPrefix in
+ * sync state messages.
+ * @param {Face} face The Face for calling registerPrefix and expressInterest. The
+ * Face object must remain valid for the life of this ChronoSync2013 object.
+ * @param {KeyChain} keyChain To sign a data packet containing a sync state message, this
+ * calls keyChain.sign(data, certificateName).
+ * @param {Name} certificateName The certificate name of the key to use for signing a
+ * data packet containing a sync state message.
+ * @param {Milliseconds} syncLifetime The interest lifetime in milliseconds for sending
+ * sync interests.
+ * @param {function} onRegisterFailed If failed to register the prefix to receive
+ * interests for the applicationBroadcastPrefix, this calls
+ * onRegisterFailed(applicationBroadcastPrefix).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @constructor
+ */
+var ChronoSync2013 = function ChronoSync2013
+  (onReceivedSyncState, onInitialized, applicationDataPrefix,
+   applicationBroadcastPrefix, sessionNo, face, keyChain, certificateName,
+   syncLifetime, onRegisterFailed)
+{
+  // assigning function pointers
+  this.onReceivedSyncState = onReceivedSyncState;
+  this.onInitialized = onInitialized;
+  this.applicationDataPrefixUri = applicationDataPrefix.toUri();
+  this.applicationBroadcastPrefix = applicationBroadcastPrefix;
+  this.session = sessionNo;
+  this.face = face;
+  this.keyChain = keyChain;
+  this.certificateName = certificateName;
+  this.sync_lifetime = syncLifetime;
+  this.usrseq = -1;
+
+  this.digest_tree = new DigestTree();
+  this.contentCache = new MemoryContentCache(face);
+
+  this.digest_log = new Array();
+  this.digest_log.push(new ChronoSync2013.DigestLogEntry("00",[]));
+
+  this.contentCache.registerPrefix
+    (this.applicationBroadcastPrefix, onRegisterFailed,
+     this.onInterest.bind(this));
+  this.enabled = true;
+
+  var interest = new Interest(this.applicationBroadcastPrefix);
+  interest.getName().append("00");
+
+  interest.setInterestLifetimeMilliseconds(1000);
+
+  var Sync;
+  try {
+    // Using protobuf.min.js in the browser.
+    Sync = dcodeIO.ProtoBuf.newBuilder().import(SyncStateProto).build("Sync");
+  }
+  catch (ex) {
+    // Using protobufjs in node.
+    Sync = require("protobufjs").newBuilder().import(SyncStateProto).build("Sync");
+  }
+  this.SyncStateMsg = Sync.SyncStateMsg;
+  this.SyncState = Sync.SyncState;
+
+  this.face.expressInterest(interest, this.onData.bind(this), this.initialTimeOut.bind(this));
+};
+
+exports.ChronoSync2013 = ChronoSync2013;
+
+ChronoSync2013.prototype.getProducerSequenceNo = function(dataPrefix, sessionNo)
+{
+  var index = this.digest_tree.find(dataPrefix, sessionNo);
+  if (index < 0)
+    return -1;
+  else
+    return this.digest_tree.get(index).getSequenceNo();
+};
+
+/**
+ * Increment the sequence number, create a sync message with the new sequence number,
+ * and publish a data packet where the name is applicationBroadcastPrefix + root
+ * digest of current digest tree. Then add the sync message to digest tree and digest
+ * log which creates a new root digest. Finally, express an interest for the next sync
+ * update with the name applicationBroadcastPrefix + the new root digest.
+ * After this, application should publish the content for the new sequence number.
+ * Get the new sequence number with getSequenceNo().
+ */
+ChronoSync2013.prototype.publishNextSequenceNo = function()
+{
+  this.usrseq ++;
+  var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
+                                 type:'UPDATE',
+                                 seqno:{
+                                   seq:this.usrseq,
+                                   session:this.session
+                                  }
+                                })];
+  var content_t = new this.SyncStateMsg({ss:content});
+  this.broadcastSyncState(this.digest_tree.getRoot(), content_t);
+
+  if (!this.update(content))
+    console.log("Warning: ChronoSync: update did not create a new digest log entry");
+
+  var interest = new Interest(this.applicationBroadcastPrefix);
+  interest.getName().append(this.digest_tree.getRoot());
+  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+
+  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
+};
+
+/**
+ * Get the sequence number of the latest data published by this application instance.
+ * @return {int} the sequence number
+ */
+ChronoSync2013.prototype.getSequenceNo = function()
+{
+  return this.usrseq;
+};
+
+// DigestLogEntry class
+
+ChronoSync2013.DigestLogEntry = function ChronoSync2013DisgestLogEntry(digest, data)
+{
+  this.digest = digest;
+  this.data = data;
+};
+
+ChronoSync2013.DigestLogEntry.prototype.getDigest = function()
+{
+  return this.digest;
+};
+
+ChronoSync2013.DigestLogEntry.prototype.getData = function()
+{
+  return this.data;
+};
+
+/**
+ * Unregister callbacks so that this does not respond to interests anymore.
+ * If you will dispose this ChronoSync2013 object while your application is
+ * still running, you should call shutdown() first.  After calling this, you
+ * should not call publishNextSequenceNo() again since the behavior will be
+ * undefined.
+ */
+ChronoSync2013.prototype.shutdown = function()
+{
+  this.enabled = false;
+  this.contentCache.unregisterAll();
+};
+
+// SyncState class
+/**
+ * A SyncState holds the values of a sync state message which is passed to the
+ * onReceivedSyncState callback which was given to the ChronoSyn2013
+ * constructor. Note: this has the same info as the Protobuf class
+ * Sync::SyncState, but we make a separate class so that we don't need the
+ * Protobuf definition in the ChronoSync API.
+ */
+ChronoSync2013.SyncState = function ChronoSync2013SyncState(dataPrefixUri, sessionNo, sequenceNo)
+{
+  this.dataPrefixUri_ = dataPrefixUri;
+  this.sessionNo_ = sessionNo;
+  this.sequenceNo_ = sequenceNo;
+};
+
+/**
+ * Get the application data prefix for this sync state message.
+ * @return The application data prefix as a Name URI string.
+ */
+ChronoSync2013.SyncState.prototype.getDataPrefix = function()
+{
+  return this.dataPrefixUri_;
+}
+
+/**
+ * Get the session number associated with the application data prefix for
+ * this sync state message.
+ * @return The session number.
+ */
+ChronoSync2013.SyncState.prototype.getSessionNo = function()
+{
+  return this.sessionNo_;
+}
+
+/**
+ * Get the sequence number for this sync state message.
+ * @return The sequence number.
+ */
+ChronoSync2013.SyncState.prototype.getSequenceNo = function()
+{
+  return this.sequenceNo_;
+}
+
+// Private methods for ChronoSync2013 class,
+/**
+ * Make a data packet with the syncMessage and with name applicationBroadcastPrefix_ + digest.
+ * Sign and send.
+ * @param {string} The root digest as a hex string for the data packet name.
+ * @param {SyncStateMsg} The syncMessage updates the digest tree state with the given digest.
+ */
+ChronoSync2013.prototype.broadcastSyncState = function(digest, syncMessage)
+{
+  var array = new Uint8Array(syncMessage.toArrayBuffer());
+  var data = new Data(this.applicationBroadcastPrefix);
+  data.getName().append(digest);
+  data.setContent(new Blob(array, false));
+  var thisChronoSync = this;
+  this.keyChain.sign(data, this.certificateName, function() {
+    thisChronoSync.contentCache.add(data);
+  });
+};
+
+/**
+ * Update the digest tree with the messages in content. If the digest tree root is not in
+ * the digest log, also add a log entry with the content.
+ * @param {SyncStates[]} The sync state messages
+ * @return {bool} True if added a digest log entry (because the updated digest tree root
+ * was not in the log), false if didn't add a log entry.
+ */
+ // Whatever's received by ondata, is pushed into digest log as its data directly
+ChronoSync2013.prototype.update = function(content)
+{
+  for (var i = 0; i < content.length; i++) {
+    if (content[i].type == 0) {
+      if (this.digest_tree.update(content[i].name, content[i].seqno.session, content[i].seqno.seq)) {
+        if (this.applicationDataPrefixUri == content[i].name)
+          this.usrseq = content[i].seqno.seq;
+      }
+    }
+  }
+
+  if (this.logfind(this.digest_tree.getRoot()) == -1) {
+    var newlog = new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(), content);
+    this.digest_log.push(newlog);
+    return true;
+  }
+  else
+    return false;
+};
+
+ChronoSync2013.prototype.logfind = function(digest)
+{
+  for (var i = 0; i < this.digest_log.length; i++) {
+    if(digest == this.digest_log[i].digest)
+      return i;
+  }
+  return -1;
+};
+
+/**
+ * Process the sync interest from the applicationBroadcastPrefix. If we can't
+ * satisfy the interest, add it to the pending interest table in
+ * this.contentCache so that a future call to contentCacheAdd may satisfy it.
+ */
+ChronoSync2013.prototype.onInterest = function
+  (prefix, interest, face, interestFilterId, filter)
+{
+  if (!this.enabled)
+    // Ignore callbacks after the application calls shutdown().
+    return;
+
+  //search if the digest is already exist in the digest log
+
+  var syncdigest = interest.getName().get(this.applicationBroadcastPrefix.size()).toEscapedString();
+  if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2) {
+    syncdigest = interest.getName().get(this.applicationBroadcastPrefix.size() + 1).toEscapedString();
+  }
+  if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2 || syncdigest == "00") {
+    this.processRecoveryInst(interest, syncdigest, face);
+  }
+  else {
+    this.contentCache.storePendingInterest(interest, face);
+
+    if (syncdigest != this.digest_tree.getRoot()) {
+      var index = this.logfind(syncdigest);
+      var content = [];
+      if(index == -1) {
+        var self = this;
+        // Are we sure that using a "/local/timeout" interest is the best future call approach?
+        var timeout = new Interest(new Name("/local/timeout"));
+        timeout.setInterestLifetimeMilliseconds(2000);
+        this.face.expressInterest
+          (timeout, this.dummyOnData,
+           this.judgeRecovery.bind(this, timeout, syncdigest, face));
+      }
+      else {
+        //common interest processing
+        this.processSyncInst(index, syncdigest, face);
+      }
+    }
+  }
+};
+
+/**
+ * Process sync/recovery data.
+ * @param {Interest}
+ * @param {Data}
+ */
+ChronoSync2013.prototype.onData = function(interest, co)
+{
+  if (!this.enabled)
+    // Ignore callbacks after the application calls shutdown().
+    return;
+
+  var arr = new Uint8Array(co.getContent().size());
+  arr.set(co.getContent().buf());
+  var content_t = this.SyncStateMsg.decode(arr.buffer);
+  var content = content_t.ss;
+
+  var isRecovery = false;
+
+  if (this.digest_tree.getRoot() == "00") {
+    isRecovery = true;
+    this.initialOndata(content);
+  }
+  else {
+    this.update(content);
+    if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2)
+      // Assume this is a recovery interest.
+      isRecovery = true;
+    else
+      isRecovery = false;
+  }
+
+  var syncStates = [];
+
+  for (var i = 0; i < content.length; i++) {
+    if (content[i].type == 0) {
+      syncStates.push(new ChronoSync2013.SyncState
+        (content[i].name, content[i].seqno.session, content[i].seqno.seq));
+    }
+  }
+
+  // Instead of using Protobuf, use our own definition of SyncStates to pass to onReceivedSyncState.
+  try {
+    this.onReceivedSyncState(syncStates, isRecovery);
+  } catch (ex) {
+    console.log("Error in onReceivedSyncState: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+
+  var n = new Name(this.applicationBroadcastPrefix);
+  n.append(this.digest_tree.getRoot());
+
+  var interest = new Interest(n);
+  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+
+  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
+};
+
+/**
+ * Interest variable not actually in use here
+ */
+ChronoSync2013.prototype.initialTimeOut = function(interest)
+{
+  if (!this.enabled)
+    // Ignore callbacks after the application calls shutdown().
+    return;
+
+  console.log("no other people");
+
+  this.usrseq++;
+  try {
+    this.onInitialized();
+  } catch (ex) {
+    console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+  var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
+                                 type:'UPDATE',
+                                 seqno: {
+                                   seq:this.usrseq,
+                                   session:this.session
+                                 }
+                               })];
+  this.update(content);
+  var n = new Name(this.applicationBroadcastPrefix);
+  n.append(this.digest_tree.getRoot());
+  var retryInterest = new Interest(n);
+  retryInterest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+
+  this.face.expressInterest(retryInterest, this.onData.bind(this), this.syncTimeout.bind(this));
+};
+
+ChronoSync2013.prototype.processRecoveryInst = function(interest, syncdigest, face)
+{
+  if (this.logfind(syncdigest) != -1) {
+    var content = [];
+
+    for(var i = 0; i < this.digest_tree.digestnode.length; i++) {
+      content[i] = new this.SyncState({ name:this.digest_tree.digestnode[i].getDataPrefix(),
+                                   type:'UPDATE',
+                                   seqno:{
+                                     seq:this.digest_tree.digestnode[i].getSequenceNo(),
+                                     session:this.digest_tree.digestnode[i].getSessionNo()
+                                    }
+                                 });
+    }
+
+    if (content.length != 0) {
+      var content_t = new this.SyncStateMsg({ss:content});
+      var str = new Uint8Array(content_t.toArrayBuffer());
+      var co = new Data(interest.getName());
+      co.setContent(new Blob(str, false));
+      if (interest.getName().get(-1).toEscapedString() == "00")
+        // Limit the lifetime of replies to interest for "00" since they can be different.
+        co.getMetaInfo().setFreshnessPeriod(1000);
+
+      this.keyChain.sign(co, this.certificateName, function() {
+        try {
+          face.putData(co);
+        } catch (e) {
+          console.log(e.toString());
+        }
+      });
+    }
+  }
+};
+
+/**
+ * Common interest processing, using digest log to find the difference after syncdigest_t
+ * @return True if sent a data packet to satisfy the interest.
+ */
+ChronoSync2013.prototype.processSyncInst = function(index, syncdigest_t, face)
+{
+  var content = [];
+  var data_name = [];
+  var data_seq = [];
+  var data_ses = [];
+
+  for (var j = index + 1; j < this.digest_log.length; j++) {
+    var temp = this.digest_log[j].getData();
+    for (var i = 0 ; i < temp.length ; i++) {
+      if (temp[i].type != 0) {
+        continue;
+      }
+      if (this.digest_tree.find(temp[i].name, temp[i].seqno.session) != -1) {
+        var n = data_name.indexOf(temp[i].name);
+        if (n == -1) {
+          data_name.push(temp[i].name);
+          data_seq.push(temp[i].seqno.seq);
+          data_ses.push(temp[i].seqno.session);
+        }
+        else {
+          data_seq[n] = temp[i].seqno.seq;
+          data_ses[n] = temp[i].seqno.session;
+        }
+      }
+    }
+  }
+
+  for(var i = 0; i < data_name.length; i++) {
+    content[i] = new this.SyncState({ name:data_name[i],
+                                 type:'UPDATE',
+                                 seqno: {
+                                   seq:data_seq[i],
+                                   session:data_ses[i]
+                                 }
+                               });
+  }
+  if (content.length != 0) {
+    var content_t = new this.SyncStateMsg({ss:content});
+    var str = new Uint8Array(content_t.toArrayBuffer());
+    var n = new Name(this.prefix)
+    n.append(this.chatroom).append(syncdigest_t);
+
+    var co = new Data(n);
+    co.setContent(new Blob(str, false));
+    this.keyChain.sign(co, this.certificateName, function() {
+      try {
+        face.putData(co);
+      }
+      catch (e) {
+        console.log(e.toString());
+      }
+    });
+  }
+};
+
+/**
+ * Send recovery interset.
+ * @param {string} syncdigest_t
+ */
+ChronoSync2013.prototype.sendRecovery = function(syncdigest_t)
+{
+  var n = new Name(this.applicationBroadcastPrefix);
+  n.append("recovery").append(syncdigest_t);
+
+  var interest = new Interest(n);
+
+  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+
+  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
+};
+
+/**
+ * This is called by onInterest after a timeout to check if a recovery is needed.
+ * This method has an interest argument because we use it as the onTimeout for
+ * Face.expressInterest.
+ * @param {Interest}
+ * @param {string}
+ * @param {Face}
+ */
+ChronoSync2013.prototype.judgeRecovery = function(interest, syncdigest_t, face)
+{
+  //console.log("*** judgeRecovery interest " + interest.getName().toUri() + " times out. Digest: " + syncdigest_t + " ***");
+  var index = this.logfind(syncdigest_t);
+  if (index != -1) {
+    if (syncdigest_t != this.digest_tree.root)
+      this.processSyncInst(index, syncdigest_t, face);
+  }
+  else
+    this.sendRecovery(syncdigest_t);
+};
+
+ChronoSync2013.prototype.syncTimeout = function(interest)
+{
+  if (!this.enabled)
+    // Ignore callbacks after the application calls shutdown().
+    return;
+
+  var component = interest.getName().get(4).toEscapedString();
+  if (component == this.digest_tree.root) {
+    var n = new Name(interest.getName());
+    var newInterest = new Interest(n);
+
+    interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+    this.face.expressInterest(newInterest, this.onData.bind(this), this.syncTimeout.bind(this));
+  }
+};
+
+ChronoSync2013.prototype.initialOndata = function(content)
+{
+  this.update(content);
+
+  var digest_t = this.digest_tree.getRoot();
+  for (var i = 0; i < content.length; i++) {
+    if (content[i].name == this.applicationDataPrefixUri && content[i].seqno.session == this.session) {
+      //if the user was an old comer, after add the static log he need to increase his seqno by 1
+      var content_t = [new this.SyncState({ name:this.applicationDataPrefixUri,
+                                       type:'UPDATE',
+                                       seqno: {
+                                         seq:content[i].seqno.seq + 1,
+                                         session:this.session
+                                       }
+                                     })];
+      if (this.update(content_t)) {
+        var newlog = new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(), content_t);
+        this.digest_log.push(newlog);
+        try {
+          this.onInitialized();
+        } catch (ex) {
+          console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+    }
+  }
+
+  var content_t;
+  if (this.usrseq >= 0) {
+    //send the data packet with new seqno back
+    content_t = new this.SyncState({ name:this.applicationDataPrefixUri,
+                                   type:'UPDATE',
+                                   seqno: {
+                                     seq:this.usrseq,
+                                     session:this.session
+                                   }
+                                 });
+  }
+  else
+    content_t = new this.SyncState({ name:this.applicationDataPrefixUri,
+                                   type:'UPDATE',
+                                   seqno: {
+                                     seq:0,
+                                     session:this.session
+                                   }
+                                 });
+  var content_tt = new this.SyncStateMsg({ss:content_t});
+  this.broadcastSyncState(digest_t, content_tt);
+
+  if (this.digest_tree.find(this.applicationDataPrefixUri, this.session) == -1) {
+    //the user haven't put himself in the digest tree
+    this.usrseq++;
+    var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
+                                   type:'UPDATE',
+                                   seqno: {
+                                     seq:this.usrseq,
+                                     session:this.session
+                                   }
+                                 })];
+    if (this.update(content)) {
+      try {
+        this.onInitialized();
+      } catch (ex) {
+        console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+  }
+};
+
+ChronoSync2013.prototype.dummyOnData = function(interest, data)
+{
+  console.log("*** dummyOnData called. ***");
+};/**
+ * This class represents the digest tree for chrono-sync2013.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Zhehao Wang, based on Jeff T.'s implementation in ndn-cpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../crypto.js');
+
+/**
+ * @constructor
+ */
+var DigestTree = function DigestTree()
+{
+  this.root = "00";
+  this.digestnode = [];
+};
+
+exports.DigestTree = DigestTree;
+
+// The meaning of a session is explained here:
+// http://named-data.net/doc/ndn-ccl-api/chrono-sync2013.html
+// DigestTree.Node works with seqno_seq and seqno_session, without protobuf definition,
+DigestTree.Node = function DigestTreeNode(dataPrefix, seqno_session, seqno_seq)
+{
+  // In this context, this should mean DigestTree.Node instead
+  this.dataPrefix = dataPrefix;
+  this.seqno_session = seqno_session;
+  this.seqno_seq = seqno_seq;
+
+  this.recomputeDigest();
+};
+
+DigestTree.Node.prototype.getDataPrefix = function()
+{
+  return this.dataPrefix;
+};
+
+DigestTree.Node.prototype.getSessionNo = function()
+{
+  return this.seqno_session;
+};
+
+DigestTree.Node.prototype.getSequenceNo = function()
+{
+  return this.seqno_seq;
+};
+
+DigestTree.Node.prototype.getDigest = function()
+{
+  return this.digest;
+};
+
+DigestTree.Node.prototype.setSequenceNo = function(sequenceNo)
+{
+  this.seqno_seq = sequenceNo;
+  this.recomputeDigest();
+};
+
+// Using Node.JS buffer, as documented here http://nodejs.org/api/buffer.html.
+DigestTree.Node.prototype.Int32ToBuffer = function(value) {
+  var result = new Buffer(4);
+  for (var i = 0; i < 4; i++) {
+    result[i] = value % 256;
+    value = Math.floor(value / 256);
+  }
+  return result;
+}
+
+DigestTree.Node.prototype.recomputeDigest = function()
+{
+  var seqHash = Crypto.createHash('sha256');
+
+  seqHash.update(this.Int32ToBuffer(this.seqno_session));
+  seqHash.update(this.Int32ToBuffer(this.seqno_seq));
+
+  var digest_seq = seqHash.digest();
+
+  var nameHash = Crypto.createHash('sha256');
+  nameHash.update(this.dataPrefix);
+  var digest_name = nameHash.digest();
+
+  var hash = Crypto.createHash('sha256');
+  hash.update(digest_name);
+  hash.update(digest_seq);
+
+  this.digest = hash.digest('hex');
+};
+
+// Do the work of string and then sequence number compare
+DigestTree.Node.Compare = function(node1, node2)
+{
+  if (node1.dataPrefix != node2.dataPrefix)
+    return node1.dataPrefix < node2.dataPrefix;
+  return node1.seqno_session < node2.seqno_session;
+};
+
+/**
+ * Update the digest tree and recompute the root digest. If the combination of dataPrefix
+ * and sessionNo already exists in the tree then update its sequenceNo (only if the given
+ * sequenceNo is newer), otherwise add a new node.
+ * @param {string} The name prefix.
+ * @param {int} sessionNo The session number.
+ * @param {int} sequenceNo The sequence number.
+ * @return True if the digest tree is updated, false if not
+ */
+DigestTree.prototype.update = function(dataPrefix, sessionNo, sequenceNo)
+{
+  var n_index = this.find(dataPrefix, sessionNo);
+  if (n_index >= 0) {
+    if (this.digestnode[n_index].getSequenceNo() < sequenceNo)
+      this.digestnode[n_index].setSequenceNo(sequenceNo);
+    else
+      return false;
+  }
+  else {
+    var temp = new DigestTree.Node(dataPrefix, sessionNo, sequenceNo);
+    this.digestnode.push(temp);
+    this.digestnode.sort(this.sortNodes);
+  }
+  this.recomputeRoot();
+  return true;
+};
+
+// Need to confirm this sort works with the insertion in ndn-cpp.
+DigestTree.prototype.sortNodes = function()
+{
+  var temp;
+  for (var i = this.digestnode.length; i > 0; i--) {
+    for (var j = 0; j < i - 1; j++) {
+      if (this.digestnode[j].getDataPrefix() > this.digestnode[j + 1].getDataPrefix()) {
+        temp = this.digestnode[j];
+        this.digestnode[j] = this.digestnode[j + 1];
+        this.digestnode[j + 1] = temp;
+      }
+    }
+  }
+};
+
+DigestTree.prototype.sortNodes = function (node1, node2)
+{
+  if (node1.getDataPrefix() == node2.getDataPrefix() &&
+     node1.getSessionNo() == node2.getSessionNo())
+    return 0;
+
+  if ((node1.getDataPrefix() > node2.getDataPrefix()) ||
+     ((node1.getDataPrefix() == node2.getDataPrefix()) &&
+     (node1.getSessionNo() >node2.getSessionNo())))
+    return 1;
+  else
+    return -1;
+}
+
+DigestTree.prototype.find = function(dataPrefix, sessionNo)
+{
+  for (var i = 0; i < this.digestnode.length; ++i) {
+    if (this.digestnode[i].getDataPrefix() == dataPrefix &&
+        this.digestnode[i].getSessionNo() == sessionNo)
+      return i;
+  }
+  return -1;
+};
+
+DigestTree.prototype.size = function()
+{
+  return this.digestnode.size();
+};
+
+// Not really used
+DigestTree.prototype.get = function(i)
+{
+  return this.digestnode[i];
+};
+
+DigestTree.prototype.getRoot = function()
+{
+  return this.root;
+};
+
+DigestTree.prototype.recomputeRoot = function()
+{
+  var md = Crypto.createHash('sha256');
+  // The result of updateHex is related with the sequence of participants,
+  // I don't think that should be the case.
+  for (var i = 0; i < this.digestnode.length; i++) {
+    md.update(new Buffer(this.digestnode[i].digest, 'hex'));
+  }
+  this.root = md.digest('hex');
+};
+// Just define the SyncStateProto object. We do a Protobuf import dynamically
+// when we need it so that protobufjs is optional.
+var SyncStateProto = {
+    "package": "Sync",
+    "messages": [
+        {
+            "name": "SyncState",
+            "fields": [
+                {
+                    "rule": "required",
+                    "type": "string",
+                    "name": "name",
+                    "id": 1,
+                    "options": {}
+                },
+                {
+                    "rule": "required",
+                    "type": "ActionType",
+                    "name": "type",
+                    "id": 2,
+                    "options": {}
+                },
+                {
+                    "rule": "optional",
+                    "type": "SeqNo",
+                    "name": "seqno",
+                    "id": 3,
+                    "options": {}
+                }
+            ],
+            "enums": [
+                {
+                    "name": "ActionType",
+                    "values": [
+                        {
+                            "name": "UPDATE",
+                            "id": 0
+                        },
+                        {
+                            "name": "DELETE",
+                            "id": 1
+                        },
+                        {
+                            "name": "OTHER",
+                            "id": 2
+                        }
+                    ],
+                    "options": {}
+                }
+            ],
+            "messages": [
+                {
+                    "name": "SeqNo",
+                    "fields": [
+                        {
+                            "rule": "required",
+                            "type": "uint32",
+                            "name": "seq",
+                            "id": 1,
+                            "options": {}
+                        },
+                        {
+                            "rule": "required",
+                            "type": "uint32",
+                            "name": "session",
+                            "id": 2,
+                            "options": {}
+                        }
+                    ],
+                    "enums": [],
+                    "messages": [],
+                    "options": {}
+                }
+            ],
+            "options": {}
+        },
+        {
+            "name": "SyncStateMsg",
+            "fields": [
+                {
+                    "rule": "repeated",
+                    "type": "SyncState",
+                    "name": "ss",
+                    "id": 1,
+                    "options": {}
+                }
+            ],
+            "enums": [],
+            "messages": [],
+            "options": {}
+        }
+    ],
+    "enums": [],
+    "imports": [],
+    "options": {}
+};
+
+exports.SyncStateProto = SyncStateProto;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../crypto.js'); /** @ignore */
+var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
+var TlvEncoder = require('../encoding/tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
+var Blob = require('./blob.js').Blob;
+
+/**
+ * A CommandInterestGenerator keeps track of a timestamp and generates command
+ * interests according to the NFD Signed Command Interests protocol:
+ * http://redmine.named-data.net/projects/nfd/wiki/Command_Interests
+ *
+ * Create a new CommandInterestGenerator and initialize the timestamp to now.
+ * @constructor
+ */
+var CommandInterestGenerator = function CommandInterestGenerator()
+{
+  this.lastTimestamp = Math.round(new Date().getTime());
+};
+
+exports.CommandInterestGenerator = CommandInterestGenerator;
+
+/**
+ * Append a timestamp component and a random value component to interest's name.
+ * This ensures that the timestamp is greater than the timestamp used in the
+ * previous call. Then use keyChain to sign the interest which appends a
+ * SignatureInfo component and a component with the signature bits. If the
+ * interest lifetime is not set, this sets it.
+ * @param {Interest} interest The interest whose name is append with components.
+ * @param {KeyChain} keyChain The KeyChain for calling sign.
+ * @param {Name} certificateName The certificate name of the key to use for
+ * signing.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the SignatureInfo and to encode interest name for signing. If omitted, use
+ * WireFormat.getDefaultWireFormat().
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some crypto/database libraries only use a callback, so onComplete is
+ * required to use these.)
+ */
+CommandInterestGenerator.prototype.generate = function
+  (interest, keyChain, certificateName, wireFormat, onComplete)
+{
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ?
+    WireFormat.getDefaultWireFormat() : wireFormat;
+
+  var timestamp = Math.round(new Date().getTime());
+  while (timestamp <= this.lastTimestamp)
+    timestamp += 1.0;
+
+  // The timestamp is encoded as a TLV nonNegativeInteger.
+  var encoder = new TlvEncoder(8);
+  encoder.writeNonNegativeInteger(timestamp);
+  interest.getName().append(new Blob(encoder.getOutput(), false));
+
+  // The random value is a TLV nonNegativeInteger too, but we know it is 8
+  // bytes, so we don't need to call the nonNegativeInteger encoder.
+  interest.getName().append(new Blob(Crypto.randomBytes(8), false));
+
+  // Update the timestamp before calling async sign.
+  this.lastTimestamp = timestamp;
+
+  keyChain.sign(interest, certificateName, wireFormat, function() {
+    if (interest.getInterestLifetimeMilliseconds() == null ||
+        interest.getInterestLifetimeMilliseconds() < 0)
+      // The caller has not set the interest lifetime, so set it here.
+      interest.setInterestLifetimeMilliseconds(1000.0);
+
+    if (onComplete)
+      onComplete();
+  });
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * An InterestFilterTable is an internal class to hold a list of entries with
+ * an interest Filter and its OnInterestCallback.
+ * @constructor
+ */
+var InterestFilterTable = function InterestFilterTable()
+{
+  this.table_ = []; // of Entry
+};
+
+exports.InterestFilterTable = InterestFilterTable;
+
+/**
+ * InterestFilterTable.Entry holds an interestFilterId, an InterestFilter and
+ * the OnInterestCallback with its related Face.
+ * Create a new Entry with the given values.
+ * @param {number} interestFilterId The ID from getNextEntryId().
+ * @param {InterestFilter} filter The InterestFilter for this entry.
+ * @param {function} onInterest The callback to call.
+ * @param {Face} face The face on which was called registerPrefix or
+ * setInterestFilter which is passed to the onInterest callback.
+ * @constructor
+ */
+InterestFilterTable.Entry = function InterestFilterTableEntry
+  (interestFilterId, filter, onInterest, face)
+{
+  this.interestFilterId_ = interestFilterId;
+  this.filter_ = filter;
+  this.onInterest_ = onInterest;
+  this.face_ = face;
+};
+
+/**
+ * Get the interestFilterId given to the constructor.
+ * @return {number} The interestFilterId.
+ */
+InterestFilterTable.Entry.prototype.getInterestFilterId = function()
+{
+  return this.interestFilterId_;
+};
+
+/**
+ * Get the InterestFilter given to the constructor.
+ * @return {InterestFilter} The InterestFilter.
+ */
+InterestFilterTable.Entry.prototype.getFilter = function()
+{
+  return this.filter_;
+};
+
+/**
+ * Get the onInterest callback given to the constructor.
+ * @return {function} The onInterest callback.
+ */
+InterestFilterTable.Entry.prototype.getOnInterest = function()
+{
+  return this.onInterest_;
+};
+
+/**
+ * Get the Face given to the constructor.
+ * @return {Face} The Face.
+ */
+InterestFilterTable.Entry.prototype.getFace = function()
+{
+  return this.face_;
+};
+
+/**
+ * Add a new entry to the table.
+ * @param {number} interestFilterId The ID from Node.getNextEntryId().
+ * @param {InterestFilter} filter The InterestFilter for this entry.
+ * @param {function} onInterest The callback to call.
+ * @param {Face} face The face on which was called registerPrefix or
+ * setInterestFilter which is passed to the onInterest callback.
+ */
+InterestFilterTable.prototype.setInterestFilter = function
+  (interestFilterId, filter, onInterest, face)
+{
+  this.table_.push(new InterestFilterTable.Entry
+    (interestFilterId, filter, onInterest, face));
+};
+
+/**
+ * Find all entries from the interest filter table where the interest conforms
+ * to the entry's filter, and add to the matchedFilters list.
+ * @param {Interest} interest The interest which may match the filter in
+ * multiple entries.
+ * @param {Array<InterestFilterTable.Entry>} matchedFilters Add each matching
+ * InterestFilterTable.Entry from the interest filter table.  The caller should
+ * pass in an empty array.
+ */
+InterestFilterTable.prototype.getMatchedFilters = function
+  (interest, matchedFilters)
+{
+  for (var i = 0; i < this.table_.length; ++i) {
+    var entry = this.table_[i];
+    if (entry.getFilter().doesMatch(interest.getName()))
+      matchedFilters.push(entry);
+  }
+};
+
+/**
+ * Remove the interest filter entry which has the interestFilterId from the
+ * interest filter table. This does not affect another interest filter with a
+ * different interestFilterId, even if it has the same prefix name. If there is
+ * no entry with the interestFilterId, do nothing.
+ * @param {number} interestFilterId The ID returned from setInterestFilter.
+ */
+InterestFilterTable.prototype.unsetInterestFilter = function(interestFilterId)
+{
+  // Go backwards through the list so we can erase entries.
+  // Remove all entries even though interestFilterId should be unique.
+  var count = 0;
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    if (this.table_[i].getInterestFilterId() == interestFilterId) {
+      ++count;
+      this.table_.splice(i, 1);
+    }
+  }
+
+  if (count === 0)
+    if (LOG > 0) console.log
+      ("unsetInterestFilter: Didn't find interestFilterId " + interestFilterId);
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * A PendingInterestTable is an internal class to hold a list of pending
+ * interests with their callbacks.
+ * @constructor
+ */
+var PendingInterestTable = function PendingInterestTable()
+{
+  this.table_ = []; // of Entry
+  this.removeRequests_ = []; // of number
+};
+
+exports.PendingInterestTable = PendingInterestTable;
+
+/**
+ * PendingInterestTable.Entry holds the callbacks and other fields for an entry
+ * in the pending interest table.
+ * Create a new Entry with the given fields. Note: You should not call this
+ * directly but call PendingInterestTable.add.
+ * @constructor
+ */
+PendingInterestTable.Entry = function PendingInterestTableEntry
+  (pendingInterestId, interest, onData, onTimeout, onNetworkNack)
+{
+  this.pendingInterestId_ = pendingInterestId;
+  this.interest_ = interest;
+  this.onData_ = onData;
+  this.onTimeout_ = onTimeout;
+  this.onNetworkNack_ = onNetworkNack;
+  this.timerId_ = -1;
+};
+
+/**
+ * Get the pendingInterestId given to the constructor.
+ * @return {number} The pendingInterestId.
+ */
+PendingInterestTable.Entry.prototype.getPendingInterestId = function()
+{
+  return this.pendingInterestId_;
+};
+
+/**
+ * Get the interest given to the constructor (from Face.expressInterest).
+ * @return {Interest} The interest. NOTE: You must not change the interest
+ * object - if you need to change it then make a copy.
+ */
+PendingInterestTable.Entry.prototype.getInterest = function()
+{
+  return this.interest_;
+};
+
+/**
+ * Get the OnData callback given to the constructor.
+ * @return {function} The OnData callback.
+ */
+PendingInterestTable.Entry.prototype.getOnData = function()
+{
+  return this.onData_;
+};
+
+/**
+ * Get the OnNetworkNack callback given to the constructor.
+ * @return {function} The OnNetworkNack callback.
+ */
+PendingInterestTable.Entry.prototype.getOnNetworkNack = function()
+{
+  return this.onNetworkNack_;
+};
+
+/**
+* Call onTimeout_ (if defined). This ignores exceptions from the call to
+* onTimeout_.
+*/
+PendingInterestTable.Entry.prototype.callTimeout = function()
+{
+  if (this.onTimeout_) {
+    try {
+      this.onTimeout_(this.interest_);
+    } catch (ex) {
+      console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Call setTimeout(callback, milliseconds) and remember the timer ID. If the
+ * timer ID has already been set on a prevous call, do nothing.
+ */
+PendingInterestTable.Entry.prototype.setTimeout = function(callback, milliseconds)
+{
+  if (this.timerId_ !== -1)
+    // Already set a timeout.
+    return;
+  this.timerId_ = setTimeout(callback, milliseconds);
+};
+
+/**
+ * Clear the timeout timer and reset the timer ID.
+ */
+PendingInterestTable.Entry.prototype.clearTimeout = function()
+{
+  if (this.timerId_ !== -1) {
+    clearTimeout(this.timerId_);
+    this.timerId_ = -1;
+  }
+};
+
+/**
+ * Add a new entry to the pending interest table. Also set a timer to call the
+ * timeout. However, if removePendingInterest was already called with the
+ * pendingInterestId, don't add an entry and return null.
+ * @param {number} pendingInterestId
+ * @param {Interest} interestCopy
+ * @param {function} onData
+ * @param {function} onTimeout
+ * @param {function} onNetworkNack
+ * @return {PendingInterestTable.Entry} The new PendingInterestTable.Entry, or
+ * null if removePendingInterest was already called with the pendingInterestId.
+ */
+PendingInterestTable.prototype.add = function
+  (pendingInterestId, interestCopy, onData, onTimeout, onNetworkNack)
+{
+  var removeRequestIndex = this.removeRequests_.indexOf(pendingInterestId);
+  if (removeRequestIndex >= 0) {
+    // removePendingInterest was called with the pendingInterestId returned by
+    //   expressInterest before we got here, so don't add a PIT entry.
+    this.removeRequests_.splice(removeRequestIndex, 1);
+    return null;
+  }
+
+  var entry = new PendingInterestTable.Entry
+    (pendingInterestId, interestCopy, onData, onTimeout, onNetworkNack);
+  this.table_.push(entry);
+
+  // Set interest timer.
+  var timeoutMilliseconds = (interestCopy.getInterestLifetimeMilliseconds() || 4000);
+  var thisTable = this;
+  var timeoutCallback = function() {
+    if (LOG > 1) console.log("Interest time out: " + interestCopy.getName().toUri());
+
+    // Remove the entry from the table.
+    var index = thisTable.table_.indexOf(entry);
+    if (index >= 0)
+      thisTable.table_.splice(index, 1);
+
+    entry.callTimeout();
+  };
+
+  entry.setTimeout(timeoutCallback, timeoutMilliseconds);
+  return entry;
+};
+
+/**
+ * Find all entries from the pending interest table where data conforms to
+ * the entry's interest selectors, remove the entries from the table, and add to
+ * the entries list.
+ * @param {Data} data The incoming Data packet to find the interest for.
+ * @param {Array<PendingInterestTable.Entry>} entries Add matching
+ * PendingInterestTable.Entry from the pending interest table. The caller should
+ * pass in an empty array.
+ */
+PendingInterestTable.prototype.extractEntriesForExpressedInterest = function
+  (data, entries)
+{
+  // Go backwards through the list so we can erase entries.
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    var pendingInterest = this.table_[i];
+    if (pendingInterest.getInterest().matchesData(data)) {
+      pendingInterest.clearTimeout();
+      entries.push(pendingInterest);
+      this.table_.splice(i, 1);
+    }
+  }
+};
+
+/**
+ * Find all entries from the pending interest table where the OnNetworkNack
+ * callback is not null and the entry's interest is the same as the given
+ * interest, remove the entries from the table, and add to the entries list. 
+ * (We don't remove the entry if the OnNetworkNack callback is null so that
+ * OnTimeout will be called later.) The interests are the same if their default
+ * wire encoding is the same (which has everything including the name, nonce,
+ * link object and selectors).
+ * @param {Interest} interest The Interest to search for (typically from a Nack
+ * packet).
+ * @param {Array<PendingInterestTable.Entry>} entries Add matching
+ * PendingInterestTable.Entry from the pending interest table. The caller should
+ * pass in an empty array.
+ */
+PendingInterestTable.prototype.extractEntriesForNackInterest = function
+  (interest, entries)
+{
+  var encoding = interest.wireEncode();
+
+  // Go backwards through the list so we can erase entries.
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    var pendingInterest = this.table_[i];
+    if (pendingInterest.getOnNetworkNack() == null)
+      continue;
+
+    // wireEncode returns the encoding cached when the interest was sent (if
+    // it was the default wire encoding).
+    if (pendingInterest.getInterest().wireEncode().equals(encoding)) {
+      pendingInterest.clearTimeout();
+      entries.push(pendingInterest);
+      this.table_.splice(i, 1);
+    }
+  }
+};
+
+/**
+ * Remove the pending interest entry with the pendingInterestId from the pending
+ * interest table. This does not affect another pending interest with a
+ * different pendingInterestId, even if it has the same interest name.
+ * If there is no entry with the pendingInterestId, do nothing.
+ * @param {number} pendingInterestId The ID returned from expressInterest.
+ */
+PendingInterestTable.prototype.removePendingInterest = function
+  (pendingInterestId)
+{
+  if (pendingInterestId == null)
+    return;
+
+  // Go backwards through the list so we can erase entries.
+  // Remove all entries even though pendingInterestId should be unique.
+  var count = 0;
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    var entry = this.table_[i];
+    if (entry.getPendingInterestId() == pendingInterestId) {
+      entry.clearTimeout();
+      this.table_.splice(i, 1);
+      ++count;
+    }
+  }
+
+  if (count === 0)
+    if (LOG > 0) console.log
+      ("removePendingInterest: Didn't find pendingInterestId " + pendingInterestId);
+
+  if (count === 0) {
+    // The pendingInterestId was not found. Perhaps this has been called before
+    //   the callback in expressInterest can add to the PIT. Add this
+    //   removal request which will be checked before adding to the PIT.
+    if (this.removeRequests_.indexOf(pendingInterestId) < 0)
+      // Not already requested, so add the request.
+      this.removeRequests_.push(pendingInterestId);
+  }
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * A RegisteredPrefixTable is an internal class to hold a list of registered
+ * prefixes with information necessary to remove the registration later.
+ * @param {InterestFilterTable} interestFilterTable See removeRegisteredPrefix(),
+ * which may call interestFilterTable.unsetInterestFilter().
+ * @constructor
+ */
+var RegisteredPrefixTable = function RegisteredPrefixTable(interestFilterTable)
+{
+  this.interestFilterTable_ = interestFilterTable;
+  this.table_ = []; // of Entry
+  this.removeRequests_ = []; // of number
+};
+
+exports.RegisteredPrefixTable = RegisteredPrefixTable;
+
+/**
+ * Add a new entry to the table. However, if removeRegisteredPrefix was already
+ * called with the registeredPrefixId, don't add an entry and return false.
+ * @param {number} registeredPrefixId The ID from Node.getNextEntryId().
+ * @param {Name} prefix The name prefix.
+ * @param {number} relatedInterestFilterId (optional) The related
+ * interestFilterId for the filter set in the same registerPrefix operation. If
+ * omitted, set to 0.
+ * return {boolean} True if added an entry, false if removeRegisteredPrefix was
+ * already called with the registeredPrefixId.
+ */
+RegisteredPrefixTable.prototype.add = function
+  (registeredPrefixId, prefix, relatedInterestFilterId)
+{
+  var removeRequestIndex = this.removeRequests_.indexOf(registeredPrefixId);
+  if (removeRequestIndex >= 0) {
+    // removeRegisteredPrefix was called with the registeredPrefixId returned by
+    //   registerPrefix before we got here, so don't add a registered prefix
+    //   table entry.
+    this.removeRequests_.splice(removeRequestIndex, 1);
+    return false;
+  }
+
+  this.table_.push(new RegisteredPrefixTable._Entry
+    (registeredPrefixId, prefix, relatedInterestFilterId));
+  return true;
+};
+
+/**
+ * Remove the registered prefix entry with the registeredPrefixId from the
+ * registered prefix table. This does not affect another registered prefix with
+ * a different registeredPrefixId, even if it has the same prefix name. If an
+ * interest filter was automatically created by registerPrefix, also call
+ * interestFilterTable_.unsetInterestFilter to remove it.
+ * If there is no entry with the registeredPrefixId, do nothing.
+ * @param {number} registeredPrefixId The ID returned from registerPrefix.
+ */
+RegisteredPrefixTable.prototype.removeRegisteredPrefix = function
+  (registeredPrefixId)
+{
+  // Go backwards through the list so we can erase entries.
+  // Remove all entries even though registeredPrefixId should be unique.
+  var count = 0;
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    var entry = this.table_[i];
+    if (entry.getRegisteredPrefixId() == registeredPrefixId) {
+      ++count;
+
+      if (entry.getRelatedInterestFilterId() > 0)
+        // Remove the related interest filter.
+        this.interestFilterTable_.unsetInterestFilter
+          (entry.getRelatedInterestFilterId());
+
+      this.table_.splice(i, 1);
+    }
+  }
+
+  if (count === 0)
+    if (LOG > 0) console.log
+      ("removeRegisteredPrefix: Didn't find registeredPrefixId " + registeredPrefixId);
+
+  if (count === 0) {
+    // The registeredPrefixId was not found. Perhaps this has been called before
+    //   the callback in registerPrefix can add to the registered prefix table.
+    //   Add this removal request which will be checked before adding to the
+    //   registered prefix table.
+    if (this.removeRequests_.indexOf(registeredPrefixId) < 0)
+      // Not already requested, so add the request.
+      this.removeRequests_.push(registeredPrefixId);
+  }
+};
+
+/**
+ * RegisteredPrefixTable._Entry holds a registeredPrefixId and information
+ * necessary to remove the registration later. It optionally holds a related
+ * interestFilterId if the InterestFilter was set in the same registerPrefix
+ * operation.
+ * Create a RegisteredPrefixTable.Entry with the given values.
+ * @param {number} registeredPrefixId The ID from Node.getNextEntryId().
+ * @param {Name} prefix The name prefix.
+ * @param {number} relatedInterestFilterId (optional) The related
+ * interestFilterId for the filter set in the same registerPrefix operation. If
+ * omitted, set to 0.
+ * @constructor
+ */
+RegisteredPrefixTable._Entry = function RegisteredPrefixTableEntry
+  (registeredPrefixId, prefix, relatedInterestFilterId)
+{
+  this.registeredPrefixId_ = registeredPrefixId;
+  this.prefix_ = prefix;
+  this.relatedInterestFilterId_ = relatedInterestFilterId;
+};
+
+/**
+ * Get the registeredPrefixId given to the constructor.
+ * @return {number} The registeredPrefixId.
+ */
+RegisteredPrefixTable._Entry.prototype.getRegisteredPrefixId = function()
+{
+  return this.registeredPrefixId;
+};
+
+/**
+ * Get the name prefix given to the constructor.
+ * @return {Name} The name prefix.
+ */
+RegisteredPrefixTable._Entry.prototype.getPrefix = function()
+{
+  return this.prefix;
+};
+
+/**
+ * Get the related interestFilterId given to the constructor.
+ * @return {number} The related interestFilterId.
+ */
+RegisteredPrefixTable._Entry.prototype.getRelatedInterestFilterId = function()
+{
+  return this.relatedInterestFilterId;
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-cxx fields.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/fields.hpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * IncomingFaceId represents the incoming face ID header field in an NDNLPv2 packet.
+ * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
+ * @constructor
+ */
+var IncomingFaceId = function IncomingFaceId()
+{
+  this.faceId_ = null;
+};
+
+exports.IncomingFaceId = IncomingFaceId;
+
+/**
+ * Get the incoming face ID value.
+ * @return {number} The face ID value.
+ */
+IncomingFaceId.prototype.getFaceId = function() { return this.faceId_; };
+
+/**
+ * Set the face ID value.
+ * @param {number} faceId The incoming face ID value.
+ */
+IncomingFaceId.prototype.setFaceId = function(faceId)
+{
+  this.faceId_ = faceId;
+};
+
+/**
+ * Get the first header field in lpPacket which is an IncomingFaceId. This is
+ * an internal method which the application normally would not use.
+ * @param {LpPacket} lpPacket The LpPacket with the header fields to search.
+ * @return {IncomingFaceId} The first IncomingFaceId header field, or null if
+ * not found.
+ */
+IncomingFaceId.getFirstHeader = function(lpPacket)
+{
+  for (var i = 0; i < lpPacket.countHeaderFields(); ++i) {
+    var field = lpPacket.getHeaderField(i);
+    if (field instanceof IncomingFaceId)
+      return field;
+  }
+
+  return null;
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-cxx packet.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/packet.hpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * An LpPacket represents an NDNLPv2 packet including header fields an an
+ * optional fragment. This is an internal class which the application normally
+ * would not use.
+ * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
+ * @constructor
+ */
+var LpPacket = function LpPacket()
+{
+  this.headerFields_ = [];
+  this.fragmentWireEncoding_ = new Blob();
+};
+
+exports.LpPacket = LpPacket;
+
+/**
+ * Get the fragment wire encoding.
+ * @return {Blob} The wire encoding, or an isNull Blob if not specified.
+ */
+LpPacket.prototype.getFragmentWireEncoding = function()
+{
+  return this.fragmentWireEncoding_;
+};
+
+/**
+ * Get the number of header fields. This does not include the fragment.
+ * @return {number} The number of header fields.
+ */
+LpPacket.prototype.countHeaderFields = function()
+{ 
+  return this.headerFields_.length;
+};
+
+/**
+ * Get the header field at the given index.
+ * @param {number} index The index, starting from 0. It is an error if index is
+ * greater to or equal to countHeaderFields().
+ * @return {object} The header field at the index.
+ */
+LpPacket.prototype.getHeaderField = function(index)
+{ 
+  return this.headerFields_[index];
+};
+
+/**
+ * Remove all header fields and set the fragment to an isNull Blob.
+ */
+LpPacket.prototype.clear = function()
+{
+  this.headerFields_ = [];
+  this.fragmentWireEncoding_ = new Blob();
+};
+
+/**
+ * Set the fragment wire encoding.
+ * @param {Blob} fragmentWireEncoding The fragment wire encoding or an isNull
+ * Blob if not specified.
+ */
+LpPacket.prototype.setFragmentWireEncoding = function(fragmentWireEncoding)
+{
+  this.fragmentWireEncoding_ =
+    typeof fragmentWireEncoding === 'object' && fragmentWireEncoding instanceof Blob ?
+      fragmentWireEncoding : new Blob(fragmentWireEncoding);
+};
+
+/**
+ * Add a header field. To add the fragment, use setFragmentWireEncoding().
+ * @param {object} headerField The header field to add.
+ */
+LpPacket.prototype.addHeaderField = function(headerField)
+{ 
+  this.headerFields_.push(headerField);
+};
+/**
+ * This class represents the top-level object for communicating with an NDN host.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cherkaoui, Jeff Thompson <jefft0@remap.ucla.edu>, Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var Interest = require('./interest.js').Interest; /** @ignore */
+var Data = require('./data.js').Data; /** @ignore */
+var ControlParameters = require('./control-parameters.js').ControlParameters; /** @ignore */
+var ControlResponse = require('./control-response.js').ControlResponse; /** @ignore */
+var InterestFilter = require('./interest-filter.js').InterestFilter; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var TlvWireFormat = require('./encoding/tlv-wire-format.js').TlvWireFormat; /** @ignore */
+var Tlv = require('./encoding/tlv/tlv.js').Tlv; /** @ignore */
+var TlvDecoder = require('./encoding/tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
+var ForwardingFlags = require('./forwarding-flags.js').ForwardingFlags; /** @ignore */
+var Transport = require('./transport/transport.js').Transport; /** @ignore */
+var TcpTransport = require('./transport/tcp-transport.js').TcpTransport; /** @ignore */
+var UnixTransport = require('./transport/unix-transport.js').UnixTransport; /** @ignore */
+var CommandInterestGenerator = require('./util/command-interest-generator.js').CommandInterestGenerator; /** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var NdnCommon = require('./util/ndn-common.js').NdnCommon; /** @ignore */
+var NetworkNack = require('./network-nack.js').NetworkNack; /** @ignore */
+var LpPacket = require('./lp/lp-packet.js').LpPacket; /** @ignore */
+var InterestFilterTable = require('./impl/interest-filter-table.js').InterestFilterTable; /** @ignore */
+var PendingInterestTable = require('./impl/pending-interest-table.js').PendingInterestTable; /** @ignore */
+var RegisteredPrefixTable = require('./impl/registered-prefix-table.js').RegisteredPrefixTable; /** @ignore */
+var fs = require('fs'); /** @ignore */
+var LOG = require('./log.js').Log.LOG;
+
+/**
+ * Create a new Face with the given settings.
+ * This throws an exception if Face.supported is false.
+ * There are two forms of the constructor.  The first form takes the transport and connectionInfo:
+ * Face(transport, connectionInfo).  The second form takes an optional settings object:
+ * Face([settings]).
+ * @constructor
+ * @param {Transport} transport An object of a subclass of Transport to use for
+ * communication.
+ * @param {Transport.ConnectionInfo} connectionInfo This must be a ConnectionInfo
+ * from the same subclass of Transport as transport. If omitted and transport is
+ * a new UnixTransport() then attempt to create to the Unix socket for the local
+ * forwarder.
+ * @param {Object} settings (optional) An associative array with the following defaults:
+ * {
+ *   getTransport: function() { return new WebSocketTransport(); }, // If in the browser.
+ *              OR function() { return new TcpTransport(); },       // If in Node.js.
+ *              // If getTransport creates a UnixTransport and connectionInfo is null,
+ *              // then connect to the local forwarder's Unix socket.
+ *   getConnectionInfo: transport.defaultGetConnectionInfo, // a function, on each call it returns a new Transport.ConnectionInfo or null if there are no more hosts.
+ *                                                          // If connectionInfo or host is not null, getConnectionInfo is ignored.
+ *   connectionInfo: null,
+ *   host: null, // If null and connectionInfo is null, use getConnectionInfo when connecting.
+ *               // However, if connectionInfo is not null, use it instead.
+ *   port: 9696, // If in the browser.
+ *      OR 6363, // If in Node.js.
+ *               // However, if connectionInfo is not null, use it instead.
+ *   onopen: function() { if (LOG > 3) console.log("NDN connection established."); },
+ *   onclose: function() { if (LOG > 3) console.log("NDN connection closed."); },
+ * }
+ */
+var Face = function Face(transportOrSettings, connectionInfo)
+{
+  if (!Face.supported)
+    throw new Error("The necessary JavaScript support is not available on this platform.");
+
+  var settings;
+  if (typeof transportOrSettings == 'object' && transportOrSettings instanceof Transport) {
+    this.getConnectionInfo = null;
+    this.transport = transportOrSettings;
+    this.connectionInfo = (connectionInfo || null);
+    // Use defaults for other settings.
+    settings = {};
+
+    if (this.connectionInfo == null) {
+      if (this.transport && this.transport.__proto__ &&
+          this.transport.__proto__.name == "UnixTransport") {
+        // Try to create the default connectionInfo for UnixTransport.
+        var filePath = Face.getUnixSocketFilePathForLocalhost();
+        if (filePath != null)
+          this.connectionInfo = new UnixTransport.ConnectionInfo(filePath);
+        else
+          console.log
+            ("Face constructor: Cannot determine the default Unix socket file path for UnixTransport");
+        if (LOG > 0)
+          console.log("Using " + this.connectionInfo.toString());
+      }
+    }
+  }
+  else {
+    settings = (transportOrSettings || {});
+    // For the browser, browserify-tcp-transport.js replaces TcpTransport with WebSocketTransport.
+    var getTransport = (settings.getTransport || function() { return new TcpTransport(); });
+    this.transport = getTransport();
+    this.getConnectionInfo = (settings.getConnectionInfo || this.transport.defaultGetConnectionInfo);
+
+    this.connectionInfo = (settings.connectionInfo || null);
+    if (this.connectionInfo == null) {
+      var host = (settings.host !== undefined ? settings.host : null);
+
+      if (this.transport && this.transport.__proto__ &&
+          this.transport.__proto__.name == "UnixTransport") {
+        // We are using UnixTransport on Node.js. There is no IP-style host and port.
+        if (host != null)
+          // Assume the host is the local Unix socket path.
+          this.connectionInfo = new UnixTransport.ConnectionInfo(host);
+        else {
+          // If getConnectionInfo is not null, it will be used instead so no
+          // need to set this.connectionInfo.
+          if (this.getConnectionInfo == null) {
+            var filePath = Face.getUnixSocketFilePathForLocalhost();
+            if (filePath != null)
+              this.connectionInfo = new UnixTransport.ConnectionInfo(filePath);
+            else
+              console.log
+                ("Face constructor: Cannot determine the default Unix socket file path for UnixTransport");
+          }
+        }
+      }
+      else {
+        if (host != null) {
+          if (typeof WebSocketTransport != 'undefined')
+            this.connectionInfo = new WebSocketTransport.ConnectionInfo
+              (host, settings.port || 9696);
+          else
+            this.connectionInfo = new TcpTransport.ConnectionInfo
+              (host, settings.port || 6363);
+        }
+      }
+    }
+  }
+
+  // Deprecated: Set this.host and this.port for backwards compatibility.
+  if (this.connectionInfo == null) {
+    this.host = null;
+    this.host = null;
+  }
+  else {
+    this.host = this.connectionInfo.host;
+    this.host = this.connectionInfo.port;
+  }
+
+  this.readyStatus = Face.UNOPEN;
+
+  // Event handler
+  this.onopen = (settings.onopen || function() { if (LOG > 3) console.log("Face connection established."); });
+  this.onclose = (settings.onclose || function() { if (LOG > 3) console.log("Face connection closed."); });
+  // This is used by reconnectAndExpressInterest.
+  this.onConnectedCallbacks = [];
+  this.commandKeyChain = null;
+  this.commandCertificateName = new Name();
+  this.commandInterestGenerator = new CommandInterestGenerator();
+  this.timeoutPrefix = new Name("/local/timeout");
+
+  this.pendingInterestTable_ = new PendingInterestTable();
+  this.interestFilterTable_ = new InterestFilterTable();
+  this.registeredPrefixTable_ = new RegisteredPrefixTable(this.interestFilterTable_);
+  this.lastEntryId = 0;
+};
+
+exports.Face = Face;
+
+Face.UNOPEN = 0;  // the Face is created but not opened yet
+Face.OPEN_REQUESTED = 1;  // requested to connect but onopen is not called.
+Face.OPENED = 2;  // connection to the forwarder opened
+Face.CLOSED = 3;  // connection to the forwarder closed
+
+TcpTransport.importFace(Face);
+
+/**
+ * If the forwarder's Unix socket file path exists, then return the file path.
+ * Otherwise return an empty string. This uses Node.js blocking file system
+ * utilities.
+ * @return The Unix socket file path to use, or an empty string.
+ */
+Face.getUnixSocketFilePathForLocalhost = function()
+{
+  var filePath = "/var/run/nfd.sock";
+  if (fs.existsSync(filePath))
+    return filePath;
+  else {
+    filePath = "/tmp/.ndnd.sock";
+    if (fs.existsSync(filePath))
+      return filePath;
+    else
+      return "";
+  }
+}
+
+/**
+ * Return true if necessary JavaScript support is available, else log an error and return false.
+ */
+Face.getSupported = function()
+{
+  try {
+    var dummy = new Buffer(1).slice(0, 1);
+  }
+  catch (ex) {
+    console.log("NDN not available: Buffer not supported. " + ex);
+    return false;
+  }
+
+  return true;
+};
+
+Face.supported = Face.getSupported();
+
+Face.prototype.createRoute = function(hostOrConnectionInfo, port)
+{
+  if (hostOrConnectionInfo instanceof Transport.ConnectionInfo)
+    this.connectionInfo = hostOrConnectionInfo;
+  else
+    this.connectionInfo = new TcpTransport.ConnectionInfo(hostOrConnectionInfo, port);
+
+  // Deprecated: Set this.host and this.port for backwards compatibility.
+  this.host = this.connectionInfo.host;
+  this.host = this.connectionInfo.port;
+};
+
+Face.prototype.close = function()
+{
+  if (this.readyStatus != Face.OPENED)
+    return;
+
+  this.readyStatus = Face.CLOSED;
+  this.transport.close();
+};
+
+/**
+ * An internal method to get the next unique entry ID for the pending interest
+ * table, interest filter table, etc. Most entry IDs are for the pending
+ * interest table (there usually are not many interest filter table entries) so
+ * we use a common pool to only have to have one method which is called by Face.
+ *
+ * @return {number} The next entry ID.
+ */
+Face.prototype.getNextEntryId = function()
+{
+  return ++this.lastEntryId;
+};
+
+/**
+ * Return a function that selects a host at random from hostList and returns
+ * makeConnectionInfo(host, port), and if no more hosts remain, return null.
+ * @param {Array<string>} hostList An array of host names.
+ * @param {number} port The port for the connection.
+ * @param {function} makeConnectionInfo This calls makeConnectionInfo(host, port)
+ * to make the Transport.ConnectionInfo. For example:
+ * function(host, port) { return new TcpTransport.ConnectionInfo(host, port); }
+ * @return {function} A function which returns a Transport.ConnectionInfo.
+ */
+Face.makeShuffledHostGetConnectionInfo = function(hostList, port, makeConnectionInfo)
+{
+  // Make a copy.
+  hostList = hostList.slice(0, hostList.length);
+  DataUtils.shuffle(hostList);
+
+  return function() {
+    if (hostList.length == 0)
+      return null;
+
+    return makeConnectionInfo(hostList.splice(0, 1)[0], port);
+  };
+};
+
+/**
+ * Send the interest through the transport, read the entire response and call 
+ * onData, onTimeout or onNetworkNack as described below.
+ * There are two forms of expressInterest. The first form takes the exact
+ * interest (including lifetime):
+ * expressInterest(interest, onData [, onTimeout] [, onNetworkNack] [, wireFormat]).
+ * The second form creates the interest from a name and optional interest template:
+ * expressInterest(name [, template], onData [, onTimeout] [, onNetworkNack] [, wireFormat]).
+ * @param {Interest} interest The Interest to send which includes the interest lifetime for the timeout.
+ * @param {function} onData When a matching data packet is received, this calls onData(interest, data) where
+ * interest is the interest given to expressInterest and data is the received
+ * Data object. NOTE: You must not change the interest object - if you need to
+ * change it then make a copy.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onTimeout (optional) If the interest times out according to the interest lifetime,
+ *   this calls onTimeout(interest) where:
+ *   interest is the interest given to expressInterest.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onNetworkNack (optional) When a network Nack packet for the
+ * interest is received and onNetworkNack is not null, this calls
+ * onNetworkNack(interest, networkNack) and does not call onTimeout. interest is
+ * the sent Interest and networkNack is the received NetworkNack. If
+ * onNetworkNack is supplied, then onTimeout must be supplied too. However, if a
+ * network Nack is received and onNetworkNack is null, do nothing and wait for
+ * the interest to time out. (Therefore, an application which does not yet
+ * process a network Nack reason treats a Nack the same as a timeout.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {Name} name The Name for the interest. (only used for the second form of expressInterest).
+ * @param {Interest} template (optional) If not omitted, copy the interest selectors from this Interest.
+ * If omitted, use a default interest lifetime. (only used for the second form of expressInterest).
+ * @param {WireFormat} (optional) A WireFormat object used to encode the message.
+ * If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {number} The pending interest ID which can be used with removePendingInterest.
+ * @throws Error If the encoded interest size exceeds Face.getMaxNdnPacketSize().
+ */
+Face.prototype.expressInterest = function
+  (interestOrName, arg2, arg3, arg4, arg5, arg6)
+{
+  var interest;
+  if (typeof interestOrName === 'object' && interestOrName instanceof Interest)
+    // Just use a copy of the interest.
+    interest = new Interest(interestOrName);
+  else {
+    // The first argument is a name. Make the interest from the name and possible template.
+    if (arg2 && typeof arg2 === 'object' && arg2 instanceof Interest) {
+      var template = arg2;
+      // Copy the template.
+      interest = new Interest(template);
+      interest.setName(interestOrName);
+
+      // Shift the remaining args to be processed below.
+      arg2 = arg3;
+      arg3 = arg4;
+      arg4 = arg5;
+      arg5 = arg6;
+    }
+    else {
+      // No template.
+      interest = new Interest(interestOrName);
+      interest.setInterestLifetimeMilliseconds(4000);   // default interest timeout
+    }
+  }
+
+  var onData = arg2;
+  var onTimeout;
+  var onNetworkNack;
+  var wireFormat;
+  // arg3,       arg4,          arg5 may be:
+  // OnTimeout,  OnNetworkNack, WireFormat
+  // OnTimeout,  OnNetworkNack, null
+  // OnTimeout,  WireFormat,    null
+  // OnTimeout,  null,          null
+  // WireFormat, null,          null
+  // null,       null,          null
+  if (typeof arg3 === "function")
+    onTimeout = arg3;
+  else
+    onTimeout = function() {};
+
+  if (typeof arg4 === "function")
+    onNetworkNack = arg4;
+  else
+    onNetworkNack = null;
+
+  if (arg3 instanceof WireFormat)
+    wireFormat = arg3;
+  else if (arg4 instanceof WireFormat)
+    wireFormat = arg4;
+  else if (arg5 instanceof WireFormat)
+    wireFormat = arg5;
+  else
+    wireFormat = WireFormat.getDefaultWireFormat();
+
+  var pendingInterestId = this.getNextEntryId();
+
+  // Set the nonce in our copy of the Interest so it is saved in the PIT.
+  interest.setNonce(Face.nonceTemplate_);
+  interest.refreshNonce();
+
+  if (this.connectionInfo == null) {
+    if (this.getConnectionInfo == null)
+      console.log('ERROR: connectionInfo is NOT SET');
+    else {
+      var thisFace = this;
+      this.connectAndExecute(function() {
+        thisFace.reconnectAndExpressInterest
+          (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
+           wireFormat);
+      });
+    }
+  }
+  else
+    this.reconnectAndExpressInterest
+      (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat);
+
+  return pendingInterestId;
+};
+
+/**
  * If the host and port are different than the ones in this.transport, then call
  *   this.transport.connect to change the connection (or connect for the first time).
  * Then call expressInterestHelper.
  */
-NDN.prototype.reconnectAndExpressInterest = function(interest, closure) {
-    if (this.transport.connectedHost != this.host || this.transport.connectedPort != this.port) {
-        var thisNDN = this;
-        this.transport.connect(thisNDN, function() { thisNDN.expressInterestHelper(interest, closure); });
-    }
-    else
-        this.expressInterestHelper(interest, closure);
-};
+Face.prototype.reconnectAndExpressInterest = function
+  (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat)
+{
+  var thisFace = this;
+  if (!this.connectionInfo.equals(this.transport.connectionInfo) || this.readyStatus === Face.UNOPEN) {
+    this.readyStatus = Face.OPEN_REQUESTED;
+    this.onConnectedCallbacks.push
+      (function() {
+        thisFace.expressInterestHelper
+          (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
+           wireFormat);
+      });
 
-/*
- * Do the work of reconnectAndExpressInterest once we know we are connected.  Set the PITTable and call
- *   this.transport.send to send the interest.
- */
-NDN.prototype.expressInterestHelper = function(interest, closure) {
-    var binaryInterest = encodeToBinaryInterest(interest);
-    var thisNDN = this;
-	//TODO: check local content store first
-	if (closure != null) {
-		var pitEntry = new PITEntry(interest, closure);
-        // TODO: This needs to be a single thread-safe transaction on a global object.
-		NDN.PITTable.push(pitEntry);
-		closure.pitEntry = pitEntry;
+    this.transport.connect
+     (this.connectionInfo, this,
+      function() {
+        thisFace.readyStatus = Face.OPENED;
 
-        // Set interest timer.
-        var timeoutMilliseconds = (interest.interestLifetime || 4000);
-        var timeoutCallback = function() {
-			if (LOG > 3) console.log("Interest time out: " + interest.name.to_uri());
-
-			// Remove PIT entry from NDN.PITTable, even if we add it again later to re-express
-            //   the interest because we don't want to match it in the mean time.
-            // TODO: Make this a thread-safe operation on the global PITTable.
-			var index = NDN.PITTable.indexOf(pitEntry);
-			if (index >= 0)
-	            NDN.PITTable.splice(index, 1);
-
-			// Raise closure callback
-			if (closure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,
-                  new UpcallInfo(thisNDN, interest, 0, null)) == Closure.RESULT_REEXPRESS) {
-			    if (LOG > 3) console.log("Re-express interest: " + interest.name.to_uri());
-                pitEntry.timerID = setTimeout(timeoutCallback, timeoutMilliseconds);
-                NDN.PITTable.push(pitEntry);
-                thisNDN.transport.send(binaryInterest);
-            }
-		};
-		pitEntry.timerID = setTimeout(timeoutCallback, timeoutMilliseconds);
-	}
-
-	this.transport.send(binaryInterest);
-};
-
-NDN.prototype.registerPrefix = function(name, closure, flag) {
-    var thisNDN = this;
-    var onConnected = function() {
-    	if (thisNDN.ndndid == null) {
-            // Fetch ndndid first, then register.
-            var interest = new Interest(NDN.ndndIdFetcher);
-    		interest.interestLifetime = 4000; // milliseconds
-            if (LOG>3) console.log('Expressing interest for ndndid from ndnd.');
-            thisNDN.reconnectAndExpressInterest
-               (interest, new NDN.FetchNdndidClosure(thisNDN, name, closure, flag));
+        // Execute each action requested while the connection was opening.
+        while (thisFace.onConnectedCallbacks.length > 0) {
+          try {
+            thisFace.onConnectedCallbacks.shift()();
+          } catch (ex) {
+            console.log("Face.reconnectAndExpressInterest: ignoring exception from onConnectedCallbacks: " + ex);
+          }
         }
-        else
-            thisNDN.registerPrefixHelper(name, closure, flag);
-    };
 
-	if (this.host == null || this.port == null) {
-        if (this.getHostAndPort == null)
-            console.log('ERROR: host OR port NOT SET');
-        else
-            this.connectAndExecute(onConnected);
-    }
+        if (thisFace.onopen)
+          // Call Face.onopen after success
+          thisFace.onopen();
+      },
+      function() { thisFace.closeByTransport(); });
+  }
+  else {
+    if (this.readyStatus === Face.OPEN_REQUESTED)
+      // The connection is still opening, so add to the interests to express.
+      this.onConnectedCallbacks.push
+        (function() {
+          thisFace.expressInterestHelper
+            (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
+             wireFormat);
+        });
+    else if (this.readyStatus === Face.OPENED)
+      this.expressInterestHelper
+        (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
+         wireFormat);
     else
-        onConnected();
+      throw new Error
+        ("reconnectAndExpressInterest: unexpected connection is not opened");
+  }
 };
 
-/*
- * This is a closure to receive the ContentObject for NDN.ndndIdFetcher and call
- *   registerPrefixHelper(name, callerClosure, flag).
+/**
+ * Do the work of reconnectAndExpressInterest once we know we are connected.
+ * Add the PendingInterest and call this.transport.send to send the interest.
  */
-NDN.FetchNdndidClosure = function FetchNdndidClosure(ndn, name, callerClosure, flag) {
-    // Inherit from Closure.
-    Closure.call(this);
+Face.prototype.expressInterestHelper = function
+  (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat)
+{
+  if (this.pendingInterestTable_.add
+      (pendingInterestId, interest, onData, onTimeout, onNetworkNack) == null)
+    // removePendingInterest was already called with the pendingInterestId.
+    return;
 
-    this.ndn = ndn;
-    this.name = name;
-    this.callerClosure = callerClosure;
-    this.flag = flag;
+  // Special case: For timeoutPrefix we don't actually send the interest.
+  if (!this.timeoutPrefix.match(interest.getName())) {
+    var binaryInterest = interest.wireEncode(wireFormat);
+    if (binaryInterest.size() > Face.getMaxNdnPacketSize())
+      throw new Error
+        ("The encoded interest size exceeds the maximum limit getMaxNdnPacketSize()");
+
+    this.transport.send(binaryInterest.buf());
+  }
 };
 
-NDN.FetchNdndidClosure.prototype.upcall = function(kind, upcallInfo) {
-    if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
-        console.log("Timeout while requesting the ndndid.  Cannot registerPrefix for " +
-            this.name.to_uri() + " .");
-        return Closure.RESULT_OK;
-    }
-    if (!(kind == Closure.UPCALL_CONTENT ||
-          kind == Closure.UPCALL_CONTENT_UNVERIFIED))
-        // The upcall is not for us.
-        return Closure.RESULT_ERR;
+/**
+ * Remove the pending interest entry with the pendingInterestId from the pending
+ * interest table. This does not affect another pending interest with a
+ * different pendingInterestId, even if it has the same interest name.
+ * If there is no entry with the pendingInterestId, do nothing.
+ * @param {number} pendingInterestId The ID returned from expressInterest.
+ */
+Face.prototype.removePendingInterest = function(pendingInterestId)
+{
+  this.pendingInterestTable_.removePendingInterest(pendingInterestId);
+};
 
-    var co = upcallInfo.contentObject;
-    if (!co.signedInfo || !co.signedInfo.publisher
-		|| !co.signedInfo.publisher.publisherPublicKeyDigest)
-        console.log
-          ("ContentObject doesn't have a publisherPublicKeyDigest. Cannot set ndndid and registerPrefix for "
-           + this.name.to_uri() + " .");
+/**
+ * Set the KeyChain and certificate name used to sign command interests (e.g.
+ * for registerPrefix).
+ * @param {KeyChain} keyChain The KeyChain object for signing interests, which
+ * must remain valid for the life of this Face. You must create the KeyChain
+ * object and pass it in. You can create a default KeyChain for your system with
+ * the default KeyChain constructor.
+ * @param {Name} certificateName The certificate name for signing interests.
+ * This makes a copy of the Name. You can get the default certificate name with
+ * keyChain.getDefaultCertificateName() .
+ */
+Face.prototype.setCommandSigningInfo = function(keyChain, certificateName)
+{
+  this.commandKeyChain = keyChain;
+  this.commandCertificateName = new Name(certificateName);
+};
+
+/**
+ * Set the certificate name used to sign command interest (e.g. for
+ * registerPrefix), using the KeyChain that was set with setCommandSigningInfo.
+ * @param {Name} certificateName The certificate name for signing interest. This
+ * makes a copy of the Name.
+ */
+Face.prototype.setCommandCertificateName = function(certificateName)
+{
+  this.commandCertificateName = new Name(certificateName);
+};
+
+/**
+ * Append a timestamp component and a random value component to interest's name.
+ * Then use the keyChain and certificateName from setCommandSigningInfo to sign
+ * the interest. If the interest lifetime is not set, this sets it.
+ * @note This method is an experimental feature. See the API docs for more
+ * detail at
+ * http://named-data.net/doc/ndn-ccl-api/face.html#face-makecommandinterest-method .
+ * @param {Interest} interest The interest whose name is appended with
+ * components.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the SignatureInfo and to encode the interest name for signing.  If omitted,
+ * use WireFormat.getDefaultWireFormat().
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * If omitted, block until complete. (Some crypto/database libraries only use a
+ * callback, so onComplete is required to use these.)
+ */
+Face.prototype.makeCommandInterest = function(interest, wireFormat, onComplete)
+{
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ?
+                 WireFormat.getDefaultWireFormat() : wireFormat;
+  this.nodeMakeCommandInterest
+    (interest, this.commandKeyChain, this.commandCertificateName, wireFormat,
+     onComplete);
+};
+
+/**
+ * Append a timestamp component and a random value component to interest's name.
+ * Then use the keyChain and certificateName from setCommandSigningInfo to sign
+ * the interest. If the interest lifetime is not set, this sets it.
+ * @param {Interest} interest The interest whose name is appended with
+ * components.
+ * @param {KeyChain} keyChain The KeyChain for calling sign.
+ * @param {Name} certificateName The certificate name of the key to use for
+ * signing.
+ * @param {WireFormat} wireFormat A WireFormat object used to encode
+ * the SignatureInfo and to encode the interest name for signing.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some crypto/database libraries only use a callback, so onComplete is
+ * required to use these.)
+ */
+Face.prototype.nodeMakeCommandInterest = function
+  (interest, keyChain, certificateName, wireFormat, onComplete)
+{
+  this.commandInterestGenerator.generate
+    (interest, keyChain, certificateName, wireFormat, onComplete);
+};
+
+/**
+ * Register prefix with the connected NDN hub and call onInterest when a
+ * matching interest is received. To register a prefix with NFD, you must
+ * first call setCommandSigningInfo.
+ * This uses the form:
+ * @param {Name} prefix The Name prefix.
+ * @param {function} onInterest (optional) If not null, this creates an interest
+ * filter from prefix so that when an Interest is received which matches the
+ * filter, this calls
+ * onInterest(prefix, interest, face, interestFilterId, filter).
+ * NOTE: You must not change the prefix object - if you need to change it then
+ * make a copy. If onInterest is null, it is ignored and you must call
+ * setInterestFilter.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onRegisterFailed If register prefix fails for any reason,
+ * this calls onRegisterFailed(prefix) where:
+ *   prefix is the prefix given to registerPrefix.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onRegisterSuccess (optional) When this receives a success
+ * message, this calls onRegisterSuccess(prefix, registeredPrefixId) where
+ * prefix is the prefix given to registerPrefix and registeredPrefixId is
+ * the value retured by registerPrefix. If onRegisterSuccess is null or omitted,
+ * this does not use it. (The onRegisterSuccess parameter comes after
+ * onRegisterFailed because it can be null or omitted, unlike onRegisterFailed.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {ForwardingFlags} flags (optional) The ForwardingFlags object for
+ * finer control of which interests are forward to the application. If omitted,
+ * use the default flags defined by the default ForwardingFlags constructor.
+ * @return {number} The registered prefix ID which can be used with
+ * removeRegisteredPrefix.
+ */
+Face.prototype.registerPrefix = function
+  (prefix, onInterest, onRegisterFailed, onRegisterSuccess, flags, wireFormat)
+{
+  // Temporarlity reassign to resolve the different overloaded forms.
+  var arg4 = onRegisterSuccess;
+  var arg5 = flags;
+  var arg6 = wireFormat;
+  // arg4, arg5, arg6 may be:
+  // OnRegisterSuccess, ForwardingFlags, WireFormat
+  // OnRegisterSuccess, ForwardingFlags, null
+  // OnRegisterSuccess, WireFormat,      null
+  // OnRegisterSuccess, null,            null
+  // ForwardingFlags,   WireFormat,      null
+  // ForwardingFlags,   null,            null
+  // WireFormat,        null,            null
+  // null,              null,            null
+  if (typeof arg4 === "function")
+    onRegisterSuccess = arg4;
+  else
+    onRegisterSuccess = null;
+
+  if (arg4 instanceof ForwardingFlags)
+    flags = arg4;
+  else if (arg5 instanceof ForwardingFlags)
+    flags = arg5;
+  else
+    flags = new ForwardingFlags();
+
+  if (arg4 instanceof WireFormat)
+    wireFormat = arg4;
+  else if (arg5 instanceof WireFormat)
+    wireFormat = arg5;
+  else if (arg6 instanceof WireFormat)
+    wireFormat = arg6;
+  else
+    wireFormat = WireFormat.getDefaultWireFormat();
+
+  if (!onRegisterFailed)
+    onRegisterFailed = function() {};
+
+  var registeredPrefixId = this.getNextEntryId();
+  var thisFace = this;
+  var onConnected = function() {
+    thisFace.nfdRegisterPrefix
+      (registeredPrefixId, prefix, onInterest, flags, onRegisterFailed,
+       onRegisterSuccess, thisFace.commandKeyChain,
+       thisFace.commandCertificateName, wireFormat);
+  };
+
+  if (this.connectionInfo == null) {
+    if (this.getConnectionInfo == null)
+      console.log('ERROR: connectionInfo is NOT SET');
+    else
+      this.connectAndExecute(onConnected);
+  }
+  else
+    onConnected();
+
+  return registeredPrefixId;
+};
+
+/**
+ * Get the practical limit of the size of a network-layer packet. If a packet
+ * is larger than this, the library or application MAY drop it.
+ * @return {number} The maximum NDN packet size.
+ */
+Face.getMaxNdnPacketSize = function() { return NdnCommon.MAX_NDN_PACKET_SIZE; };
+
+/**
+ * A RegisterResponse has onData to receive the response Data packet from the
+ * register prefix interest sent to the connected NDN hub. If this gets a bad
+ * response or onTimeout is called, then call onRegisterFailed.
+ */
+Face.RegisterResponse = function RegisterResponse
+  (prefix, onRegisterFailed, onRegisterSuccess, registeredPrefixId, parent,
+   onInterest)
+{
+  this.prefix = prefix;
+  this.onRegisterFailed = onRegisterFailed;
+  this.onRegisterSuccess= onRegisterSuccess;
+  this.registeredPrefixId = registeredPrefixId;
+  this.parent = parent;
+  this.onInterest = onInterest;
+};
+
+Face.RegisterResponse.prototype.onData = function(interest, responseData)
+{
+  // Decode responseData.getContent() and check for a success code.
+  var controlResponse = new ControlResponse();
+  try {
+    controlResponse.wireDecode(responseData.getContent(), TlvWireFormat.get());
+  }
+  catch (e) {
+    // Error decoding the ControlResponse.
+    if (LOG > 0)
+      console.log("Register prefix failed: Error decoding the NFD response: " + e);
+    if (this.onRegisterFailed) {
+      try {
+        this.onRegisterFailed(this.prefix);
+      } catch (ex) {
+        console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+    return;
+  }
+
+  // Status code 200 is "OK".
+  if (controlResponse.getStatusCode() != 200) {
+    if (LOG > 0)
+      console.log("Register prefix failed: Expected NFD status code 200, got: " +
+                  controlResponse.getStatusCode());
+    if (this.onRegisterFailed) {
+      try {
+        this.onRegisterFailed(this.prefix);
+      } catch (ex) {
+        console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+    return;
+  }
+
+  // Success, so we can add to the registered prefix table.
+  if (this.registeredPrefixId != 0) {
+    var interestFilterId = 0;
+    if (this.onInterest != null)
+      // registerPrefix was called with the "combined" form that includes the
+      // callback, so add an InterestFilterEntry.
+      interestFilterId = this.parent.setInterestFilter
+        (new InterestFilter(this.prefix), this.onInterest);
+
+    if (!this.parent.registeredPrefixTable_.add
+        (this.registeredPrefixId, this.prefix, interestFilterId)) {
+      // removeRegisteredPrefix was already called with the registeredPrefixId.
+      if (interestFilterId > 0)
+        // Remove the related interest filter we just added.
+        this.parent.unsetInterestFilter(interestFilterId);
+
+      return;
+    }
+  }
+
+  if (LOG > 2)
+    console.log("Register prefix succeeded with the NFD forwarder for prefix " +
+                this.prefix.toUri());
+  if (this.onRegisterSuccess != null) {
+    try {
+      this.onRegisterSuccess(this.prefix, this.registeredPrefixId);
+    } catch (ex) {
+      console.log("Error in onRegisterSuccess: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * We timed out waiting for the response.
+ */
+Face.RegisterResponse.prototype.onTimeout = function(interest)
+{
+  if (LOG > 2)
+    console.log("Timeout for NFD register prefix command.");
+  if (this.onRegisterFailed) {
+    try {
+      this.onRegisterFailed(this.prefix);
+    } catch (ex) {
+      console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Do the work of registerPrefix to register with NFD.
+ * @param {number} registeredPrefixId The Face.getNextEntryId() which
+ * registerPrefix got so it could return it to the caller. If this is 0, then
+ * don't add to registeredPrefixTable (assuming it has already been done).
+ * @param {Name} prefix
+ * @param {function} onInterest
+ * @param {ForwardingFlags} flags
+ * @param {function} onRegisterFailed
+ * @param {function} onRegisterSuccess
+ * @param {KeyChain} commandKeyChain
+ * @param {Name} commandCertificateName
+ * @param {WireFormat} wireFormat
+ */
+Face.prototype.nfdRegisterPrefix = function
+  (registeredPrefixId, prefix, onInterest, flags, onRegisterFailed,
+   onRegisterSuccess, commandKeyChain, commandCertificateName, wireFormat)
+{
+  if (commandKeyChain == null)
+      throw new Error
+        ("registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo.");
+  if (commandCertificateName.size() == 0)
+      throw new Error
+        ("registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo.");
+
+  var controlParameters = new ControlParameters();
+  controlParameters.setName(prefix);
+  controlParameters.setForwardingFlags(flags);
+
+  // Make the callback for this.isLocal().
+  var thisFace = this;
+  var onIsLocalResult = function(isLocal) {
+    var commandInterest = new Interest();
+    if (isLocal) {
+      commandInterest.setName(new Name("/localhost/nfd/rib/register"));
+      // The interest is answered by the local host, so set a short timeout.
+      commandInterest.setInterestLifetimeMilliseconds(2000.0);
+    }
     else {
-		if (LOG>3) console.log('Got ndndid from ndnd.');
-		this.ndn.ndndid = co.signedInfo.publisher.publisherPublicKeyDigest;
-		if (LOG>3) console.log(this.ndn.ndndid);
+      commandInterest.setName(new Name("/localhop/nfd/rib/register"));
+      // The host is remote, so set a longer timeout.
+      commandInterest.setInterestLifetimeMilliseconds(4000.0);
+    }
+    // NFD only accepts TlvWireFormat packets.
+    commandInterest.getName().append
+      (controlParameters.wireEncode(TlvWireFormat.get()));
+    thisFace.nodeMakeCommandInterest
+      (commandInterest, commandKeyChain, commandCertificateName,
+       TlvWireFormat.get(), function() {
+      // Send the registration interest.
+      var response = new Face.RegisterResponse
+         (prefix, onRegisterFailed, onRegisterSuccess, registeredPrefixId,
+          thisFace, onInterest);
+      thisFace.reconnectAndExpressInterest
+        (null, commandInterest, response.onData.bind(response),
+         response.onTimeout.bind(response), null, wireFormat);
+    });
+  };
 
-        this.ndn.registerPrefixHelper(this.name, this.callerClosure, this.flag);
-	}
-
-    return Closure.RESULT_OK;
+  this.isLocal
+    (onIsLocalResult,
+     function(message) {
+       if (LOG > 0)
+         console.log("Error in Transport.isLocal: " + message);
+       if (onRegisterFailed) {
+         try {
+           onRegisterFailed(prefix);
+         } catch (ex) {
+           console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+         }
+       }
+     });
 };
 
-/*
- * Do the work of registerPrefix once we know we are connected with a ndndid.
+/**
+ * Remove the registered prefix entry with the registeredPrefixId from the
+ * registered prefix table. This does not affect another registered prefix with
+ * a different registeredPrefixId, even if it has the same prefix name. If an
+ * interest filter was automatically created by registerPrefix, also remove it.
+ * If there is no entry with the registeredPrefixId, do nothing.
+ *
+ * @param {number} registeredPrefixId The ID returned from registerPrefix.
  */
-NDN.prototype.registerPrefixHelper = function(name, closure, flag) {
-	var fe = new ForwardingEntry('selfreg', name, null, null, 3, 2147483647);
-	var bytes = encodeForwardingEntry(fe);
-
-	var si = new SignedInfo();
-	si.setFields();
-
-	var co = new ContentObject(new Name(), si, bytes, new Signature());
-	co.sign();
-	var coBinary = encodeToBinaryContentObject(co);
-
-	//var nodename = unescape('%00%88%E2%F4%9C%91%16%16%D6%21%8E%A0c%95%A5%A6r%11%E0%A0%82%89%A6%A9%85%AB%D6%E2%065%DB%AF');
-	var nodename = this.ndndid;
-	var interestName = new Name(['ndnx', nodename, 'selfreg', coBinary]);
-
-	var interest = new Interest(interestName);
-	interest.scope = 1;
-	if (LOG > 3) console.log('Send Interest registration packet.');
-
-    var csEntry = new CSEntry(name.getName(), closure);
-	NDN.CSTable.push(csEntry);
-
-    this.transport.send(encodeToBinaryInterest(interest));
+Face.prototype.removeRegisteredPrefix = function(registeredPrefixId)
+{
+  this.registeredPrefixTable_.removeRegisteredPrefix(registeredPrefixId);
 };
 
-/*
- * This is called when an entire binary XML element is received, such as a ContentObject or Interest.
- * Look up in the PITTable and call the closure callback.
+/**
+ * Add an entry to the local interest filter table to call the onInterest
+ * callback for a matching incoming Interest. This method only modifies the
+ * library's local callback table and does not register the prefix with the
+ * forwarder. It will always succeed. To register a prefix with the forwarder,
+ * use registerPrefix. There are two forms of setInterestFilter.
+ * The first form uses the exact given InterestFilter:
+ * setInterestFilter(filter, onInterest).
+ * The second form creates an InterestFilter from the given prefix Name:
+ * setInterestFilter(prefix, onInterest).
+ * @param {InterestFilter} filter The InterestFilter with a prefix and optional
+ * regex filter used to match the name of an incoming Interest. This makes a
+ * copy of filter.
+ * @param {Name} prefix The Name prefix used to match the name of an incoming
+ * Interest.
+ * @param {function} onInterest When an Interest is received which matches the
+ * filter, this calls onInterest(prefix, interest, face, interestFilterId, filter).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
  */
-NDN.prototype.onReceivedElement = function(element) {
-    if (LOG>3) console.log('Complete element received. Length ' + element.length + '. Start decoding.');
-	var decoder = new BinaryXMLDecoder(element);
-	// Dispatch according to packet type
-	if (decoder.peekStartElement(NDNProtocolDTags.Interest)) {  // Interest packet
-		if (LOG > 3) console.log('Interest packet received.');
-
-		var interest = new Interest();
-		interest.from_ndnb(decoder);
-		if (LOG > 3) console.log(interest);
-		var nameStr = escape(interest.name.getName());
-		if (LOG > 3) console.log(nameStr);
-
-		var entry = getEntryForRegisteredPrefix(nameStr);
-		if (entry != null) {
-			//console.log(entry);
-			var info = new UpcallInfo(this, interest, 0, null);
-			var ret = entry.closure.upcall(Closure.UPCALL_INTEREST, info);
-			if (ret == Closure.RESULT_INTEREST_CONSUMED && info.contentObject != null)
-				this.transport.send(encodeToBinaryContentObject(info.contentObject));
-		}
-	} else if (decoder.peekStartElement(NDNProtocolDTags.ContentObject)) {  // Content packet
-		if (LOG > 3) console.log('ContentObject packet received.');
-
-		var co = new ContentObject();
-		co.from_ndnb(decoder);
-
-		var pitEntry = NDN.getEntryForExpressedInterest(co.name);
-		if (pitEntry != null) {
-			// Cancel interest timer
-			clearTimeout(pitEntry.timerID);
-
-			// Remove PIT entry from NDN.PITTable
-			var index = NDN.PITTable.indexOf(pitEntry);
-			if (index >= 0)
-				NDN.PITTable.splice(index, 1);
-
-			var currentClosure = pitEntry.closure;
-
-			if (this.verify == false) {
-				// Pass content up without verifying the signature
-				currentClosure.upcall(Closure.UPCALL_CONTENT_UNVERIFIED, new UpcallInfo(this, pitEntry.interest, 0, co));
-				return;
-			}
-
-			// Key verification
-
-			// Recursive key fetching & verification closure
-			var KeyFetchClosure = function KeyFetchClosure(content, closure, key, sig, wit) {
-				this.contentObject = content;  // unverified content object
-				this.closure = closure;  // closure corresponding to the contentObject
-				this.keyName = key;  // name of current key to be fetched
-				this.sigHex = sig;  // hex signature string to be verified
-				this.witness = wit;
-
-				Closure.call(this);
-			};
-
-            var thisNDN = this;
-			KeyFetchClosure.prototype.upcall = function(kind, upcallInfo) {
-				if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
-					console.log("In KeyFetchClosure.upcall: interest time out.");
-					console.log(this.keyName.contentName.getName());
-				} else if (kind == Closure.UPCALL_CONTENT) {
-					//console.log("In KeyFetchClosure.upcall: signature verification passed");
-
-					var rsakey = decodeSubjectPublicKeyInfo(upcallInfo.contentObject.content);
-					var verified = rsakey.verifyByteArray(this.contentObject.rawSignatureData, this.witness, this.sigHex);
-
-					var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-					//console.log("raise encapsulated closure");
-					this.closure.upcall(flag, new UpcallInfo(thisNDN, null, 0, this.contentObject));
-
-					// Store key in cache
-					var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
-					NDN.addKeyEntry(keyEntry);
-					//console.log(NDN.KeyStore);
-				} else if (kind == Closure.UPCALL_CONTENT_BAD) {
-					console.log("In KeyFetchClosure.upcall: signature verification failed");
-				}
-			};
-
-			if (co.signedInfo && co.signedInfo.locator && co.signature) {
-				if (LOG > 3) console.log("Key verification...");
-				var sigHex = DataUtils.toHex(co.signature.signature).toLowerCase();
-
-				var wit = null;
-				if (co.signature.Witness != null) {
-					wit = new Witness();
-					wit.decode(co.signature.Witness);
-				}
-
-				var keylocator = co.signedInfo.locator;
-				if (keylocator.type == KeyLocatorType.KEYNAME) {
-					if (LOG > 3) console.log("KeyLocator contains KEYNAME");
-					//var keyname = keylocator.keyName.contentName.getName();
-					//console.log(nameStr);
-					//console.log(keyname);
-
-					if (keylocator.keyName.contentName.match(co.name)) {
-						if (LOG > 3) console.log("Content is key itself");
-
-						var rsakey = decodeSubjectPublicKeyInfo(co.content);
-						var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
-						var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-
-						currentClosure.upcall(flag, new UpcallInfo(this, pitEntry.interest, 0, co));
-
-						// SWT: We don't need to store key here since the same key will be
-						//      stored again in the closure.
-						//var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
-						//NDN.addKeyEntry(keyEntry);
-						//console.log(NDN.KeyStore);
-					} else {
-						// Check local key store
-						var keyEntry = NDN.getKeyByName(keylocator.keyName);
-						if (keyEntry) {
-							// Key found, verify now
-							if (LOG > 3) console.log("Local key cache hit");
-							var rsakey = keyEntry.rsaKey;
-							var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
-							var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-
-							// Raise callback
-							currentClosure.upcall(flag, new UpcallInfo(this, pitEntry.interest, 0, co));
-						} else {
-							// Not found, fetch now
-							if (LOG > 3) console.log("Fetch key according to keylocator");
-							var nextClosure = new KeyFetchClosure(co, currentClosure, keylocator.keyName, sigHex, wit);
-							this.expressInterest(keylocator.keyName.contentName.getPrefix(4), nextClosure);
-						}
-					}
-				} else if (keylocator.type == KeyLocatorType.KEY) {
-					if (LOG > 3) console.log("Keylocator contains KEY");
-
-					var rsakey = decodeSubjectPublicKeyInfo(co.signedInfo.locator.publicKey);
-					var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
-
-					var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-					// Raise callback
-					currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(this, pitEntry.interest, 0, co));
-
-					// Since KeyLocator does not contain key name for this key,
-					// we have no way to store it as a key entry in KeyStore.
-				} else {
-					var cert = keylocator.certificate;
-					console.log("KeyLocator contains CERT");
-					console.log(cert);
-
-					// TODO: verify certificate
-				}
-			}
-		}
-	} else
-		console.log('Incoming packet is not Interest or ContentObject. Discard now.');
+Face.prototype.setInterestFilter = function(filterOrPrefix, onInterest)
+{
+  var interestFilterId = this.getNextEntryId();
+  this.interestFilterTable_.setInterestFilter
+    (interestFilterId, new InterestFilter(filterOrPrefix), onInterest, this);
+  return interestFilterId;
 };
 
-/*
- * Assume this.getHostAndPort is not null.  This is called when this.host is null or its host
- *   is not alive.  Get a host and port, connect, then execute onConnected().
+/**
+ * Remove the interest filter entry which has the interestFilterId from the
+ * interest filter table. This does not affect another interest filter with a
+ * different interestFilterId, even if it has the same prefix name. If there is
+ * no entry with the interestFilterId, do nothing.
+ * @param {number} interestFilterId The ID returned from setInterestFilter.
  */
-NDN.prototype.connectAndExecute = function(onConnected) {
-    var hostAndPort = this.getHostAndPort();
-    if (hostAndPort == null) {
-        console.log('ERROR: No more hosts from getHostAndPort');
-        this.host = null;
+Face.prototype.unsetInterestFilter = function(interestFilterId)
+{
+  this.interestFilterTable_.unsetInterestFilter(interestFilterId);
+};
+
+/**
+ * The OnInterest callback calls this to put a Data packet which satisfies an
+ * Interest.
+ * @param {Data} data The Data packet which satisfies the interest.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the Data packet. If omitted, use WireFormat.getDefaultWireFormat().
+ * @throws Error If the encoded Data packet size exceeds getMaxNdnPacketSize().
+ */
+Face.prototype.putData = function(data, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var encoding = data.wireEncode(wireFormat);
+  if (encoding.size() > Face.getMaxNdnPacketSize())
+    throw new Error
+      ("The encoded Data packet size exceeds the maximum limit getMaxNdnPacketSize()");
+
+  this.transport.send(encoding.buf());
+};
+
+/**
+ * Send the encoded packet out through the transport.
+ * @param {Buffer} encoding The Buffer with the encoded packet to send.
+ * @throws Error If the encoded packet size exceeds getMaxNdnPacketSize().
+ */
+Face.prototype.send = function(encoding)
+{
+  if (encoding.length > Face.getMaxNdnPacketSize())
+    throw new Error
+      ("The encoded packet size exceeds the maximum limit getMaxNdnPacketSize()");
+
+  this.transport.send(encoding);
+};
+
+/**
+ * Check if the face is local based on the current connection through the
+ * Transport; some Transport may cause network I/O (e.g. an IP host name lookup).
+ * @param {function} onResult On success, this calls onResult(isLocal) where
+ * isLocal is true if the host is local, false if not. We use callbacks because
+ * this may need to do network I/O (e.g. an IP host name lookup).
+ * @param {function} onError On failure for DNS lookup or other error, this
+ * calls onError(message) where message is an error string.
+ */
+Face.prototype.isLocal = function(onResult, onError)
+{
+  // TODO: How to call transport.isLocal when this.connectionInfo is null? (This
+  // happens when the application does not supply a host but relies on the
+  // getConnectionInfo function to select a host.) For now return true to keep
+  // the same behavior from before we added Transport.isLocal.
+  if (this.connectionInfo == null)
+    onResult(false);
+  else
+    this.transport.isLocal(this.connectionInfo, onResult, onError);
+};
+
+/**
+ * This is called when an entire element is received, such as a Data or Interest.
+ */
+Face.prototype.onReceivedElement = function(element)
+{
+  if (LOG > 3) console.log('Complete element received. Length ' + element.length + '. Start decoding.');
+
+  var lpPacket = null;
+  if (element[0] == Tlv.LpPacket_LpPacket) {
+    // Decode the LpPacket and replace element with the fragment.
+    lpPacket = new LpPacket();
+    // Set copy false so that the fragment is a slice which will be copied below.
+    // The header fields are all integers and don't need to be copied.
+    TlvWireFormat.get().decodeLpPacket(lpPacket, element, false);
+    element = lpPacket.getFragmentWireEncoding().buf();
+  }
+
+  // First, decode as Interest or Data.
+  var interest = null;
+  var data = null;
+  if (element[0] == Tlv.Interest || element[0] == Tlv.Data) {
+    var decoder = new TlvDecoder (element);
+    if (decoder.peekType(Tlv.Interest, element.length)) {
+      interest = new Interest();
+      interest.wireDecode(element, TlvWireFormat.get());
+
+      if (lpPacket != null)
+        interest.setLpPacket(lpPacket);
+    }
+    else if (decoder.peekType(Tlv.Data, element.length)) {
+      data = new Data();
+      data.wireDecode(element, TlvWireFormat.get());
+
+      if (lpPacket != null)
+        data.setLpPacket(lpPacket);
+    }
+  }
+
+  if (lpPacket !== null) {
+    // We have decoded the fragment, so remove the wire encoding to save memory.
+    lpPacket.setFragmentWireEncoding(new Blob());
+
+    var networkNack = NetworkNack.getFirstHeader(lpPacket);
+    if (networkNack != null) {
+      if (interest == null)
+        // We got a Nack but not for an Interest, so drop the packet.
         return;
+
+      var pitEntries = [];
+      this.pendingInterestTable_.extractEntriesForNackInterest(interest, pitEntries);
+      for (var i = 0; i < pitEntries.length; ++i) {
+        var pendingInterest = pitEntries[i];
+        try {
+          pendingInterest.getOnNetworkNack()(pendingInterest.getInterest(), networkNack);
+        } catch (ex) {
+          console.log("Error in onNetworkNack: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+
+      // We have processed the network Nack packet.
+      return;
     }
+  }
 
-    if (hostAndPort.host == this.host && hostAndPort.port == this.port) {
-        console.log('ERROR: The host returned by getHostAndPort is not alive: ' +
-                this.host + ":" + this.port);
-        return;
+  // Now process as Interest or Data.
+  if (interest !== null) {
+    if (LOG > 3) console.log('Interest packet received.');
+
+    // Call all interest filter callbacks which match.
+    var matchedFilters = [];
+    this.interestFilterTable_.getMatchedFilters(interest, matchedFilters);
+    for (var i = 0; i < matchedFilters.length; ++i) {
+      var entry = matchedFilters[i];
+      if (LOG > 3)
+        console.log("Found interest filter for " + interest.getName().toUri());
+      try {
+        entry.getOnInterest()
+          (entry.getFilter().getPrefix(), interest, this,
+           entry.getInterestFilterId(), entry.getFilter());
+      } catch (ex) {
+        console.log("Error in onInterest: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
     }
+  }
+  else if (data !== null) {
+    if (LOG > 3) console.log('Data packet received.');
 
-    this.host = hostAndPort.host;
-    this.port = hostAndPort.port;
-    if (LOG>3) console.log("Connect: trying host from getHostAndPort: " + this.host);
-
-    // Fetch any content.
-    var interest = new Interest(new Name("/"));
-	interest.interestLifetime = 4000; // milliseconds
-
-    var thisNDN = this;
-	var timerID = setTimeout(function() {
-        if (LOG>3) console.log("Connect: timeout waiting for host " + thisNDN.host);
-        // Try again.
-        thisNDN.connectAndExecute(onConnected);
-	}, 3000);
-
-    this.reconnectAndExpressInterest
-        (interest, new NDN.ConnectClosure(this, onConnected, timerID));
+    var pendingInterests = [];
+    this.pendingInterestTable_.extractEntriesForExpressedInterest
+      (data, pendingInterests);
+    // Process each matching PIT entry (if any).
+    for (var i = 0; i < pendingInterests.length; ++i) {
+      var pendingInterest = pendingInterests[i];
+      try {
+        pendingInterest.getOnData()(pendingInterest.getInterest(), data);
+      } catch (ex) {
+        console.log("Error in onData: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+  }
 };
 
-NDN.ConnectClosure = function ConnectClosure(ndn, onConnected, timerID) {
-    // Inherit from Closure.
-    Closure.call(this);
-
-    this.ndn = ndn;
-    this.onConnected = onConnected;
-    this.timerID = timerID;
-};
-
-NDN.ConnectClosure.prototype.upcall = function(kind, upcallInfo) {
-    if (!(kind == Closure.UPCALL_CONTENT ||
-          kind == Closure.UPCALL_CONTENT_UNVERIFIED))
-        // The upcall is not for us.
-        return Closure.RESULT_ERR;
-
-    // The host is alive, so cancel the timeout and continue with onConnected().
-    clearTimeout(this.timerID);
-
-    // Call NDN.onopen after success
-	this.ndn.readyStatus = NDN.OPENED;
-	this.ndn.onopen();
-
-    this.onConnected();
-
-    return Closure.RESULT_OK;
-};
-
-/*
- * A BinaryXmlElementReader lets you call onReceivedData multiple times which uses a
- *   BinaryXMLStructureDecoder to detect the end of a binary XML element and calls
- *   elementListener.onReceivedElement(element) with the element.
- * This handles the case where a single call to onReceivedData may contain multiple elements.
+/**
+ * Assume this.getConnectionInfo is not null.  This is called when
+ * this.connectionInfo is null or its host is not alive.
+ * Get a connectionInfo, connect, then execute onConnected().
  */
-var BinaryXmlElementReader = function BinaryXmlElementReader(elementListener) {
-    this.elementListener = elementListener;
-	this.dataParts = [];
-    this.structureDecoder = new BinaryXMLStructureDecoder();
+Face.prototype.connectAndExecute = function(onConnected)
+{
+  var connectionInfo = this.getConnectionInfo();
+  if (connectionInfo == null) {
+    console.log('ERROR: No more connectionInfo from getConnectionInfo');
+    this.connectionInfo = null;
+    // Deprecated: Set this.host and this.port for backwards compatibility.
+    this.host = null;
+    this.host = null;
+
+    return;
+  }
+
+  if (connectionInfo.equals(this.connectionInfo)) {
+    console.log
+      ('ERROR: The host returned by getConnectionInfo is not alive: ' +
+       this.connectionInfo.toString());
+    return;
+  }
+
+  this.connectionInfo = connectionInfo;
+  if (LOG>0) console.log("connectAndExecute: trying host from getConnectionInfo: " +
+                         this.connectionInfo.toString());
+  // Deprecated: Set this.host and this.port for backwards compatibility.
+  this.host = this.connectionInfo.host;
+  this.host = this.connectionInfo.port;
+
+  // Fetch any content.
+  var interest = new Interest(new Name("/"));
+  interest.setInterestLifetimeMilliseconds(4000);
+
+  var thisFace = this;
+  var timerID = setTimeout(function() {
+    if (LOG>0) console.log("connectAndExecute: timeout waiting for host " + thisFace.host);
+      // Try again.
+      thisFace.connectAndExecute(onConnected);
+  }, 3000);
+
+  this.reconnectAndExpressInterest
+    (null, interest,
+     function(localInterest, localData) {
+        // The host is alive, so cancel the timeout and continue with onConnected().
+        clearTimeout(timerID);
+
+        if (LOG>0)
+          console.log("connectAndExecute: connected to host " + thisFace.host);
+        onConnected();
+     },
+     function(localInterest) { /* Ignore timeout */ },
+     null, WireFormat.getDefaultWireFormat());
 };
 
-BinaryXmlElementReader.prototype.onReceivedData = function(/* Uint8Array */ rawData) {
-    // Process multiple objects in the data.
-    while(true) {
-        // Scan the input to check if a whole ndnb object has been read.
-        this.structureDecoder.seek(0);
-        if (this.structureDecoder.findElementEnd(rawData)) {
-            // Got the remainder of an object.  Report to the caller.
-            this.dataParts.push(rawData.subarray(0, this.structureDecoder.offset));
-            var element = DataUtils.concatArrays(this.dataParts);
-            this.dataParts = [];
-            try {
-                this.elementListener.onReceivedElement(element);
-            } catch (ex) {
-                console.log("BinaryXmlElementReader: ignoring exception from onReceivedElement: " + ex);
-            }
+/**
+ * This is called by the Transport when the connection is closed by the remote host.
+ */
+Face.prototype.closeByTransport = function()
+{
+  this.readyStatus = Face.CLOSED;
+  this.onclose();
+};
 
-            // Need to read a new object.
-            rawData = rawData.subarray(this.structureDecoder.offset, rawData.length);
-            this.structureDecoder = new BinaryXMLStructureDecoder();
-            if (rawData.length == 0)
-                // No more data in the packet.
-                return;
-
-            // else loop back to decode.
-        }
-        else {
-            // Save for a later call to concatArrays so that we only copy data once.
-            this.dataParts.push(rawData);
-			if (LOG>3) console.log('Incomplete packet received. Length ' + rawData.length + '. Wait for more input.');
-            return;
-        }
-    }
-}
\ No newline at end of file
+Face.nonceTemplate_ = new Blob(new Buffer(4), false);
+(function(n,t,i){"use strict";function s(n,t){return typeof t!="object"&&(t=t()),Object.keys(t).forEach(function(i){n[i]=t[i]}),n}function y(n){return{from:function(t){return n.prototype=Object.create(t.prototype),n.prototype.constructor=n,{extend:function(i){s(n.prototype,typeof i!="object"?i(t.prototype):i)}}}}}function p(n,t){return t(n)}function u(n,t){function cr(){w.on("versionchange",function(){w.close();w.on("error").fire(new g("Database version changed by other database connection."))})}function di(n){this._cfg={version:n,storesSource:null,dbschema:{},tables:{},contentUpgrade:null};this.stores({})}function lr(n,t,i,u){var e,f,s,h,l,c;if(n===0)Object.keys(st).forEach(function(n){gi(t,n,st[n].primKey,st[n].indexes)}),e=w._createTransaction(yt,ui,st),e.idbtrans=t,e.idbtrans.onerror=o(i,["populating database"]),e.on("error").subscribe(i),r.newPSD(function(){r.PSD.trans=e;try{w.on("populate").fire(e)}catch(n){u.onerror=t.onerror=function(n){n.preventDefault()};try{t.abort()}catch(f){}t.db.close();i(n)}});else{if(f=[],s=ri.filter(function(t){return t._cfg.version===n})[0],!s)throw new g("Dexie specification of currently installed DB version is missing");st=w._dbSchema=s._cfg.dbschema;h=!1;l=ri.filter(function(t){return t._cfg.version>n});l.forEach(function(n){var e=st,r=n._cfg.dbschema,u;fr(e,t);fr(r,t);st=w._dbSchema=r;u=ar(e,r);u.add.forEach(function(n){f.push(function(t,i){gi(t,n[0],n[1].primKey,n[1].indexes);i()})});u.change.forEach(function(n){if(n.recreate)throw new g("Not yet support for changing primary key");else f.push(function(t,i){var r=t.objectStore(n.name);n.add.forEach(function(n){nr(r,n)});n.change.forEach(function(n){r.deleteIndex(n.name);nr(r,n)});n.del.forEach(function(n){r.deleteIndex(n)});i()})});n._cfg.contentUpgrade&&f.push(function(t,u){var f,e;h=!0;f=w._createTransaction(yt,[].slice.call(t.db.objectStoreNames,0),r);f.idbtrans=t;e=0;f._promise=p(f._promise,function(n){return function(t,i,r){function f(n){return function(){n.apply(this,arguments);--e==0&&u()}}return++e,n.call(this,t,function(n,t){arguments[0]=f(n);arguments[1]=f(t);i.apply(this,arguments)},r)}});t.onerror=o(i,["running upgrader function for version",n._cfg.version]);f.on("error").subscribe(i);n._cfg.contentUpgrade(f);e===0&&u()});h&&dr()||f.push(function(n,t){yr(r,n);t()})});c=function(){try{f.length?f.shift()(t,c):vr(st,t)}catch(n){u.onerror=t.onerror=function(n){n.preventDefault()};try{t.abort()}catch(r){}t.db.close();i(n)}};c()}}function ar(n,t){var f={del:[],add:[],change:[]},r,e,o,i,c,s,u,l,h;for(r in n)t[r]||f.del.push(r);for(r in t)if(e=n[r],o=t[r],e)if(i={name:r,def:t[r],recreate:!1,del:[],add:[],change:[]},e.primKey.src!==o.primKey.src)i.recreate=!0,f.change.push(i);else{c=e.indexes.reduce(function(n,t){return n[t.name]=t,n},{});s=o.indexes.reduce(function(n,t){return n[t.name]=t,n},{});for(u in c)s[u]||i.del.push(u);for(u in s)l=c[u],h=s[u],l?l.src!==h.src&&i.change.push(h):i.add.push(h);(i.recreate||i.del.length>0||i.add.length>0||i.change.length>0)&&f.change.push(i)}else f.add.push([r,o]);return f}function gi(n,t,i,r){var u=n.db.createObjectStore(t,i.keyPath?{keyPath:i.keyPath,autoIncrement:i.auto}:{autoIncrement:i.auto});return r.forEach(function(n){nr(u,n)}),u}function vr(n,t){Object.keys(n).forEach(function(i){t.db.objectStoreNames.contains(i)||gi(t,i,n[i].primKey,n[i].indexes)})}function yr(n,t){for(var u,r=0;r<t.db.objectStoreNames.length;++r)u=t.db.objectStoreNames[r],(n[u]===null||n[u]===i)&&t.db.deleteObjectStore(u)}function nr(n,t){n.createIndex(t.name,t.keyPath,{unique:t.unique,multiEntry:t.multi})}function pr(n,t){throw new g("Table "+t[0]+" not part of transaction. Original Scope Function Source: "+u.Promise.PSD.trans.scopeFunc.toString());}function ei(n,t,i,r){this.name=n;this.schema=i;this.hook=ni[n]?ni[n].hook:v(null,{creating:[at,f],reading:[lt,nt],updating:[vt,f],deleting:[wt,f]});this._tpf=t;this._collClass=r||li}function tr(n,t,i,r){ei.call(this,n,t,i,r||rr)}function ir(n,t,i,r){function o(n,t,i,r){return s._promise(n,i,r)}var s=this,f,u,e;for(this.db=w,this.mode=n,this.storeNames=t,this.idbtrans=null,this.on=v(this,["complete","error"],"abort"),this._reculock=0,this._blockedFuncs=[],this._psd=null,this.active=!0,this._dbschema=i,r&&(this.parent=r),this._tpf=o,this.tables=Object.create(ki),f=t.length-1;f!==-1;--f)u=t[f],e=w._tableFactory(n,i[u],o),this.tables[u]=e,this[u]||(this[u]=e)}function ci(n,t,i){this._ctx={table:n,index:t===":id"?null:t,collClass:n._collClass,or:i}}function li(n,t){var r=null,u=null,i;if(t)try{r=t()}catch(f){u=f}i=n._ctx;this._ctx={table:i.table,index:i.index,isPrimKey:!i.index||i.table.schema.primKey.keyPath&&i.index===i.table.schema.primKey.name,range:r,op:"openCursor",dir:"next",unique:"",algorithm:null,filter:null,isMatch:null,offset:0,limit:Infinity,error:u,or:i.or}}function rr(){li.apply(this,arguments)}function wr(n,t){return n._cfg.version-t._cfg.version}function ur(n,t,i,u,f,e){i.forEach(function(i){var o=w._tableFactory(u,f[i],t);n.forEach(function(n){n[i]||(e?Object.defineProperty(n,i,{configurable:!0,enumerable:!0,get:function(){var n=r.PSD&&r.PSD.trans;return n&&n.db===w?n.tables[i]:o}}):n[i]=o)})})}function br(n){n.forEach(function(n){for(var t in n)n[t]instanceof ei&&delete n[t]})}function pi(n,t,i,u,f,e){var s=r.PSD;e=e||nt;n.onerror||(n.onerror=o(f));n.onsuccess=t?k(function(){var r=n.result,o;r?(o=function(){r.continue()},t(r,function(n){o=n},u,f)&&i(e(r.value),r,function(n){o=n}),o()):u()},f,s):k(function(){var t=n.result,r;t?(r=function(){t.continue()},i(e(t.value),t,function(n){r=n}),r()):u()},f,s)}function kr(n){var t=[];return n.split(",").forEach(function(n){n=n.trim();var i=n.replace("&","").replace("++","").replace("*",""),r=i.indexOf("[")!==0?i:n.substring(n.indexOf("[")+1,n.indexOf("]")).split("+");t.push(new a(i,r||null,n.indexOf("&")!==-1,n.indexOf("*")!==-1,n.indexOf("++")!==-1,Array.isArray(r),r.indexOf(".")!==-1))}),t}function wi(n,t){return n<t?-1:n>t?1:0}function or(n,t){return n<t?1:n>t?-1:0}function sr(n){return function(t,i){for(var r=0,u;;){if(u=n(t[r],i[r]),u!==0)return u;if(++r,r===t.length||r===i.length)return n(t.length,i.length)}}}function bi(n,t){return n?t?function(){return n.apply(this,arguments)&&t.apply(this,arguments)}:n:t}function dr(){return navigator.userAgent.indexOf("Trident")>=0||navigator.userAgent.indexOf("MSIE")>=0}function gr(){if(w.verno=et.version/10,w._dbSchema=st={},ui=[].slice.call(et.objectStoreNames,0),ui.length!==0){var n=et.transaction(ft(ui),"readonly");ui.forEach(function(t){for(var u,s,r=n.objectStore(t),i=r.keyPath,f=i&&typeof i=="string"&&i.indexOf(".")!==-1,h=new a(i,i||"",!1,!1,!!r.autoIncrement,i&&typeof i!="string",f),o=[],e=0;e<r.indexNames.length;++e)u=r.index(r.indexNames[e]),i=u.keyPath,f=i&&typeof i=="string"&&i.indexOf(".")!==-1,s=new a(u.name,i,!!u.unique,!!u.multiEntry,!1,i&&typeof i!="string",f),o.push(s);st[t]=new ut(t,h,o,{})});ur([ni],w._transPromiseFactory,Object.keys(st),yt,st)}}function fr(n,t){for(var i,r,u,o,s=t.db.objectStoreNames,f=0;f<s.length;++f)for(i=s[f],r=t.objectStore(i),u=0;u<r.indexNames.length;++u){var h=r.indexNames[u],e=r.index(h).keyPath,c=typeof e=="string"?e:"["+[].slice.call(e).join("+")+"]";n[i]&&(o=n[i].idxByName[c],o&&(o.name=h))}}var hr=t&&t.addons||u.addons,oi=u.dependencies,ai=oi.indexedDB,kt=oi.IDBKeyRange,nu=oi.IDBTransaction,tu=oi.DOMError,yi=oi.TypeError,g=oi.Error,st=this._dbSchema={},ri=[],ui=[],ni={},ki={},et=null,si=!0,fi=null,vi=!1,ti="readonly",yt="readwrite",w=this,ii=[],hi=!1,er=!!ct();this.version=function(n){if(et)throw new g("Cannot add version when database is open");this.verno=Math.max(this.verno,n);var t=ri.filter(function(t){return t._cfg.version===n})[0];return t?t:(t=new di(n),ri.push(t),ri.sort(wr),t)};s(di.prototype,{stores:function(n){var i,t;return this._cfg.storesSource=this._cfg.storesSource?s(this._cfg.storesSource,n):n,i={},ri.forEach(function(n){s(i,n._cfg.storesSource)}),t=this._cfg.dbschema={},this._parseStoresSpec(i,t),st=w._dbSchema=t,br([ni,w,ki]),ur([ki],pr,Object.keys(t),yt,t),ur([ni,w,this._cfg.tables],w._transPromiseFactory,Object.keys(t),yt,t,!0),ui=Object.keys(t),this},upgrade:function(n){var t=this;return e(function(){n(w._createTransaction(yt,Object.keys(t._cfg.dbschema),t._cfg.dbschema))}),this._cfg.contentUpgrade=n,this},_parseStoresSpec:function(n,t){Object.keys(n).forEach(function(i){if(n[i]!==null){var u={},f=kr(n[i]),r=f.shift();if(r.multi)throw new g("Primary key cannot be multi-valued");r.keyPath&&r.auto&&h(u,r.keyPath,0);f.forEach(function(n){if(n.auto)throw new g("Only primary key can be marked as autoIncrement (++)");if(!n.keyPath)throw new g("Index must have a name and cannot be an empty string");h(u,n.keyPath,n.compound?n.keyPath.map(function(){return""}):"")});t[i]=new ut(i,r,f,u)}})}});this._allTables=ni;this._tableFactory=function(n,t,i){return n===ti?new ei(t.name,i,t,li):new tr(t.name,i,t)};this._createTransaction=function(n,t,i,r){return new ir(n,t,i,r)};this._transPromiseFactory=function(n,t,i){var f,u;return!si||r.PSD&&r.PSD.letThrough?(u=w._createTransaction(n,t,st),u._promise(n,function(n,t){u.error(function(n){w.on("error").fire(n)});i(function(t){u.complete(function(){n(t)})},t,u)})):f=new r(function(r,u){ii.push({resume:function(){var e=w._transPromiseFactory(n,t,i);f.onuncatched=e.onuncatched;e.then(r,u)}})})};this._whenReady=function(n){return si&&(!r.PSD||!r.PSD.letThrough)?new r(function(t,i){e(function(){new r(function(){n(t,i)})});ii.push({resume:function(){n(t,i)}})}):new r(n)};this.verno=0;this.open=function(){return new r(function(t,i){function f(n){try{u.transaction.abort()}catch(t){}vi=!1;fi=n;si=!1;i(fi);ii.forEach(function(n){n.resume()});ii=[]}if(et||vi)throw new g("Database already opened or being opened");var u,e=!1;try{if(fi=null,vi=!0,ri.length===0&&(hi=!0),!ai)throw new g("indexedDB API not found. If using IE10+, make sure to run your code on a server URL (not locally). If using Safari, make sure to include indexedDB polyfill.");u=hi?ai.open(n):ai.open(n,Math.round(w.verno*10));u.onerror=o(f,["opening database",n]);u.onblocked=function(n){w.on("blocked").fire(n)};u.onupgradeneeded=k(function(t){var i,r;hi&&!w._allowEmptyDB?(u.onerror=function(n){n.preventDefault()},u.transaction.abort(),u.result.close(),i=ai.deleteDatabase(n),i.onsuccess=i.onerror=function(){f(new g("Database '"+n+"' doesnt exist"))}):(t.oldVersion===0&&(e=!0),u.transaction.onerror=o(f),r=t.oldVersion>Math.pow(2,62)?0:t.oldVersion,lr(r/10,u.transaction,f,u))},f);u.onsuccess=k(function(){vi=!1;et=u.result;hi?gr():et.objectStoreNames.length>0&&fr(st,et.transaction(ft(et.objectStoreNames),ti));et.onversionchange=w.on("versionchange").fire;er||rt(function(t){if(t.indexOf(n)===-1)return t.push(n)});r.newPSD(function(){function i(){si=!1;ii.forEach(function(n){n.resume()});ii=[];t()}r.PSD.letThrough=!0;try{var n=w.on.ready.fire();n&&typeof n.then=="function"?n.then(i,function(n){et.close();et=null;f(n)}):b(i)}catch(u){f(u)}})},f)}catch(s){f(s)}})};this.close=function(){et&&(et.close(),et=null,si=!0,fi=null)};this.delete=function(){var t=arguments;return new r(function(i,r){function u(){w.close();var t=ai.deleteDatabase(n);t.onsuccess=function(){er||rt(function(t){var i=t.indexOf(n);if(i>=0)return t.splice(i,1)});i()};t.onerror=o(r,["deleting",n]);t.onblocked=function(){w.on("blocked").fire()}}if(t.length>0)throw new g("Arguments not allowed in db.delete()");vi?ii.push({resume:u}):u()})};this.backendDB=function(){return et};this.isOpen=function(){return et!==null};this.hasFailed=function(){return fi!==null};this.dynamicallyOpened=function(){return hi};this.name=n;Object.defineProperty(this,"tables",{get:function(){return Object.keys(ni).map(function(n){return ni[n]})}});this.on=v(this,"error","populate","blocked",{ready:[bt,f],versionchange:[pt,f]});this.on.ready.subscribe=p(this.on.ready.subscribe,function(n){return function(t,i){function r(){return i||w.on.ready.unsubscribe(r),t.apply(this,arguments)}n.call(this,r);w.isOpen()&&(si?ii.push({resume:r}):r())}});e(function(){w.on("populate").fire(w._createTransaction(yt,ui,st));w.on("error").fire(new g)});this.transaction=function(n,t,i){function s(t,e){var s=null,c,a,h;try{if(f)throw f;s=w._createTransaction(n,o,st,u);c=o.map(function(n){return s.tables[n]});c.push(s);h=0;r.newPSD(function(){r.PSD.trans=s;s.scopeFunc=i;u&&(s.idbtrans=u.idbtrans,s._promise=p(s._promise,function(n){return function(t,i,u){function f(n){return function(t){var i;return r._rootExec(function(){i=n(t);r._tickFinalize(function(){--h==0&&s.active&&(s.active=!1,s.on.complete.fire())})}),i}}return++h,n.call(this,t,function(n,t,r){return i(f(n),f(t),r)},u)}}));s.complete(function(){t(a)});s.error(function(n){s.idbtrans&&(s.idbtrans.onerror=ht);try{s.abort()}catch(i){}u&&(u.active=!1,u.on.error.fire(n));var t=e(n);u||t||w.on.error.fire(n)});r._rootExec(function(){a=i.apply(s,c)})});(!s.idbtrans||u&&h===0)&&s._nop()}catch(l){s&&s.idbtrans&&(s.idbtrans.onerror=ht);s&&s.abort();u&&u.on.error.fire(l);b(function(){e(l)||w.on("error").fire(l)})}}var u,e;t=[].slice.call(arguments,1,arguments.length-1);i=arguments[arguments.length-1];u=r.PSD&&r.PSD.trans;u&&u.db===w&&n.indexOf("!")===-1||(u=null);e=n.indexOf("?")!==-1;n=n.replace("!","").replace("?","");var h=Array.isArray(t[0])?t.reduce(function(n,t){return n.concat(t)}):t,f=null,o=h.map(function(n){return typeof n=="string"?n:(n instanceof ei||(f=f||new yi("Invalid type. Arguments following mode must be instances of Table or String")),n.name)});return n=="r"||n==ti?n=ti:n=="rw"||n==yt?n=yt:f=new g("Invalid transaction mode: "+n),u&&(f||(u&&u.mode===ti&&n===yt&&(e?u=null:f=f||new g("Cannot enter a sub-transaction with READWRITE mode when parent transaction is READONLY")),u&&o.forEach(function(n){u.tables.hasOwnProperty(n)||(e?u=null:f=f||new g("Table "+n+" not included in parent transaction. Parent Transaction function: "+u.scopeFunc.toString()))}))),u?u._promise(n,s,"lock"):w._whenReady(s)};this.table=function(n){if(!hi&&!ni.hasOwnProperty(n))throw new g("Table does not exist");return ni[n]};s(ei.prototype,function(){function n(){throw new g("Current Transaction is READONLY");}return{_trans:function(n,t,i){return this._tpf(n,[this.name],t,i)},_idbstore:function(n,t,i){var r=this;return this._tpf(n,[this.name],function(n,i,u){t(n,i,u.idbtrans.objectStore(r.name),u)},i)},get:function(n,t){var i=this;return e(function(){t(i.schema.instanceTemplate)}),this._idbstore(ti,function(t,r,u){var f=u.get(n);f.onerror=o(r,["getting",n,"from",i.name]);f.onsuccess=function(){t(i.hook.reading.fire(f.result))}}).then(t)},where:function(n){return new ci(this,n)},count:function(n){return this.toCollection().count(n)},offset:function(n){return this.toCollection().offset(n)},limit:function(n){return this.toCollection().limit(n)},reverse:function(){return this.toCollection().reverse()},filter:function(n){return this.toCollection().and(n)},each:function(n){var t=this;return e(function(){n(t.schema.instanceTemplate)}),this._idbstore(ti,function(i,r,u){var f=u.openCursor();f.onerror=o(r,["calling","Table.each()","on",t.name]);pi(f,null,n,i,r,t.hook.reading.fire)})},toArray:function(n){var t=this;return e(function(){n([t.schema.instanceTemplate])}),this._idbstore(ti,function(n,i,r){var u=[],f=r.openCursor();f.onerror=o(i,["calling","Table.toArray()","on",t.name]);pi(f,null,function(n){u.push(n)},function(){n(u)},i,t.hook.reading.fire)}).then(n)},orderBy:function(n){return new this._collClass(new ci(this,n))},toCollection:function(){return new this._collClass(new ci(this))},mapToClass:function(n,t){var i,r;return this.schema.mappedClass=n,i=Object.create(n.prototype),this.schema.primKey.keyPath&&(h(i,this.schema.primKey.keyPath,this.schema.primKey.auto?0:""),ot(n.prototype,this.schema.primKey.keyPath)),t&&it(i,t),this.schema.instanceTemplate=i,r=Object.setPrototypeOf?function(t){return t?(Object.setPrototypeOf(t,n.prototype),t):t}:function(t){var r,i;if(!t)return t;r=Object.create(n.prototype);for(i in t)t.hasOwnProperty(i)&&(r[i]=t[i]);return r},this.schema.readHook&&this.hook.reading.unsubscribe(this.schema.readHook),this.schema.readHook=r,this.hook("reading",r),n},defineClass:function(n){return this.mapToClass(u.defineClass(n),n)},add:n,put:n,"delete":n,clear:n,update:n}});y(tr).from(ei).extend(function(){return{add:function(n,t){var u=this,r=this.hook.creating.fire;return this._idbstore(yt,function(e,s,l,a){var v={},w,y,p;r!==f&&(w=t||(l.keyPath?c(n,l.keyPath):i),y=r.call(v,w,n,a),w===i&&y!==i&&(l.keyPath?h(n,l.keyPath,y):t=y));p=t?l.add(n,t):l.add(n);p.onerror=o(function(n){if(v.onerror)v.onerror(n);return s(n)},["adding",n,"into",u.name]);p.onsuccess=function(t){var i=l.keyPath;if(i&&h(n,i,t.target.result),v.onsuccess)v.onsuccess(t.target.result);e(p.result)}})},put:function(n,t){var r=this,u=this.hook.creating.fire,e=this.hook.updating.fire;return u!==f||e!==f?this._trans(yt,function(u,f,e){var o=t||r.schema.primKey.keyPath&&c(n,r.schema.primKey.keyPath);o===i?e.tables[r.name].add(n).then(u,f):(e._lock(),n=l(n),e.tables[r.name].where(":id").equals(o).modify(function(){this.value=n}).then(function(i){return i===0?e.tables[r.name].add(n,t):o}).finally(function(){e._unlock()}).then(u,f))}):this._idbstore(yt,function(i,u,f){var e=t?f.put(n,t):f.put(n);e.onerror=o(u,["putting",n,"into",r.name]);e.onsuccess=function(t){var r=f.keyPath;r&&h(n,r,t.target.result);i(e.result)}})},"delete":function(n){return this.hook.deleting.subscribers.length?this.where(":id").equals(n).delete():this._idbstore(yt,function(t,i,r){var u=r.delete(n);u.onerror=o(i,["deleting",n,"from",r.name]);u.onsuccess=function(){t(u.result)}})},clear:function(){return this.hook.deleting.subscribers.length?this.toCollection().delete():this._idbstore(yt,function(n,t,i){var r=i.clear();r.onerror=o(t,["clearing",i.name]);r.onsuccess=function(){n(r.result)}})},update:function(n,t){if(typeof t!="object"||Array.isArray(t))throw new g("db.update(keyOrObject, modifications). modifications must be an object.");if(typeof n!="object"||Array.isArray(n))return this.where(":id").equals(n).modify(t);Object.keys(t).forEach(function(i){h(n,i,t[i])});var u=c(n,this.schema.primKey.keyPath);return u===i&&r.reject(new g("Object does not contain its primary key")),this.where(":id").equals(u).modify(t)}}});s(ir.prototype,{_lock:function(){return++this._reculock,this._reculock===1&&r.PSD&&(r.PSD.lockOwnerFor=this),this},_unlock:function(){if(--this._reculock==0)for(r.PSD&&(r.PSD.lockOwnerFor=null);this._blockedFuncs.length>0&&!this._locked();){var n=this._blockedFuncs.shift();try{n()}catch(t){}}return this},_locked:function(){return this._reculock&&(!r.PSD||r.PSD.lockOwnerFor!==this)},_nop:function(n){this.tables[this.storeNames[0]].get(0).then(n)},_promise:function(n,t,i){var f=this;return r.newPSD(function(){var e;return f._locked()?e=new r(function(r,u){f._blockedFuncs.push(function(){f._promise(n,t,i).then(r,u)})}):(e=f.active?new r(function(r,e){if(!f.idbtrans&&n){if(!et)throw fi?new g("Database not open. Following error in populate, ready or upgrade function made Dexie.open() fail: "+fi):new g("Database not open");var o=f.idbtrans=et.transaction(ft(f.storeNames),f.mode);o.onerror=function(n){f.on("error").fire(n&&n.target.error);n.preventDefault();f.abort()};o.onabort=function(n){f.active=!1;f.on("abort").fire(n)};o.oncomplete=function(n){f.active=!1;f.on("complete").fire(n)}}i&&f._lock();try{t(r,e,f)}catch(s){u.ignoreTransaction(function(){f.on("error").fire(s)});f.abort();e(s)}}):r.reject(gt(new g("Transaction is inactive. Original Scope Function Source: "+f.scopeFunc.toString()))),f.active&&i&&e.finally(function(){f._unlock()})),e.onuncatched=function(n){u.ignoreTransaction(function(){f.on("error").fire(n)});f.abort()},e})},complete:function(n){return this.on("complete",n)},error:function(n){return this.on("error",n)},abort:function(){if(this.idbtrans&&this.active)try{this.active=!1;this.idbtrans.abort();this.on.error.fire(new g("Transaction Aborted"))}catch(n){}},table:function(n){if(!this.tables.hasOwnProperty(n))throw new g("Table "+n+" not in transaction");return this.tables[n]}});s(ci.prototype,function(){function n(n,t){try{throw t;}catch(i){n._ctx.error=i}return n}function i(n){return Array.prototype.slice.call(n.length===1&&Array.isArray(n[0])?n[0]:n)}function r(n){return n==="next"?function(n){return n.toUpperCase()}:function(n){return n.toLowerCase()}}function u(n){return n==="next"?function(n){return n.toLowerCase()}:function(n){return n.toUpperCase()}}function f(n,t,i,r,u,f){for(var h,s=Math.min(n.length,r.length),o=-1,e=0;e<s;++e){if(h=t[e],h!==r[e])return u(n[e],i[e])<0?n.substr(0,e)+i[e]+i.substr(e+1):u(n[e],r[e])<0?n.substr(0,e)+r[e]+i.substr(e+1):o>=0?n.substr(0,o)+t[o]+i.substr(o+1):null;u(n[e],h)<0&&(o=e)}return s<r.length&&f==="next"?n+i.substr(n.length):s<n.length&&f==="prev"?n.substr(0,i.length):o<0?null:n.substr(0,o)+r[o]+i.substr(o+1)}function t(n,t,i){function a(n){s=r(n);e=u(n);h=n==="next"?wi:or;c=s(i);o=e(i);l=n}var s,e,h,c,o,l;a("next");n._ondirectionchange=function(n){a(n)};n._addAlgorithm(function(n,i,r){var u=n.key,s,a;return typeof u!="string"?!1:(s=e(u),t(s,o)?(i(function(){n.continue()}),!0):(a=f(u,s,c,o,h,l),a?i(function(){n.continue(a)}):i(r),!1))})}return{between:function(n,t,i,r){return(i=i!==!1,r=r===!0,n>t||n===t&&(i||r)&&!(i&&r))?new this._ctx.collClass(this,function(){return kt.only(n)}).limit(0):new this._ctx.collClass(this,function(){return kt.bound(n,t,!i,!r)})},equals:function(n){return new this._ctx.collClass(this,function(){return kt.only(n)})},above:function(n){return new this._ctx.collClass(this,function(){return kt.lowerBound(n,!0)})},aboveOrEqual:function(n){return new this._ctx.collClass(this,function(){return kt.lowerBound(n)})},below:function(n){return new this._ctx.collClass(this,function(){return kt.upperBound(n,!0)})},belowOrEqual:function(n){return new this._ctx.collClass(this,function(){return kt.upperBound(n)})},startsWith:function(t){return typeof t!="string"?n(new this._ctx.collClass(this),new yi("String expected")):this.between(t,t+String.fromCharCode(65535),!0,!0)},startsWithIgnoreCase:function(i){if(typeof i!="string")return n(new this._ctx.collClass(this),new yi("String expected"));if(i==="")return this.startsWith(i);var r=new this._ctx.collClass(this,function(){return kt.bound(i.toUpperCase(),i.toLowerCase()+String.fromCharCode(65535))});return t(r,function(n,t){return n.indexOf(t)===0},i),r._ondirectionchange=function(){n(r,new g("reverse() not supported with WhereClause.startsWithIgnoreCase()"))},r},equalsIgnoreCase:function(i){if(typeof i!="string")return n(new this._ctx.collClass(this),new yi("String expected"));var r=new this._ctx.collClass(this,function(){return kt.bound(i.toUpperCase(),i.toLowerCase())});return t(r,function(n,t){return n===t},i),r},anyOf:function(){var f=this._ctx,e=f.table.schema,o=f.index?e.idxByName[f.index]:e.primKey,s=o&&o.compound,n=i(arguments),t=s?sr(wi):wi,u,r;return(n.sort(t),n.length===0)?new this._ctx.collClass(this,function(){return kt.only("")}).limit(0):(u=new this._ctx.collClass(this,function(){return kt.bound(n[0],n[n.length-1])}),u._ondirectionchange=function(i){t=i==="next"?wi:or;s&&(t=sr(t));n.sort(t)},r=0,u._addAlgorithm(function(i,u,f){for(var e=i.key;t(e,n[r])>0;)if(++r,r===n.length)return u(f),!1;return t(e,n[r])===0?(u(function(){i.continue()}),!0):(u(function(){i.continue(n[r])}),!1)}),u)}}});s(li.prototype,function(){function t(n,t){n.filter=bi(n.filter,t)}function f(n,t){n.isMatch=bi(n.isMatch,t)}function r(n,t){if(n.isPrimKey)return t;var i=n.table.schema.idxByName[n.index];if(!i)throw new g("KeyPath "+n.index+" on object store "+t.name+" is not indexed");return n.isPrimKey?t:t.index(i.name)}function u(n,t){return r(n,t)[n.op](n.range||null,n.dir+n.unique)}function i(n,t,i,r,f){n.or?function(){function e(){++c==2&&i()}function h(n,i,u){if(!o||o(i,u,e,r)){var f=i.primaryKey.toString();s.hasOwnProperty(f)||(s[f]=!0,t(n,i,u))}}var o=n.filter,s={},l=n.table.schema.primKey.keyPath,c=0;n.or._iterate(h,e,r,f);pi(u(n,f),n.algorithm,h,e,r,n.table.hook.reading.fire)}():pi(u(n,f),bi(n.algorithm,n.filter),t,i,r,n.table.hook.reading.fire)}function n(n){return n.table.schema.instanceTemplate}return{_read:function(n,t){var i=this._ctx;return i.error?i.table._trans(null,function(n,t){t(i.error)}):i.table._idbstore(ti,n).then(t)},_write:function(n){var t=this._ctx;return t.error?t.table._trans(null,function(n,i){i(t.error)}):t.table._idbstore(yt,n,"locked")},_addAlgorithm:function(n){var t=this._ctx;t.algorithm=bi(t.algorithm,n)},_iterate:function(n,t,r,u){return i(this._ctx,n,t,r,u)},each:function(t){var r=this._ctx;return e(function(){t(n(r))}),this._read(function(n,u,f){i(r,t,n,u,f)})},count:function(n){var f,t,u;return e(function(){n(0)}),f=this,t=this._ctx,t.filter||t.algorithm||t.or?(u=0,this._read(function(n,r,f){i(t,function(){return++u,!1},function(){n(u)},r,f)},n)):this._read(function(n,i,u){var e=r(t,u),s=t.range?e.count(t.range):e.count();s.onerror=o(i,["calling","count()","on",f.name]);s.onsuccess=function(i){n(Math.min(i.target.result,Math.max(0,t.limit-t.offset)))}},n)},sortBy:function(t,i){function u(n,t){return t?u(n[r[t]],t-1):n[h]}function c(n,t){var i=u(n,o),r=u(t,o);return i<r?-f:i>r?f:0}var s=this._ctx,f;e(function(){i([n(s)])});var r=t.split(".").reverse(),h=r[0],o=r.length-1;return f=this._ctx.dir==="next"?1:-1,this.toArray(function(n){return n.sort(c)}).then(i)},toArray:function(t){var r=this._ctx;return e(function(){t([n(r)])}),this._read(function(n,t,u){var f=[];i(r,function(n){f.push(n)},function(){n(f)},t,u)},t)},offset:function(n){var i=this._ctx;return n<=0?this:(i.offset+=n,i.or||i.algorithm||i.filter?t(i,function(){return--n<0}):t(i,function(t,i){return n===0?!0:n===1?(--n,!1):(i(function(){t.advance(n);n=0}),!1)}),this)},limit:function(n){return this._ctx.limit=Math.min(this._ctx.limit,n),t(this._ctx,function(t,i,r){return--n<=0&&i(r),n>=0}),this},until:function(i,r){var u=this._ctx;return e(function(){i(n(u))}),t(this._ctx,function(n,t,u){return i(n.value)?(t(u),r):!0}),this},first:function(t){var i=this;return e(function(){t(n(i._ctx))}),this.limit(1).toArray(function(n){return n[0]}).then(t)},last:function(n){return this.reverse().first(n)},and:function(i){var r=this;return e(function(){i(n(r._ctx))}),t(this._ctx,function(n){return i(n.value)}),f(this._ctx,i),this},or:function(n){return new ci(this._ctx.table,n,this)},reverse:function(){return this._ctx.dir=this._ctx.dir==="prev"?"next":"prev",this._ondirectionchange&&this._ondirectionchange(this._ctx.dir),this},desc:function(){return this.reverse()},eachKey:function(t){var i=this,r=this._ctx;return e(function(){t(n(i._ctx)[i._ctx.index])}),r.isPrimKey||(r.op="openKeyCursor"),this.each(function(n,i){t(i.key,i)})},eachUniqueKey:function(n){return this._ctx.unique="unique",this.eachKey(n)},keys:function(t){var u,i,r;return e(function(){t([n(i)[u._ctx.index]])}),u=this,i=this._ctx,i.isPrimKey||(i.op="openKeyCursor"),r=[],this.each(function(n,t){r.push(t.key)}).then(function(){return r}).then(t)},uniqueKeys:function(n){return this._ctx.unique="unique",this.keys(n)},firstKey:function(n){var t=this;return this.limit(1).keys(function(n){return n[0]}).then(n)},lastKey:function(n){return this.reverse().firstKey(n)},distinct:function(){var n={};return t(this._ctx,function(t){var i=t.primaryKey.toString(),r=n.hasOwnProperty(i);return n[i]=!0,!r}),this}}});y(rr).from(li).extend({modify:function(n){var a=this,t=this._ctx,r=t.table.hook,i=r.updating.fire,u=r.deleting.fire;return e(function(){typeof n=="function"&&n.call({value:t.table.schema.instanceTemplate},t.table.schema.instanceTemplate)}),this._write(function(r,e,v,y){function st(n,i){var r,u,f;if(et=i.primaryKey,r={primKey:i.primaryKey,value:n},w.call(r,n)!==!1)u=!r.hasOwnProperty("value"),f=u?i.delete():i.update(r.value),++ut,f.onerror=o(function(n){if(p.push(n),nt.push(r.primKey),r.onerror)r.onerror(n);return it(),!0},u?["deleting",n,"from",t.table.name]:["modifying",n,"on",t.table.name]),f.onsuccess=function(){if(r.onsuccess)r.onsuccess(r.value);++b;it()};else if(r.onsuccess)r.onsuccess(r.value)}function ot(n){return n&&(p.push(n),nt.push(et)),e(new d("Error modifying one or more objects",p,b,nt))}function it(){ft&&b+p.length===ut&&(p.length>0?ot():r(b))}var w,k,rt,g;typeof n=="function"?w=i===f&&u===f?n:function(t){var f=l(t),e,r;if(n.call(this,t)===!1)return!1;this.hasOwnProperty("value")?(e=dt(f,this.value),r=i.call(this,e,this.primKey,f,y),r&&(t=this.value,Object.keys(r).forEach(function(n){h(t,n,r[n])}))):u.call(this,this.primKey,t,y)}:i===f?(k=Object.keys(n),rt=k.length,w=function(t){for(var i,u,f=!1,r=0;r<rt;++r)i=k[r],u=n[i],c(t,i)!==u&&(h(t,i,u),f=!0);return f}):(g=n,n=tt(g),w=function(t){var u=!1,r=i.call(this,n,this.primKey,l(t),y);return r&&s(n,r),Object.keys(n).forEach(function(i){var r=n[i];c(t,i)!==r&&(h(t,i,r),u=!0)}),r&&(n=tt(g)),u});var ut=0,b=0,ft=!1,p=[],nt=[],et=null;a._iterate(st,function(){ft=!0;it()},ot,v)})},"delete":function(){return this.modify(function(){delete this.value})}});s(this,{Collection:li,Table:ei,Transaction:ir,Version:di,WhereClause:ci,WriteableCollection:rr,WriteableTable:tr});cr();hr.forEach(function(n){n(w)})}function f(){}function nt(n){return n}function lt(n,t){return n===nt?t:function(i){return t(n(i))}}function w(n,t){return function(){n.apply(this,arguments);t.apply(this,arguments)}}function at(n,t){return n===f?t:function(){var f=n.apply(this,arguments),r,u,e;return f!==i&&(arguments[0]=f),r=this.onsuccess,u=this.onerror,delete this.onsuccess,delete this.onerror,e=t.apply(this,arguments),r&&(this.onsuccess=this.onsuccess?w(r,this.onsuccess):r),u&&(this.onerror=this.onerror?w(u,this.onerror):u),e!==i?e:f}}function vt(n,t){return n===f?t:function(){var r=n.apply(this,arguments),f,e,u;return r!==i&&s(arguments[0],r),f=this.onsuccess,e=this.onerror,delete this.onsuccess,delete this.onerror,u=t.apply(this,arguments),f&&(this.onsuccess=this.onsuccess?w(f,this.onsuccess):f),e&&(this.onerror=this.onerror?w(e,this.onerror):e),r===i?u===i?i:u:u===i?r:s(r,u)}}function yt(n,t){return n===f?t:function(){return n.apply(this,arguments)===!1?!1:t.apply(this,arguments)}}function pt(n,t){return n===f?t:function(){return t.apply(this,arguments)===!1?!1:n.apply(this,arguments)}}function wt(n,t){return n===f?t:function(){n.apply(this,arguments);t.apply(this,arguments)}}function bt(n,t){return n===f?t:function(){var i=n.apply(this,arguments),r,u;return i&&typeof i.then=="function"?(r=this,u=arguments,i.then(function(){return t.apply(r,u)})):t.apply(this,arguments)}}function v(t){function i(n,t,i){if(Array.isArray(n))return c(n);if(typeof n=="object")return h(n);t||(t=yt);i||(i=f);var r={subscribers:[],fire:i,subscribe:function(n){r.subscribers.push(n);r.fire=t(r.fire,n)},unsubscribe:function(n){r.subscribers=r.subscribers.filter(function(t){return t!==n});r.fire=r.subscribers.reduce(t,i)}};return u[n]=e[n]=r,r}function h(t){Object.keys(t).forEach(function(r){var f=t[r],u;if(Array.isArray(f))i(r,t[r][0],t[r][1]);else if(f==="asap")u=i(r,null,function(){var t=arguments;u.subscribers.forEach(function(i){b(function(){i.apply(n,t)})})}),u.subscribe=function(n){u.subscribers.indexOf(n)===-1&&u.subscribers.push(n)},u.unsubscribe=function(n){var t=u.subscribers.indexOf(n);t!==-1&&u.subscribers.splice(t,1)};else throw new Error("Invalid event config");})}function c(n){function r(){if(t)return!1;t=!0}var t=!1;n.forEach(function(n){i(n).subscribe(r)})}var o=arguments,u={},e=function(n,i){if(i){var f=[].slice.call(arguments,1),r=u[n];return r.subscribe.apply(r,f),t}if(typeof n=="string")return u[n]},r,s;for(e.addEventType=i,r=1,s=o.length;r<s;++r)i(o[r]);return e}function kt(n){if(!n)throw new Error("Assertion failed");}function b(t){n.setImmediate?setImmediate(t):setTimeout(t,0)}function et(n){var t=setTimeout(n,1e3);clearTimeout(t)}function k(n,t,i){return function(){var u=r.PSD;r.PSD=i;try{n.apply(this,arguments)}catch(f){t(f)}finally{r.PSD=u}}}function c(n,t){var f,r,o,s,u,e;if(n.hasOwnProperty(t))return n[t];if(!t)return n;if(typeof t!="string"){for(f=[],r=0,o=t.length;r<o;++r)s=c(n,t[r]),f.push(s);return f}return(u=t.indexOf("."),u!==-1)?(e=n[t.substr(0,u)],e===i?i:c(e,t.substr(u+1))):i}function h(n,t,r){var u,c,e,f,s,o;if(n&&t!==i)if(typeof t!="string"&&"length"in t)for(kt(typeof r!="string"&&"length"in r),u=0,c=t.length;u<c;++u)h(n,t[u],r[u]);else e=t.indexOf("."),e!==-1?(f=t.substr(0,e),s=t.substr(e+1),s===""?r===i?delete n[f]:n[f]=r:(o=n[f],o||(o=n[f]={}),h(o,s,r))):r===i?delete n[t]:n[t]=r}function ot(n,t){h(n,t,i)}function tt(n){var i={};for(var t in n)n.hasOwnProperty(t)&&(i[t]=n[t]);return i}function l(n){var t,i,u,r;if(!n||typeof n!="object")return n;if(Array.isArray(n))for(t=[],i=0,u=n.length;i<u;++i)t.push(l(n[i]));else if(n instanceof Date)t=new Date,t.setTime(n.getTime());else{t=n.constructor?Object.create(n.constructor.prototype):{};for(r in n)n.hasOwnProperty(r)&&(t[r]=l(n[r]))}return t}function dt(n,t){var u={};for(var r in n)n.hasOwnProperty(r)&&(t.hasOwnProperty(r)?n[r]!==t[r]&&JSON.stringify(n[r])!=JSON.stringify(t[r])&&(u[r]=t[r]):u[r]=i);for(r in t)t.hasOwnProperty(r)&&!n.hasOwnProperty(r)&&(u[r]=t[r]);return u}function st(n){if(typeof n=="function")return new n;if(Array.isArray(n))return[st(n[0])];if(n&&typeof n=="object"){var t={};return it(t,n),t}return n}function it(n,t){Object.keys(t).forEach(function(i){var r=st(t[i]);n[i]=r})}function o(n,t){return function(i){var r=i&&i.target.error||new Error,u;return t&&(u=" occurred when "+t.map(function(n){switch(typeof n){case"function":return n();case"string":return n;default:return JSON.stringify(n)}}).join(" "),r.name?r.toString=function(){return r.name+u+(r.message?". "+r.message:"")}:r=r+u),n(r),i&&(i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault()),!1}}function gt(n){try{throw n;}catch(t){return t}}function ht(n){n.preventDefault()}function rt(n){var t,i=u.dependencies.localStorage;if(!i)return n([]);try{t=JSON.parse(i.getItem("Dexie.DatabaseNames")||"[]")}catch(r){t=[]}n(t)&&i.setItem("Dexie.DatabaseNames",JSON.stringify(t))}function a(n,t,i,r,u,f,e){this.name=n;this.keyPath=t;this.unique=i;this.multi=r;this.auto=u;this.compound=f;this.dotted=e;var o=typeof t=="string"?t:t&&"["+[].join.call(t,"+")+"]";this.src=(i?"&":"")+(r?"*":"")+(u?"++":"")+o}function ut(n,t,i,r){this.name=n;this.primKey=t||new a;this.indexes=i||[new a];this.instanceTemplate=r;this.mappedClass=null;this.idxByName=i.reduce(function(n,t){return n[t.name]=t,n},{})}function d(n,t,i,r){this.name="ModifyError";this.failures=t;this.failedKeys=r;this.successCount=i;this.message=t.join("\n")}function ft(n){return n.length===1?n[0]:n}function ct(){var n=u.dependencies.indexedDB,t=n&&(n.getDatabaseNames||n.webkitGetDatabaseNames);return t&&t.bind(n)}var r=function(){function y(n){u.push([n,a.call(arguments,1)])}function p(){var r=u,t,f,i;for(u=[],t=0,f=r.length;t<f;++t)i=r[t],i[0].apply(n,i[1])}function t(n){if(typeof this!="object")throw new TypeError("Promises must be constructed via new");if(typeof n!="function")throw new TypeError("not a function");this._state=null;this._value=null;this._deferreds=[];this._catched=!1;var r=this,u=!0;this._PSD=t.PSD;try{k(this,n,function(n){u?i(c,r,n):c(r,n)},function(n){return u?(i(s,r,n),!1):s(r,n)})}finally{u=!1}}function o(n,f){var s,o,l,a,b,c;if(n._state===null){n._deferreds.push(f);return}if(s=n._state?f.onFulfilled:f.onRejected,s===null)return(n._state?f.resolve:f.reject)(n._value);l=r;r=!1;i=y;try{a=t.PSD;t.PSD=n._PSD;o=s(n._value);n._state||o&&typeof o.then=="function"&&o._state===!1||w(n);f.resolve(o)}catch(v){if(b=f.reject(v),!b&&n.onuncatched)try{n.onuncatched(v)}catch(v){}}finally{if(t.PSD=a,l){do{while(u.length>0)p();if(c=e.pop(),c)try{c()}catch(v){}}while(e.length>0||u.length>0);i=h;r=!0}}}function d(n){var f=r,t;r=!1;i=y;try{n()}finally{if(f){do{while(u.length>0)p();if(t=e.pop(),t)try{t()}catch(o){}}while(e.length>0||u.length>0);i=h;r=!0}}}function w(n){n._catched=!0;n._parent&&w(n._parent)}function c(n,i){var r=t.PSD;t.PSD=n._PSD;try{if(i===n)throw new TypeError("A promise cannot be resolved with itself.");if(i&&(typeof i=="object"||typeof i=="function")&&typeof i.then=="function"){k(n,function(n,t){i.then(n,t)},function(t){c(n,t)},function(t){s(n,t)});return}n._state=!0;n._value=i;b.call(n)}catch(u){s(u)}finally{t.PSD=r}}function s(n,i){var r=t.PSD;if(t.PSD=n._PSD,n._state=!1,n._value=i,b.call(n),!n._catched)try{if(n.onuncatched)n.onuncatched(n._value);t.on.error.fire(n._value)}catch(u){}return t.PSD=r,n._catched}function b(){for(var n=0,t=this._deferreds.length;n<t;n++)o(this,this._deferreds[n]);this._deferreds=[]}function l(n,t,i,r){this.onFulfilled=typeof n=="function"?n:null;this.onRejected=typeof t=="function"?t:null;this.resolve=i;this.reject=r}function k(n,t,i,r){var u=!1;try{t(function(n){u||(u=!0,i(n))},function(t){return u?n._catched:(u=!0,r(t))})}catch(f){return u?void 0:r(f)}}var a=[].slice,h=typeof setImmediate=="undefined"?function(t){var i=arguments;setTimeout(function(){t.apply(n,a.call(i,1))},0)}:setImmediate,i=h,r=!0,u=[],e=[];return t.on=v(null,"error"),t.all=function(){var n=Array.prototype.slice.call(arguments.length===1&&Array.isArray(arguments[0])?arguments[0]:arguments);return new t(function(t,i){function f(r,e){try{if(e&&(typeof e=="object"||typeof e=="function")){var o=e.then;if(typeof o=="function"){o.call(e,function(n){f(r,n)},i);return}}n[r]=e;--u==0&&t(n)}catch(s){i(s)}}var u,r;if(n.length===0)return t([]);for(u=n.length,r=0;r<n.length;r++)f(r,n[r])})},t.prototype.then=function(n,r){var f=this,u=new t(function(t,u){f._state===null?o(f,new l(n,r,t,u)):i(o,f,new l(n,r,t,u))});return u._PSD=this._PSD,u.onuncatched=this.onuncatched,u._parent=this,u},t.prototype._then=function(n,t){o(this,new l(n,t,f,f))},t.prototype["catch"]=function(n){if(arguments.length===1)return this.then(null,n);var i=arguments[0],r=arguments[1];return typeof i=="function"?this.then(null,function(n){return n instanceof i?r(n):t.reject(n)}):this.then(null,function(n){return n&&n.name===i?r(n):t.reject(n)})},t.prototype["finally"]=function(n){return this.then(function(t){return n(),t},function(i){return n(),t.reject(i)})},t.prototype.onuncatched=null,t.resolve=function(n){var i=new t(function(){});return i._state=!0,i._value=n,i},t.reject=function(n){var i=new t(function(){});return i._state=!1,i._value=n,i},t.race=function(n){return new t(function(t,i){n.map(function(n){n.then(t,i)})})},t.PSD=null,t.newPSD=function(n){var i=t.PSD;t.PSD=i?Object.create(i):{};try{return n()}finally{t.PSD=i}},t._rootExec=d,t._tickFinalize=function(n){if(r)throw new Error("Not in a virtual tick");e.push(n)},t}(),e=function(){},g;y(d).from(Error);u.delete=function(n){var t=new u(n),i=t.delete();return i.onblocked=function(n){t.on("blocked",n);return this},i};u.getDatabaseNames=function(n){return new r(function(n,t){var r=ct(),i;r?(i=r(),i.onsuccess=function(t){n([].slice.call(t.target.result,0))},i.onerror=o(t)):rt(function(t){return n(t),!1})}).then(n)};u.defineClass=function(n){function t(n){n&&s(this,n)}return it(t.prototype,n),t};u.ignoreTransaction=function(n){return r.newPSD(function(){return r.PSD.trans=null,n()})};u.spawn=function(){return n.console&&console.warn("Dexie.spawn() is deprecated. Use Dexie.ignoreTransaction() instead."),u.ignoreTransaction.apply(this,arguments)};u.vip=function(n){return r.newPSD(function(){return r.PSD.letThrough=!0,n()})};Object.defineProperty(u,"currentTransaction",{get:function(){return r.PSD&&r.PSD.trans||null}});u.Promise=r;u.derive=y;u.extend=s;u.override=p;u.events=v;u.getByKeyPath=c;u.setByKeyPath=h;u.delByKeyPath=ot;u.shallowClone=tt;u.deepClone=l;u.addons=[];u.fakeAutoComplete=e;u.asap=b;u.ModifyError=d;u.MultiModifyError=d;u.IndexSpec=a;u.TableSchema=ut;g=n.idbModules&&n.idbModules.shimIndexedDB?n.idbModules:{};u.dependencies={indexedDB:g.shimIndexedDB||n.indexedDB||n.mozIndexedDB||n.webkitIndexedDB||n.msIndexedDB,IDBKeyRange:g.IDBKeyRange||n.IDBKeyRange||n.webkitIDBKeyRange,IDBTransaction:g.IDBTransaction||n.IDBTransaction||n.webkitIDBTransaction,Error:n.Error||String,SyntaxError:n.SyntaxError||String,TypeError:n.TypeError||String,DOMError:n.DOMError||String,localStorage:(typeof chrome!="undefined"&&chrome!==null?chrome.storage:void 0)!=null?null:n.localStorage};u.version=1.1;t("Dexie",u);et(function(){e=et})}).apply(null,typeof define=="function"&&define.amd?[self||window,function(n,t){define(n,function(){return t})}]:typeof global!="undefined"&&typeof module!="undefined"&&module.exports?[global,function(n,t){module.exports=t}]:[self||window,function(n,t){(self||window)[n]=t}]);
+//# sourceMappingURL=Dexie.min.js.map
diff --git a/gui/html/js/ndn-js.min.js b/gui/html/js/ndn-js.min.js
index 092e995..c73b511 100644
--- a/gui/html/js/ndn-js.min.js
+++ b/gui/html/js/ndn-js.min.js
@@ -1,224 +1,165 @@
-var Closure=function(){this.ndn_data=null;this.ndn_data_dirty=!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 WebSocketTransport=function(){if(!WebSocket)throw Error("WebSocket support is not available on this platform.");this.elementReader=this.connectedPort=this.connectedHost=this.ws=null;this.defaultGetHostAndPort=NDN.makeShuffledGetHostAndPort(["A.ws.ndn.ucla.edu","B.ws.ndn.ucla.edu","C.ws.ndn.ucla.edu","D.ws.ndn.ucla.edu","E.ws.ndn.ucla.edu"],9696)};
-WebSocketTransport.prototype.connect=function(a,b){null!=this.ws&&delete this.ws;this.ws=new WebSocket("ws://"+a.host+":"+a.port);0<LOG&&console.log("ws connection created.");this.connectedHost=a.host;this.connectedPort=a.port;this.ws.binaryType="arraybuffer";this.elementReader=new BinaryXmlElementReader(a);var c=this;this.ws.onmessage=function(a){a=a.data;if(null==a||void 0==a||""==a)console.log("INVALID ANSWER");else if(a instanceof ArrayBuffer){a=new Uint8Array(a);3<LOG&&console.log("BINARY RESPONSE IS "+
-DataUtils.toHex(a));try{c.elementReader.onReceivedData(a)}catch(b){console.log("NDN.ws.onmessage exception: "+b)}}};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);b()};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.");
-c.ws=null;a.readyStatus=NDN.CLOSED;a.onclose()}};WebSocketTransport.prototype.send=function(a){if(null!=this.ws){var b=new Uint8Array(a.length);b.set(a);this.ws.send(b.buffer);3<LOG&&console.log("ws.send() returned.")}else console.log("WebSocket connection is not established.")};
-var NDNProtocolDTags={Any:13,Name:14,Component:15,Certificate:16,Collection:17,CompleteName:18,Content:19,SignedInfo:20,ContentDigest:21,ContentHash:22,Count:24,Header:25,Interest:26,Key:27,KeyLocator:28,KeyName:29,Length:30,Link:31,LinkAuthenticator:32,NameComponentCount:33,RootDigest:36,Signature:37,Start:38,Timestamp:39,Type:40,Nonce:41,Scope:42,Exclude:43,Bloom:44,BloomSeed:45,AnswerOriginKind:47,InterestLifetime:48,Witness:53,SignatureBits:54,DigestAlgorithm:55,BlockSize:56,FreshnessSeconds:58,
-FinalBlockID:59,PublisherPublicKeyDigest:60,PublisherCertificateDigest:61,PublisherIssuerKeyDigest:62,PublisherIssuerCertificateDigest:63,ContentObject:64,WrappedKey:65,WrappingKeyIdentifier:66,WrapAlgorithm:67,KeyAlgorithm:68,Label:69,EncryptedKey:70,EncryptedNonceKey:71,WrappingKeyName:72,Action:73,FaceID:74,IPProto:75,Host:76,Port:77,MulticastInterface:78,ForwardingFlags:79,FaceInstance:80,ForwardingEntry:81,MulticastTTL:82,MinSuffixComponents:83,MaxSuffixComponents:84,ChildSelector:85,RepositoryInfo:86,
-Version:87,RepositoryVersion:88,GlobalPrefix:89,LocalName:90,Policy:91,Namespace:92,GlobalPrefixName:93,PolicyVersion:94,KeyValueSet:95,KeyValuePair:96,IntegerValue:97,DecimalValue:98,StringValue:99,BinaryValue:100,NameValue:101,Entry:102,ACL:103,ParameterizedName:104,Prefix:105,Suffix:106,Root:107,ProfileName:108,Parameters:109,InfoString:110,StatusResponse:112,StatusCode:113,StatusText:114,SyncNode:115,SyncNodeKind:116,SyncNodeElement:117,SyncVersion:118,SyncNodeElements:119,SyncContentHash:120,
-SyncLeafCount:121,SyncTreeDepth:122,SyncByteCount:123,ConfigSlice:124,ConfigSliceList:125,ConfigSliceOp:126,NDNProtocolDataUnit:17702112,NDNPROTOCOL_DATA_UNIT:"NDNProtocolDataUnit"},NDNProtocolDTagsStrings=[null,null,null,null,null,null,null,null,null,null,null,null,null,"Any","Name","Component","Certificate","Collection","CompleteName","Content","SignedInfo","ContentDigest","ContentHash",null,"Count","Header","Interest","Key","KeyLocator","KeyName","Length","Link","LinkAuthenticator","NameComponentCount",
-null,null,"RootDigest","Signature","Start","Timestamp","Type","Nonce","Scope","Exclude","Bloom","BloomSeed",null,"AnswerOriginKind","InterestLifetime",null,null,null,null,"Witness","SignatureBits","DigestAlgorithm","BlockSize",null,"FreshnessSeconds","FinalBlockID","PublisherPublicKeyDigest","PublisherCertificateDigest","PublisherIssuerKeyDigest","PublisherIssuerCertificateDigest","ContentObject","WrappedKey","WrappingKeyIdentifier","WrapAlgorithm","KeyAlgorithm","Label","EncryptedKey","EncryptedNonceKey",
-"WrappingKeyName","Action","FaceID","IPProto","Host","Port","MulticastInterface","ForwardingFlags","FaceInstance","ForwardingEntry","MulticastTTL","MinSuffixComponents","MaxSuffixComponents","ChildSelector","RepositoryInfo","Version","RepositoryVersion","GlobalPrefix","LocalName","Policy","Namespace","GlobalPrefixName","PolicyVersion","KeyValueSet","KeyValuePair","IntegerValue","DecimalValue","StringValue","BinaryValue","NameValue","Entry","ACL","ParameterizedName","Prefix","Suffix","Root","ProfileName",
-"Parameters","InfoString",null,"StatusResponse","StatusCode","StatusText","SyncNode","SyncNodeKind","SyncNodeElement","SyncVersion","SyncNodeElements","SyncContentHash","SyncLeafCount","SyncTreeDepth","SyncByteCount","ConfigSlice","ConfigSliceList","ConfigSliceOp"],NDNTime=function(a){this.NANOS_MAX=999877929;"number"==typeof a?this.msec=a:1<LOG&&console.log("UNRECOGNIZED TYPE FOR TIME")};NDNTime.prototype.getJavascriptDate=function(){var a=new Date;a.setTime(this.msec);return a};
-var ExponentialReExpressClosure=function(a,b){Closure.call(this);this.callerClosure=a;b=b||{};this.maxInterestLifetime=b.maxInterestLifetime||16E3};
-ExponentialReExpressClosure.prototype.upcall=function(a,b){try{if(a==Closure.UPCALL_INTEREST_TIMED_OUT){var c=b.interest.interestLifetime;if(null==c)return this.callerClosure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,b);c*=2;if(c>this.maxInterestLifetime)return this.callerClosure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,b);var d=b.interest.clone();d.interestLifetime=c;b.ndn.expressInterest(d.name,this,d);return Closure.RESULT_OK}return this.callerClosure.upcall(a,b)}catch(e){return console.log("ExponentialReExpressClosure.upcall exception: "+
-e),Closure.RESULT_ERR}};var Name=function Name(b){if("string"==typeof b)3<LOG&&console.log("Content Name String "+b),this.components=Name.createNameArray(b);else if("object"===typeof b)if(this.components=[],b instanceof Name)this.add(b);else for(var c=0;c<b.length;++c)this.add(b[c]);else null==b?this.components=[]:1<LOG&&console.log("NO CONTENT NAME GIVEN")};Name.prototype.getName=function(){return this.to_uri()};
-Name.createNameArray=function(a){a=a.trim();if(0>=a.length)return[];var b=a.indexOf(":");if(0<=b){var c=a.indexOf("/");if(0>c||b<c)a=a.substr(b+1,a.length-b-1).trim()}if("/"==a[0])if(2<=a.length&&"/"==a[1]){b=a.indexOf("/",2);if(0>b)return[];a=a.substr(b+1,a.length-b-1).trim()}else a=a.substr(1,a.length-1).trim();a=a.split("/");for(b=0;b<a.length;++b)c=Name.fromEscapedString(a[b]),null==c?(a.splice(b,1),--b):a[b]=c;return a};
-Name.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());for(this.components=[];a.peekStartElement(NDNProtocolDTags.Component);)this.add(a.readBinaryElement(NDNProtocolDTags.Component));a.readEndElement()};Name.prototype.to_ndnb=function(a){if(null==this.components)throw Error("CANNOT ENCODE EMPTY CONTENT NAME");a.writeStartElement(this.getElementLabel());for(var b=this.components.length,c=0;c<b;c++)a.writeElement(NDNProtocolDTags.Component,this.components[c]);a.writeEndElement()};
-Name.prototype.getElementLabel=function(){return NDNProtocolDTags.Name};
-Name.prototype.add=function(a){var b;if("string"==typeof a)b=DataUtils.stringToUtf8Array(a);else if("object"==typeof a&&a instanceof Uint8Array)b=new Uint8Array(a);else if("object"==typeof a&&a instanceof ArrayBuffer)b=new Uint8Array(new ArrayBuffer(a.byteLength)),b.set(new Uint8Array(a));else{if("object"==typeof a&&a instanceof Name){a=a==this?this.components.slice(0,this.components.length):a.components;for(b=0;b<a.length;++b)this.components.push(new Uint8Array(a[b]));return this}if("object"==typeof a)b=
-new Uint8Array(a);else throw Error("Cannot add Name element at index "+this.components.length+": Invalid type");}this.components.push(b);return this};Name.prototype.addSegment=function(a){for(var b=1,c=a;0<c;)b++,c>>=8;b=new Uint8Array(b);c=0;b[c]=0;for(c++;0<a;)b[c]=a&255,a>>=8,c++;this.components.push(b);return this};Name.prototype.to_uri=function(){if(0==this.components.length)return"/";for(var a="",b=0;b<this.components.length;++b)a+="/"+Name.toEscapedString(this.components[b]);return a};
-Name.prototype.addSegment=function(a){a=DataUtils.nonNegativeIntToBigEndian(a);var b=new Uint8Array(a.length+1);b.set(a,1);this.components.push(b);return this};Name.prototype.getPrefix=function(a){return new Name(this.components.slice(0,a))};Name.prototype.cut=function(){return new Name(this.components.slice(0,this.components.length-1))};Name.prototype.getComponent=function(a){var b=new ArrayBuffer(this.components[a].length);(new Uint8Array(b)).set(this.components[a]);return b};
-Name.prototype.indexOfFileName=function(){for(var a=this.components.length-1;0<=a;--a){var b=this.components[a];if(!(0>=b.length)&&!(0==b[0]||192==b[0]||193==b[0]||245<=b[0]&&255>=b[0]))return a}return-1};Name.prototype.equalsName=function(a){if(this.components.length!=a.components.length)return!1;for(var b=this.components.length-1;0<=b;--b)if(!DataUtils.arraysEqual(this.components[b],a.components[b]))return!1;return!0};
-Name.prototype.getContentDigestValue=function(){for(var a=this.components.length-1;0<=a;--a){var b=Name.getComponentContentDigestValue(this.components[a]);if(null!=b)return b}return null};
-Name.getComponentContentDigestValue=function(a){return a.length==Name.ContentDigestPrefix.length+32+Name.ContentDigestSuffix.length&&DataUtils.arraysEqual(a.subarray(0,Name.ContentDigestPrefix.length),Name.ContentDigestPrefix)&&DataUtils.arraysEqual(a.subarray(a.length-Name.ContentDigestSuffix.length,a.length),Name.ContentDigestSuffix)?a.subarray(Name.ContentDigestPrefix.length,Name.ContentDigestPrefix.length+32):null};Name.ContentDigestPrefix=new Uint8Array([193,46,77,46,71,193,1,170,2,133]);
-Name.ContentDigestSuffix=new Uint8Array([0]);Name.toEscapedString=function(a){for(var b="",c=!1,d=0;d<a.length;++d)if(46!=a[d]){c=!0;break}if(c)for(d=0;d<a.length;++d)c=a[d],b=48<=c&&57>=c||65<=c&&90>=c||97<=c&&122>=c||43==c||45==c||46==c||95==c?b+String.fromCharCode(c):b+("%"+(16>c?"0":"")+c.toString(16).toUpperCase());else{b="...";for(d=0;d<a.length;++d)b+="."}return b};
-Name.fromEscapedString=function(a){a=unescape(a.trim());return null==a.match(/[^.]/)?2>=a.length?null:DataUtils.toNumbersFromString(a.substr(3,a.length-3)):DataUtils.toNumbersFromString(a)};Name.prototype.match=function(a){var b=this.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 ContentObject=function(a,b,c,d){this.name="string"==typeof a?new Name(a):a;this.signedInfo=b;this.content="string"==typeof c?DataUtils.toNumbersFromString(c):c;this.signature=d;this.rawSignatureData=this.endContent=this.endSIG=this.startSIG=null};
-ContentObject.prototype.sign=function(){var a=this.encodeObject(this.name),b=this.encodeObject(this.signedInfo),c=this.encodeContent(),d=new ArrayBuffer(a.length+b.length+c.length),d=new Uint8Array(d);d.set(a,0);d.set(b,a.length);d.set(c,a.length+b.length);4<LOG&&console.log("Signature Data is (binary) "+d);4<LOG&&console.log("Signature Data is (RawString)");4<LOG&&console.log(DataUtils.toString(d));a=new RSAKey;a.readPrivateKeyFromPEMString(globalKeyManager.privateKey);a=a.signByteArrayWithSHA256(d);
-4<LOG&&console.log("SIGNATURE SAVED IS");4<LOG&&console.log(a);4<LOG&&console.log(DataUtils.toNumbers(a.trim()));this.signature.signature=DataUtils.toNumbers(a.trim())};ContentObject.prototype.encodeObject=function(a){var b=new BinaryXMLEncoder;a.to_ndnb(b);return b.getReducedOstream()};ContentObject.prototype.encodeContent=function(){var a=new BinaryXMLEncoder;a.writeElement(NDNProtocolDTags.Content,this.content);return a.getReducedOstream()};
-ContentObject.prototype.saveRawData=function(a){this.rawSignatureData=a.subarray(this.startSIG,this.endSIG)};
-ContentObject.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(NDNProtocolDTags.Signature)&&(this.signature=new Signature,this.signature.from_ndnb(a));this.startSIG=a.offset;this.name=new Name;this.name.from_ndnb(a);a.peekStartElement(NDNProtocolDTags.SignedInfo)&&(this.signedInfo=new SignedInfo,this.signedInfo.from_ndnb(a));this.content=a.readBinaryElement(NDNProtocolDTags.Content);this.endSIG=a.offset;a.readEndElement();this.saveRawData(a.istream)};
-ContentObject.prototype.to_ndnb=function(a){a.writeStartElement(this.getElementLabel());null!=this.signature&&this.signature.to_ndnb(a);this.startSIG=a.offset;null!=this.name&&this.name.to_ndnb(a);null!=this.signedInfo&&this.signedInfo.to_ndnb(a);a.writeElement(NDNProtocolDTags.Content,this.content);this.endSIG=a.offset;a.writeEndElement();this.saveRawData(a.ostream)};ContentObject.prototype.getElementLabel=function(){return NDNProtocolDTags.ContentObject};
-var Signature=function(a,b,c){this.Witness=a;this.signature=b;this.digestAlgorithm=c};
-Signature.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());4<LOG&&console.log("STARTED DECODING SIGNATURE");a.peekStartElement(NDNProtocolDTags.DigestAlgorithm)&&(4<LOG&&console.log("DIGIEST ALGORITHM FOUND"),this.digestAlgorithm=a.readUTF8Element(NDNProtocolDTags.DigestAlgorithm));a.peekStartElement(NDNProtocolDTags.Witness)&&(4<LOG&&console.log("WITNESS FOUND"),this.Witness=a.readBinaryElement(NDNProtocolDTags.Witness));4<LOG&&console.log("SIGNATURE FOUND");this.signature=
-a.readBinaryElement(NDNProtocolDTags.SignatureBits);a.readEndElement()};
-Signature.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode: field values missing.");a.writeStartElement(this.getElementLabel());null!=this.digestAlgorithm&&!this.digestAlgorithm.equals(NDNDigestHelper.DEFAULT_DIGEST_ALGORITHM)&&a.writeElement(NDNProtocolDTags.DigestAlgorithm,OIDLookup.getDigestOID(this.DigestAlgorithm));null!=this.Witness&&a.writeElement(NDNProtocolDTags.Witness,this.Witness);a.writeElement(NDNProtocolDTags.SignatureBits,this.signature);a.writeEndElement()};
-Signature.prototype.getElementLabel=function(){return NDNProtocolDTags.Signature};Signature.prototype.validate=function(){return null!=this.signature};
-var ContentType={DATA:0,ENCR:1,GONE:2,KEY:3,LINK:4,NACK:5},ContentTypeValue={"0":787648,1:1101969,2:1631044,3:2639423,4:2917194,5:3408010},ContentTypeValueReverse={787648:0,1101969:1,1631044:2,2639423:3,2917194:4,3408010:5},SignedInfo=function(a,b,c,d,e,f){this.publisher=a;this.timestamp=b;this.type=c;this.locator=d;this.freshnessSeconds=e;this.finalBlockID=f;this.setFields()};
-SignedInfo.prototype.setFields=function(){var a=globalKeyManager.publicKey;4<LOG&&console.log("PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ");4<LOG&&console.log(a);var a=DataUtils.toNumbers(globalKeyManager.publicKey),b=hex_sha256_from_bytes(a);this.publisher=new PublisherPublicKeyDigest(DataUtils.toNumbers(b));b=(new Date).getTime();this.timestamp=new NDNTime(b);4<LOG&&console.log("TIME msec is");4<LOG&&console.log(this.timestamp.msec);this.type=0;4<LOG&&console.log("PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ");
-4<LOG&&console.log(a);this.locator=new KeyLocator(a,KeyLocatorType.KEY)};
-SignedInfo.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)&&(4<LOG&&console.log("DECODING PUBLISHER KEY"),this.publisher=new PublisherPublicKeyDigest,this.publisher.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.Timestamp)&&(4<LOG&&console.log("DECODING TIMESTAMP"),this.timestamp=a.readDateTime(NDNProtocolDTags.Timestamp));if(a.peekStartElement(NDNProtocolDTags.Type)){var b=a.readBinaryElement(NDNProtocolDTags.Type);
-4<LOG&&console.log("Binary Type of of Signed Info is "+b);this.type=b;if(null==this.type)throw Error("Cannot parse signedInfo type: bytes.");}else this.type=ContentType.DATA;a.peekStartElement(NDNProtocolDTags.FreshnessSeconds)&&(this.freshnessSeconds=a.readIntegerElement(NDNProtocolDTags.FreshnessSeconds),4<LOG&&console.log("FRESHNESS IN SECONDS IS "+this.freshnessSeconds));a.peekStartElement(NDNProtocolDTags.FinalBlockID)&&(4<LOG&&console.log("DECODING FINAL BLOCKID"),this.finalBlockID=a.readBinaryElement(NDNProtocolDTags.FinalBlockID));
-a.peekStartElement(NDNProtocolDTags.KeyLocator)&&(4<LOG&&console.log("DECODING KEY LOCATOR"),this.locator=new KeyLocator,this.locator.from_ndnb(a));a.readEndElement()};
-SignedInfo.prototype.to_ndnb=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_ndnb(a));null!=this.timestamp&&a.writeDateTime(NDNProtocolDTags.Timestamp,this.timestamp);null!=this.type&&0!=this.type&&a.writeElement(NDNProtocolDTags.type,this.type);null!=this.freshnessSeconds&&a.writeElement(NDNProtocolDTags.FreshnessSeconds,
-this.freshnessSeconds);null!=this.finalBlockID&&a.writeElement(NDNProtocolDTags.FinalBlockID,this.finalBlockID);null!=this.locator&&this.locator.to_ndnb(a);a.writeEndElement()};SignedInfo.prototype.valueToType=function(){return null};SignedInfo.prototype.getElementLabel=function(){return NDNProtocolDTags.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",l=e[j+"Date"](),n=e[j+"Day"](),m=e[j+"Month"](),p=e[j+"FullYear"](),k=e[j+"Hours"](),q=e[j+"Minutes"](),s=e[j+"Seconds"](),j=e[j+"Milliseconds"](),r=g?0:e.getTimezoneOffset(),t={d:l,dd:d(l),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:k%12||12,hh:d(k%12||12),H:k,HH:d(k),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>k?"a":"p",tt:12>k?"am":"pm",T:12>k?"A":"P",TT:12>k?"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<l%10?0:(10!=l%100-l%10)*l%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,l,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=l;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;
-Interest.ANSWER_STALE=4;Interest.MARK_STALE=16;Interest.DEFAULT_ANSWER_ORIGIN_KIND=Interest.ANSWER_CONTENT_STORE|Interest.ANSWER_GENERATED;
-Interest.prototype.from_ndnb=function(a){a.readStartElement(NDNProtocolDTags.Interest);this.name=new Name;this.name.from_ndnb(a);a.peekStartElement(NDNProtocolDTags.MinSuffixComponents)&&(this.minSuffixComponents=a.readIntegerElement(NDNProtocolDTags.MinSuffixComponents));a.peekStartElement(NDNProtocolDTags.MaxSuffixComponents)&&(this.maxSuffixComponents=a.readIntegerElement(NDNProtocolDTags.MaxSuffixComponents));a.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)&&(this.publisherPublicKeyDigest=
-new PublisherPublicKeyDigest,this.publisherPublicKeyDigest.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.Exclude)&&(this.exclude=new Exclude,this.exclude.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.ChildSelector)&&(this.childSelector=a.readIntegerElement(NDNProtocolDTags.ChildSelector));a.peekStartElement(NDNProtocolDTags.AnswerOriginKind)&&(this.answerOriginKind=a.readIntegerElement(NDNProtocolDTags.AnswerOriginKind));a.peekStartElement(NDNProtocolDTags.Scope)&&(this.scope=a.readIntegerElement(NDNProtocolDTags.Scope));
-a.peekStartElement(NDNProtocolDTags.InterestLifetime)&&(this.interestLifetime=1E3*DataUtils.bigEndianToUnsignedInt(a.readBinaryElement(NDNProtocolDTags.InterestLifetime))/4096);a.peekStartElement(NDNProtocolDTags.Nonce)&&(this.nonce=a.readBinaryElement(NDNProtocolDTags.Nonce));a.readEndElement()};
-Interest.prototype.to_ndnb=function(a){a.writeStartElement(NDNProtocolDTags.Interest);this.name.to_ndnb(a);null!=this.minSuffixComponents&&a.writeElement(NDNProtocolDTags.MinSuffixComponents,this.minSuffixComponents);null!=this.maxSuffixComponents&&a.writeElement(NDNProtocolDTags.MaxSuffixComponents,this.maxSuffixComponents);null!=this.publisherPublicKeyDigest&&this.publisherPublicKeyDigest.to_ndnb(a);null!=this.exclude&&this.exclude.to_ndnb(a);null!=this.childSelector&&a.writeElement(NDNProtocolDTags.ChildSelector,
-this.childSelector);this.DEFAULT_ANSWER_ORIGIN_KIND!=this.answerOriginKind&&null!=this.answerOriginKind&&a.writeElement(NDNProtocolDTags.AnswerOriginKind,this.answerOriginKind);null!=this.scope&&a.writeElement(NDNProtocolDTags.Scope,this.scope);null!=this.interestLifetime&&a.writeElement(NDNProtocolDTags.InterestLifetime,DataUtils.nonNegativeIntToBigEndian(4096*(this.interestLifetime/1E3)));null!=this.nonce&&a.writeElement(NDNProtocolDTags.Nonce,this.nonce);a.writeEndElement()};
-Interest.prototype.matches_name=function(a){return!this.name.match(a)||null!=this.minSuffixComponents&&!(a.components.length+1-this.name.components.length>=this.minSuffixComponents)||null!=this.maxSuffixComponents&&!(a.components.length+1-this.name.components.length<=this.maxSuffixComponents)||null!=this.exclude&&a.components.length>this.name.components.length&&this.exclude.matches(a.components[this.name.components.length])?!1:!0};
-Interest.prototype.clone=function(){return new Interest(this.name,this.faceInstance,this.minSuffixComponents,this.maxSuffixComponents,this.publisherPublicKeyDigest,this.exclude,this.childSelector,this.answerOriginKind,this.scope,this.interestLifetime,this.nonce)};var Exclude=function(a){this.values=a||[]};Exclude.ANY="*";
-Exclude.prototype.from_ndnb=function(a){for(a.readStartElement(NDNProtocolDTags.Exclude);;)if(a.peekStartElement(NDNProtocolDTags.Component))this.values.push(a.readBinaryElement(NDNProtocolDTags.Component));else if(a.peekStartElement(NDNProtocolDTags.Any))a.readStartElement(NDNProtocolDTags.Any),a.readEndElement(),this.values.push(Exclude.ANY);else if(a.peekStartElement(NDNProtocolDTags.Bloom))a.readBinaryElement(NDNProtocolDTags.Bloom),this.values.push(Exclude.ANY);else break;a.readEndElement()};
-Exclude.prototype.to_ndnb=function(a){if(!(null==this.values||0==this.values.length)){a.writeStartElement(NDNProtocolDTags.Exclude);for(var b=0;b<this.values.length;++b)this.values[b]==Exclude.ANY?(a.writeStartElement(NDNProtocolDTags.Any),a.writeEndElement()):a.writeElement(NDNProtocolDTags.Component,this.values[b]);a.writeEndElement()}};
-Exclude.prototype.to_uri=function(){if(null==this.values||0==this.values.length)return"";for(var a="",b=0;b<this.values.length;++b)0<b&&(a+=","),a=this.values[b]==Exclude.ANY?a+"*":a+Name.toEscapedString(this.values[b]);return a};
-Exclude.prototype.matches=function(a){for(var b=0;b<this.values.length;++b)if(this.values[b]==Exclude.ANY){var c=null;0<b&&(c=this.values[b-1]);var d,e=null;for(d=b+1;d<this.values.length;++d)if(this.values[d]!=Exclude.ANY){e=this.values[d];break}if(null!=e){if(null!=c){if(0<Exclude.compareComponents(a,c)&&0>Exclude.compareComponents(a,e))return!0}else if(0>Exclude.compareComponents(a,e))return!0;b=d-1}else if(null!=c){if(0<Exclude.compareComponents(a,c))return!0}else return!0}else if(DataUtils.arraysEqual(a,
-this.values[b]))return!0;return!1};Exclude.compareComponents=function(a,b){if(a.length<b.length)return-1;if(a.length>b.length)return 1;for(var c=0;c<a.length;++c){if(a[c]<b[c])return-1;if(a[c]>b[c])return 1}return 0};
-var Key=function(){},KeyLocatorType={KEY:1,CERTIFICATE:2,KEYNAME:3},KeyLocator=function(a,b){this.type=b;b==KeyLocatorType.KEYNAME?(3<LOG&&console.log("KeyLocator: SET KEYNAME"),this.keyName=a):b==KeyLocatorType.KEY?(3<LOG&&console.log("KeyLocator: SET KEY"),this.publicKey=a):b==KeyLocatorType.CERTIFICATE&&(3<LOG&&console.log("KeyLocator: SET CERTIFICATE"),this.certificate=a)};
-KeyLocator.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());if(a.peekStartElement(NDNProtocolDTags.Key)){try{this.publicKey=a.readBinaryElement(NDNProtocolDTags.Key),this.type=KeyLocatorType.KEY,4<LOG&&console.log("PUBLIC KEY FOUND: "+this.publicKey)}catch(b){throw Error("Cannot parse key: ",b);}if(null==this.publicKey)throw Error("Cannot parse key: ");}else if(a.peekStartElement(NDNProtocolDTags.Certificate)){try{this.certificate=a.readBinaryElement(NDNProtocolDTags.Certificate),
-this.type=KeyLocatorType.CERTIFICATE,4<LOG&&console.log("CERTIFICATE FOUND: "+this.certificate)}catch(c){throw Error("Cannot decode certificate: "+c);}if(null==this.certificate)throw Error("Cannot parse certificate! ");}else this.type=KeyLocatorType.KEYNAME,this.keyName=new KeyName,this.keyName.from_ndnb(a);a.readEndElement()};
-KeyLocator.prototype.to_ndnb=function(a){4<LOG&&console.log("type is is "+this.type);if(!this.validate())throw new ContentEncodingException("Cannot encode "+this.getClass().getName()+": field values missing.");a.writeStartElement(this.getElementLabel());if(this.type==KeyLocatorType.KEY)5<LOG&&console.log("About to encode a public key"+this.publicKey),a.writeElement(NDNProtocolDTags.Key,this.publicKey);else if(this.type==KeyLocatorType.CERTIFICATE)try{a.writeElement(NDNProtocolDTags.Certificate,this.certificate)}catch(b){throw Error("CertificateEncodingException attempting to write key locator: "+
-b);}else this.type==KeyLocatorType.KEYNAME&&this.keyName.to_ndnb(a);a.writeEndElement()};KeyLocator.prototype.getElementLabel=function(){return NDNProtocolDTags.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_ndnb=function(a){a.readStartElement(this.getElementLabel());this.contentName=new Name;this.contentName.from_ndnb(a);4<LOG&&console.log("KEY NAME FOUND: ");PublisherID.peek(a)&&(this.publisherID=new PublisherID,this.publisherID.from_ndnb(a));a.readEndElement()};
-KeyName.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode : field values missing.");a.writeStartElement(this.getElementLabel());this.contentName.to_ndnb(a);null!=this.publisherID&&this.publisherID.to_ndnb(a);a.writeEndElement()};KeyName.prototype.getElementLabel=function(){return NDNProtocolDTags.KeyName};KeyName.prototype.validate=function(){return null!=this.contentName};
-var PublisherType=function(a){this.KEY=NDNProtocolDTags.PublisherPublicKeyDigest;this.CERTIFICATE=NDNProtocolDTags.PublisherCertificateDigest;this.ISSUER_KEY=NDNProtocolDTags.PublisherIssuerKeyDigest;this.ISSUER_CERTIFICATE=NDNProtocolDTags.PublisherIssuerCertificateDigest;this.Tag=a},isTypeTagVal=function(a){return a==NDNProtocolDTags.PublisherPublicKeyDigest||a==NDNProtocolDTags.PublisherCertificateDigest||a==NDNProtocolDTags.PublisherIssuerKeyDigest||a==NDNProtocolDTags.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_ndnb=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+"."));};
-PublisherID.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode "+this.getClass().getName()+": field values missing.");a.writeElement(this.getElementLabel(),this.publisherID)};PublisherID.peek=function(a){a=a.peekStartElementAsLong();return null==a?!1:isTypeTagVal(a)};PublisherID.prototype.getElementLabel=function(){return this.publisherType.Tag};PublisherID.prototype.validate=function(){return null!=id()&&null!=type()};
-var PublisherPublicKeyDigest=function(a){this.PUBLISHER_ID_LEN=64;this.publisherPublicKeyDigest=a};
-PublisherPublicKeyDigest.prototype.from_ndnb=function(a){this.publisherPublicKeyDigest=a.readBinaryElement(this.getElementLabel());4<LOG&&console.log("Publisher public key digest is "+this.publisherPublicKeyDigest);if(null==this.publisherPublicKeyDigest)throw Error("Cannot parse publisher key digest.");this.publisherPublicKeyDigest.length!=this.PUBLISHER_ID_LEN&&0<LOG&&console.log("LENGTH OF PUBLISHER ID IS WRONG! Expected "+this.PUBLISHER_ID_LEN+", got "+this.publisherPublicKeyDigest.length)};
-PublisherPublicKeyDigest.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode : field values missing.");3<LOG&&console.log("PUBLISHER KEY DIGEST IS"+this.publisherPublicKeyDigest);a.writeElement(this.getElementLabel(),this.publisherPublicKeyDigest)};PublisherPublicKeyDigest.prototype.getElementLabel=function(){return NDNProtocolDTags.PublisherPublicKeyDigest};PublisherPublicKeyDigest.prototype.validate=function(){return null!=this.publisherPublicKeyDigest};
-var NetworkProtocol={TCP:6,UDP:17},FaceInstance=function(a,b,c,d,e,f,g,h,j){this.action=a;this.publisherPublicKeyDigest=b;this.faceID=c;this.ipProto=d;this.host=e;this.Port=f;this.multicastInterface=g;this.multicastTTL=h;this.freshnessSeconds=j};
-FaceInstance.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(NDNProtocolDTags.Action)&&(this.action=a.readUTF8Element(NDNProtocolDTags.Action));a.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)&&(this.publisherPublicKeyDigest=new PublisherPublicKeyDigest,this.publisherPublicKeyDigest.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.FaceID)&&(this.faceID=a.readIntegerElement(NDNProtocolDTags.FaceID));if(a.peekStartElement(NDNProtocolDTags.IPProto)){var b=
-a.readIntegerElement(NDNProtocolDTags.IPProto);this.ipProto=null;if(NetworkProtocol.TCP==b)this.ipProto=NetworkProtocol.TCP;else if(NetworkProtocol.UDP==b)this.ipProto=NetworkProtocol.UDP;else throw Error("FaceInstance.decoder.  Invalid "+NDNProtocolDTags.tagToString(NDNProtocolDTags.IPProto)+" field: "+b);}a.peekStartElement(NDNProtocolDTags.Host)&&(this.host=a.readUTF8Element(NDNProtocolDTags.Host));a.peekStartElement(NDNProtocolDTags.Port)&&(this.Port=a.readIntegerElement(NDNProtocolDTags.Port));
-a.peekStartElement(NDNProtocolDTags.MulticastInterface)&&(this.multicastInterface=a.readUTF8Element(NDNProtocolDTags.MulticastInterface));a.peekStartElement(NDNProtocolDTags.MulticastTTL)&&(this.multicastTTL=a.readIntegerElement(NDNProtocolDTags.MulticastTTL));a.peekStartElement(NDNProtocolDTags.FreshnessSeconds)&&(this.freshnessSeconds=a.readIntegerElement(NDNProtocolDTags.FreshnessSeconds));a.readEndElement()};
-FaceInstance.prototype.to_ndnb=function(a){a.writeStartElement(this.getElementLabel());null!=this.action&&0!=this.action.length&&a.writeElement(NDNProtocolDTags.Action,this.action);null!=this.publisherPublicKeyDigest&&this.publisherPublicKeyDigest.to_ndnb(a);null!=this.faceID&&a.writeElement(NDNProtocolDTags.FaceID,this.faceID);null!=this.ipProto&&a.writeElement(NDNProtocolDTags.IPProto,this.ipProto);null!=this.host&&0!=this.host.length&&a.writeElement(NDNProtocolDTags.Host,this.host);null!=this.Port&&
-a.writeElement(NDNProtocolDTags.Port,this.Port);null!=this.multicastInterface&&0!=this.multicastInterface.length&&a.writeElement(NDNProtocolDTags.MulticastInterface,this.multicastInterface);null!=this.multicastTTL&&a.writeElement(NDNProtocolDTags.MulticastTTL,this.multicastTTL);null!=this.freshnessSeconds&&a.writeElement(NDNProtocolDTags.FreshnessSeconds,this.freshnessSeconds);a.writeEndElement()};FaceInstance.prototype.getElementLabel=function(){return NDNProtocolDTags.FaceInstance};
-var ForwardingEntry=function(a,b,c,d,e,f){this.action=a;this.prefixName=b;this.ndndID=c;this.faceID=d;this.flags=e;this.lifetime=f};
-ForwardingEntry.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(NDNProtocolDTags.Action)&&(this.action=a.readUTF8Element(NDNProtocolDTags.Action));a.peekStartElement(NDNProtocolDTags.Name)&&(this.prefixName=new Name,this.prefixName.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)&&(this.NdndId=new PublisherPublicKeyDigest,this.NdndId.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.FaceID)&&(this.faceID=a.readIntegerElement(NDNProtocolDTags.FaceID));
-a.peekStartElement(NDNProtocolDTags.ForwardingFlags)&&(this.flags=a.readIntegerElement(NDNProtocolDTags.ForwardingFlags));a.peekStartElement(NDNProtocolDTags.FreshnessSeconds)&&(this.lifetime=a.readIntegerElement(NDNProtocolDTags.FreshnessSeconds));a.readEndElement()};
-ForwardingEntry.prototype.to_ndnb=function(a){a.writeStartElement(this.getElementLabel());null!=this.action&&0!=this.action.length&&a.writeElement(NDNProtocolDTags.Action,this.action);null!=this.prefixName&&this.prefixName.to_ndnb(a);null!=this.NdndId&&this.NdndId.to_ndnb(a);null!=this.faceID&&a.writeElement(NDNProtocolDTags.FaceID,this.faceID);null!=this.flags&&a.writeElement(NDNProtocolDTags.ForwardingFlags,this.flags);null!=this.lifetime&&a.writeElement(NDNProtocolDTags.FreshnessSeconds,this.lifetime);
-a.writeEndElement()};ForwardingEntry.prototype.getElementLabel=function(){return NDNProtocolDTags.ForwardingEntry};var DynamicUint8Array=function(a){a||(a=16);this.array=new Uint8Array(a);this.length=a};DynamicUint8Array.prototype.ensureLength=function(a){if(!(this.array.length>=a)){var b=2*this.array.length;a>b&&(b=a);a=new Uint8Array(b);a.set(this.array);this.array=a;this.length=b}};DynamicUint8Array.prototype.set=function(a,b){this.ensureLength(a.length+b);this.array.set(a,b)};
-DynamicUint8Array.prototype.subarray=function(a,b){return this.array.subarray(a,b)};
-var XML_EXT=0,XML_TAG=1,XML_DTAG=2,XML_ATTR=3,XML_DATTR=4,XML_BLOB=5,XML_UDATA=6,XML_CLOSE=0,XML_SUBTYPE_PROCESSING_INSTRUCTIONS=16,XML_TT_BITS=3,XML_TT_MASK=(1<<XML_TT_BITS)-1,XML_TT_VAL_BITS=XML_TT_BITS+1,XML_TT_VAL_MASK=(1<<XML_TT_VAL_BITS)-1,XML_REG_VAL_BITS=7,XML_REG_VAL_MASK=(1<<XML_REG_VAL_BITS)-1,XML_TT_NO_MORE=1<<XML_REG_VAL_BITS,BYTE_MASK=255,LONG_BYTES=8,LONG_BITS=64,bits_11=2047,bits_18=262143,bits_32=4294967295,BinaryXMLEncoder=function(){this.ostream=new DynamicUint8Array(100);this.offset=
-0;this.CODEC_NAME="Binary"};BinaryXMLEncoder.prototype.writeUString=function(a){this.encodeUString(a,XML_UDATA)};BinaryXMLEncoder.prototype.writeBlob=function(a){3<LOG&&console.log(a);this.encodeBlob(a,a.length)};BinaryXMLEncoder.prototype.writeStartElement=function(a,b){null==a?this.encodeUString(a,XML_TAG):this.encodeTypeAndVal(XML_DTAG,a);null!=b&&this.writeAttributes(b)};
-BinaryXMLEncoder.prototype.writeEndElement=function(){this.ostream.ensureLength(this.offset+1);this.ostream.array[this.offset]=XML_CLOSE;this.offset+=1};BinaryXMLEncoder.prototype.writeAttributes=function(a){if(null!=a)for(var b=0;b<a.length;b++){var c=a[b].k,d=a[b].v,e=stringToTag(c);null==e?this.encodeUString(c,XML_ATTR):this.encodeTypeAndVal(XML_DATTR,e);this.encodeUString(d)}};
-stringToTag=function(a){return 0<=a&&a<NDNProtocolDTagsStrings.length?NDNProtocolDTagsStrings[a]:a==NDNProtocolDTags.NDNProtocolDataUnit?NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT:null};tagToString=function(a){for(var b=0;b<NDNProtocolDTagsStrings.length;++b)if(null!=NDNProtocolDTagsStrings[b]&&NDNProtocolDTagsStrings[b]==a)return b;return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT==a?NDNProtocolDTags.NDNProtocolDataUnit:null};
-BinaryXMLEncoder.prototype.writeElement=function(a,b,c){this.writeStartElement(a,c);"number"===typeof b?(4<LOG&&console.log("GOING TO WRITE THE NUMBER .charCodeAt(0) "+b.toString().charCodeAt(0)),4<LOG&&console.log("GOING TO WRITE THE NUMBER "+b.toString()),4<LOG&&console.log("type of number is "+typeof b.toString()),this.writeUString(b.toString())):"string"===typeof b?(4<LOG&&console.log("GOING TO WRITE THE STRING  "+b),4<LOG&&console.log("type of STRING is "+typeof b),this.writeUString(b)):(4<LOG&&
-console.log("GOING TO WRITE A BLOB  "+b),this.writeBlob(b));this.writeEndElement()};var TypeAndVal=function(a,b){this.type=a;this.val=b};
-BinaryXMLEncoder.prototype.encodeTypeAndVal=function(a,b){4<LOG&&console.log("Encoding type "+a+" and value "+b);4<LOG&&console.log("OFFSET IS "+this.offset);if(a>XML_UDATA||0>a||0>b)throw Error("Tag and value must be positive, and tag valid.");var c=this.numEncodingBytes(b);this.ostream.ensureLength(this.offset+c);this.ostream.array[this.offset+c-1]=BYTE_MASK&(XML_TT_MASK&a|(XML_TT_VAL_MASK&b)<<XML_TT_BITS)|XML_TT_NO_MORE;b>>>=XML_TT_VAL_BITS;for(var d=this.offset+c-2;0!=b&&d>=this.offset;)this.ostream.array[d]=
-BYTE_MASK&b&XML_REG_VAL_MASK,b>>>=XML_REG_VAL_BITS,--d;if(0!=b)throw Error("This should not happen: miscalculated encoding");this.offset+=c;return c};
-BinaryXMLEncoder.prototype.encodeUString=function(a,b){if(null!=a&&!(b==XML_TAG||b==XML_ATTR&&0==a.length)){3<LOG&&console.log("The string to write is ");3<LOG&&console.log(a);var c=DataUtils.stringToUtf8Array(a);this.encodeTypeAndVal(b,b==XML_TAG||b==XML_ATTR?c.length-1:c.length);3<LOG&&console.log("THE string to write is ");3<LOG&&console.log(c);this.writeString(c);this.offset+=c.length}};
-BinaryXMLEncoder.prototype.encodeBlob=function(a,b){null!=a&&(4<LOG&&console.log("LENGTH OF XML_BLOB IS "+b),this.encodeTypeAndVal(XML_BLOB,b),this.writeBlobArray(a),this.offset+=b)};var ENCODING_LIMIT_1_BYTE=(1<<XML_TT_VAL_BITS)-1,ENCODING_LIMIT_2_BYTES=(1<<XML_TT_VAL_BITS+XML_REG_VAL_BITS)-1,ENCODING_LIMIT_3_BYTES=(1<<XML_TT_VAL_BITS+2*XML_REG_VAL_BITS)-1;
-BinaryXMLEncoder.prototype.numEncodingBytes=function(a){if(a<=ENCODING_LIMIT_1_BYTE)return 1;if(a<=ENCODING_LIMIT_2_BYTES)return 2;if(a<=ENCODING_LIMIT_3_BYTES)return 3;var b=1;for(a>>>=XML_TT_VAL_BITS;0!=a;)b++,a>>>=XML_REG_VAL_BITS;return b};
-BinaryXMLEncoder.prototype.writeDateTime=function(a,b){4<LOG&&console.log("ENCODING DATE with LONG VALUE");4<LOG&&console.log(b.msec);var c=Math.round(4096*(b.msec/1E3)).toString(16),c=DataUtils.toNumbers("0".concat(c,"0"));4<LOG&&console.log("ENCODING DATE with BINARY VALUE");4<LOG&&console.log(c);4<LOG&&console.log("ENCODING DATE with BINARY VALUE(HEX)");4<LOG&&console.log(DataUtils.toHex(c));this.writeElement(a,c)};
-BinaryXMLEncoder.prototype.writeString=function(a){if("string"===typeof a){4<LOG&&console.log("GOING TO WRITE A STRING");4<LOG&&console.log(a);this.ostream.ensureLength(this.offset+a.length);for(var b=0;b<a.length;b++)4<LOG&&console.log("input.charCodeAt(i)="+a.charCodeAt(b)),this.ostream.array[this.offset+b]=a.charCodeAt(b)}else 4<LOG&&console.log("GOING TO WRITE A STRING IN BINARY FORM"),4<LOG&&console.log(a),this.writeBlobArray(a)};
-BinaryXMLEncoder.prototype.writeBlobArray=function(a){4<LOG&&console.log("GOING TO WRITE A BLOB");this.ostream.set(a,this.offset)};BinaryXMLEncoder.prototype.getReducedOstream=function(){return this.ostream.subarray(0,this.offset)};XML_EXT=0;XML_TAG=1;XML_DTAG=2;XML_ATTR=3;XML_DATTR=4;XML_BLOB=5;XML_UDATA=6;XML_CLOSE=0;XML_SUBTYPE_PROCESSING_INSTRUCTIONS=16;XML_TT_BITS=3;XML_TT_MASK=(1<<XML_TT_BITS)-1;XML_TT_VAL_BITS=XML_TT_BITS+1;XML_TT_VAL_MASK=(1<<XML_TT_VAL_BITS)-1;XML_REG_VAL_BITS=7;
-XML_REG_VAL_MASK=(1<<XML_REG_VAL_BITS)-1;XML_TT_NO_MORE=1<<XML_REG_VAL_BITS;BYTE_MASK=255;LONG_BYTES=8;LONG_BITS=64;bits_11=2047;bits_18=262143;bits_32=4294967295;tagToString=function(a){return 0<=a&&a<NDNProtocolDTagsStrings.length?NDNProtocolDTagsStrings[a]:a==NDNProtocolDTags.NDNProtocolDataUnit?NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT:null};
-stringToTag=function(a){for(var b=0;b<NDNProtocolDTagsStrings.length;++b)if(null!=NDNProtocolDTagsStrings[b]&&NDNProtocolDTagsStrings[b]==a)return b;return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT==a?NDNProtocolDTags.NDNProtocolDataUnit:null};var BinaryXMLDecoder=function(a){this.istream=a;this.offset=0};BinaryXMLDecoder.prototype.initializeDecoding=function(){};BinaryXMLDecoder.prototype.readStartDocument=function(){};BinaryXMLDecoder.prototype.readEndDocument=function(){};
-BinaryXMLDecoder.prototype.readStartElement=function(a,b){var c=this.decodeTypeAndVal();if(null==c)throw new ContentDecodingException(Error("Expected start element: "+a+" got something not a tag."));var d=null;c.type()==XML_TAG?(d="string"==typeof c.val()?parseInt(c.val())+1:c.val()+1,d=this.decodeUString(d)):c.type()==XML_DTAG&&(d=c.val());if(null==d||d!=a)throw console.log("expecting "+a+" but got "+d),new ContentDecodingException(Error("Expected start element: "+a+" got: "+d+"("+c.val()+")"));
-null!=b&&readAttributes(b)};
-BinaryXMLDecoder.prototype.readAttributes=function(a){if(null!=a)try{for(var b=this.peekTypeAndVal();null!=b&&(XML_ATTR==b.type()||XML_DATTR==b.type());){var c=this.decodeTypeAndVal(),d=null;if(XML_ATTR==c.type()){var e;e="string"==typeof c.val()?parseInt(c.val())+1:c.val()+1;d=this.decodeUString(e)}else if(XML_DATTR==c.type()&&(d=tagToString(c.val()),null==d))throw new ContentDecodingException(Error("Unknown DATTR value"+c.val()));var f=this.decodeUString();a.push([d,f]);b=this.peekTypeAndVal()}}catch(g){throw new ContentDecodingException(Error("readStartElement",
-g));}};BinaryXMLDecoder.prototype.peekStartElementAsString=function(){var a=null,b=this.offset;try{var c=this.decodeTypeAndVal();if(null!=c)if(c.type()==XML_TAG){var d;d="string"==typeof c.val()?parseInt(c.val())+1:c.val()+1;a=this.decodeUString(d)}else c.type()==XML_DTAG&&(a=tagToString(c.val()))}catch(e){}finally{try{this.offset=b}catch(f){throw Log.logStackTrace(Log.FAC_ENCODING,Level.WARNING,f),new ContentDecodingException(Error("Cannot reset stream! "+f.getMessage(),f));}}return a};
-BinaryXMLDecoder.prototype.peekStartElement=function(a){if("string"==typeof a){var b=this.peekStartElementAsString();return null!=b&&b==a?!0:!1}if("number"==typeof a)return b=this.peekStartElementAsLong(),null!=b&&b==a?!0:!1;throw new ContentDecodingException(Error("SHOULD BE STRING OR NUMBER"));};
-BinaryXMLDecoder.prototype.peekStartElementAsLong=function(){var a=null,b=this.offset;try{var c=this.decodeTypeAndVal();if(null!=c)if(c.type()==XML_TAG){if(c.val()+1>DEBUG_MAX_LEN)throw new ContentDecodingException(Error("Decoding error: length "+c.val()+1+" longer than expected maximum length!"));var d;d="string"==typeof c.val()?parseInt(c.val())+1:c.val()+1;var e=this.decodeUString(d),a=stringToTag(e)}else c.type()==XML_DTAG&&(a=c.val())}catch(f){}finally{try{this.offset=b}catch(g){throw Log.logStackTrace(Log.FAC_ENCODING,
-Level.WARNING,g),Error("Cannot reset stream! "+g.getMessage(),g);}}return a};BinaryXMLDecoder.prototype.readBinaryElement=function(a,b){var c=null;this.readStartElement(a,b);return c=this.readBlob()};
-BinaryXMLDecoder.prototype.readEndElement=function(){4<LOG&&console.log("this.offset is "+this.offset);var a=this.istream[this.offset];this.offset++;4<LOG&&console.log("XML_CLOSE IS "+XML_CLOSE);4<LOG&&console.log("next is "+a);if(a!=XML_CLOSE)throw console.log("Expected end element, got: "+a),new ContentDecodingException(Error("Expected end element, got: "+a));};BinaryXMLDecoder.prototype.readUString=function(){var a=this.decodeUString();this.readEndElement();return a};
-BinaryXMLDecoder.prototype.readBlob=function(){var a=this.decodeBlob();this.readEndElement();return a};BinaryXMLDecoder.prototype.readDateTime=function(a){a=this.readBinaryElement(a);a=DataUtils.toHex(a);a=parseInt(a,16);var b=1E3*(a/4096);3<LOG&&console.log("DECODED DATE WITH VALUE");3<LOG&&console.log(b);b=new NDNTime(b);if(null==b)throw new ContentDecodingException(Error("Cannot parse timestamp: "+DataUtils.printHexBytes(a)));return b};
-BinaryXMLDecoder.prototype.decodeTypeAndVal=function(){var a=-1,b=0,c=!0;do{var d=this.istream[this.offset];if(0>d||0==d&&0==b)return null;(c=0==(d&XML_TT_NO_MORE))?(b<<=XML_REG_VAL_BITS,b|=d&XML_REG_VAL_MASK):(a=d&XML_TT_MASK,b<<=XML_TT_VAL_BITS,b|=d>>>XML_TT_BITS&XML_TT_VAL_MASK);this.offset++}while(c);3<LOG&&console.log("TYPE is "+a+" VAL is "+b);return new TypeAndVal(a,b)};BinaryXMLDecoder.peekTypeAndVal=function(){var a=null,b=this.offset;try{a=this.decodeTypeAndVal()}finally{this.offset=b}return a};
-BinaryXMLDecoder.prototype.decodeBlob=function(a){if(null==a)return a=this.decodeTypeAndVal(),a="string"==typeof a.val()?parseInt(a.val()):a.val(),this.decodeBlob(a);var b=this.istream.subarray(this.offset,this.offset+a);this.offset+=a;return b};
-BinaryXMLDecoder.prototype.decodeUString=function(a){if(null==a){a=this.offset;var b=this.decodeTypeAndVal();3<LOG&&console.log("TV is "+b);3<LOG&&console.log(b);3<LOG&&console.log("Type of TV is "+typeof b);return null==b||XML_UDATA!=b.type()?(this.offset=a,""):this.decodeUString(b.val())}a=this.decodeBlob(a);return DataUtils.toString(a)};TypeAndVal=function(a,b){this.t=a;this.v=b};TypeAndVal.prototype.type=function(){return this.t};TypeAndVal.prototype.val=function(){return this.v};
-BinaryXMLDecoder.prototype.readIntegerElement=function(a){4<LOG&&console.log("READING INTEGER "+a);4<LOG&&console.log("TYPE OF "+typeof a);a=this.readUTF8Element(a);return parseInt(a)};BinaryXMLDecoder.prototype.readUTF8Element=function(a,b){this.readStartElement(a,b);return this.readUString()};BinaryXMLDecoder.prototype.seek=function(a){this.offset=a};function ContentDecodingException(a){this.message=a.message;for(var b in a)this[b]=a[b]}ContentDecodingException.prototype=Error();
-ContentDecodingException.prototype.name="ContentDecodingException";var BinaryXMLStructureDecoder=function(){this.gotElementEnd=!1;this.level=this.offset=0;this.state=BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;this.headerLength=0;this.useHeaderBuffer=!1;this.headerBuffer=new DynamicUint8Array(5);this.nBytesToRead=0};BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE=0;BinaryXMLStructureDecoder.READ_BYTES=1;
-BinaryXMLStructureDecoder.prototype.findElementEnd=function(a){if(this.gotElementEnd)return!0;for(var b=new BinaryXMLDecoder(a);;){if(this.offset>=a.length)return!1;switch(this.state){case BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE:if(0==this.headerLength&&a[this.offset]==XML_CLOSE){++this.offset;--this.level;if(0==this.level)return!0;if(0>this.level)throw Error("BinaryXMLStructureDecoder: Unexepected close tag at offset "+(this.offset-1));this.startHeader();break}for(var c=this.headerLength;;){if(this.offset>=
-a.length){this.useHeaderBuffer=!0;var d=this.headerLength-c;this.headerBuffer.set(a.subarray(this.offset-d,d),c);return!1}d=a[this.offset++];++this.headerLength;if(d&XML_TT_NO_MORE)break}this.useHeaderBuffer?(d=this.headerLength-c,this.headerBuffer.set(a.subarray(this.offset-d,d),c),c=(new BinaryXMLDecoder(this.headerBuffer.array)).decodeTypeAndVal()):(b.seek(this.offset-this.headerLength),c=b.decodeTypeAndVal());if(null==c)throw Error("BinaryXMLStructureDecoder: Can't read header starting at offset "+
-(this.offset-this.headerLength));d=c.t;if(d==XML_DATTR)this.startHeader();else if(d==XML_DTAG||d==XML_EXT)++this.level,this.startHeader();else if(d==XML_TAG||d==XML_ATTR)d==XML_TAG&&++this.level,this.nBytesToRead=c.v+1,this.state=BinaryXMLStructureDecoder.READ_BYTES;else if(d==XML_BLOB||d==XML_UDATA)this.nBytesToRead=c.v,this.state=BinaryXMLStructureDecoder.READ_BYTES;else throw Error("BinaryXMLStructureDecoder: Unrecognized header type "+d);break;case BinaryXMLStructureDecoder.READ_BYTES:c=a.length-
-this.offset;if(c<this.nBytesToRead)return this.offset+=c,this.nBytesToRead-=c,!1;this.offset+=this.nBytesToRead;this.startHeader();break;default:throw Error("BinaryXMLStructureDecoder: Unrecognized state "+this.state);}}};BinaryXMLStructureDecoder.prototype.startHeader=function(){this.headerLength=0;this.useHeaderBuffer=!1;this.state=BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE};BinaryXMLStructureDecoder.prototype.seek=function(a){this.offset=a};var DataUtils=function(){};DataUtils.keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-DataUtils.stringtoBase64=function(a){a=escape(a);var b="",c,d,e="",f,g,h="",j=0;do c=a.charCodeAt(j++),d=a.charCodeAt(j++),e=a.charCodeAt(j++),f=c>>2,c=(c&3)<<4|d>>4,g=(d&15)<<2|e>>6,h=e&63,isNaN(d)?g=h=64:isNaN(e)&&(h=64),b=b+DataUtils.keyStr.charAt(f)+DataUtils.keyStr.charAt(c)+DataUtils.keyStr.charAt(g)+DataUtils.keyStr.charAt(h);while(j<a.length);return b};
-DataUtils.base64toString=function(a){var b="",c,d,e="",f,g="",h=0;/[^A-Za-z0-9\+\/\=]/g.exec(a)&&alert("There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\nExpect errors in decoding.");a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do c=DataUtils.keyStr.indexOf(a.charAt(h++)),d=DataUtils.keyStr.indexOf(a.charAt(h++)),f=DataUtils.keyStr.indexOf(a.charAt(h++)),g=DataUtils.keyStr.indexOf(a.charAt(h++)),c=c<<2|d>>4,d=(d&15)<<4|f>>2,e=(f&3)<<6|g,
-b+=String.fromCharCode(c),64!=f&&(b+=String.fromCharCode(d)),64!=g&&(b+=String.fromCharCode(e));while(h<a.length);return unescape(b)};DataUtils.toHex=function(a){4<LOG&&console.log("ABOUT TO CONVERT "+a);for(var b="",c=0;c<a.length;c++)b+=(16>a[c]?"0":"")+a[c].toString(16);4<LOG&&console.log("Converted to: "+b);return b};DataUtils.stringToHex=function(a){for(var b="",c=0;c<a.length;++c)var d=a.charCodeAt(c),b=b+((16>d?"0":"")+d.toString(16));return b};
-DataUtils.toString=function(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a[c]);return b};DataUtils.toNumbers=function(a){if("string"==typeof a){var b=new Uint8Array(Math.floor(a.length/2)),c=0;a.replace(/(..)/g,function(a){b[c++]=parseInt(a,16)});return b}};DataUtils.hexToRawString=function(a){if("string"==typeof a){var b="";a.replace(/(..)/g,function(a){b+=String.fromCharCode(parseInt(a,16))});return b}};
-DataUtils.toNumbersFromString=function(a){for(var b=new Uint8Array(a.length),c=0;c<a.length;c++)b[c]=a.charCodeAt(c);return b};DataUtils.stringToUtf8Array=function(a){return DataUtils.toNumbersFromString(str2rstr_utf8(a))};DataUtils.concatArrays=function(a){for(var b=0,c=0;c<a.length;++c)b+=a[c].length;for(var b=new Uint8Array(b),d=0,c=0;c<a.length;++c)b.set(a[c],d),d+=a[c].length;return b};
-DataUtils.decodeUtf8=function(a){for(var b="",c=0,d=0,e=0;c<a.length;)if(d=a.charCodeAt(c),128>d)b+=String.fromCharCode(d),c++;else if(191<d&&224>d)e=a.charCodeAt(c+1),b+=String.fromCharCode((d&31)<<6|e&63),c+=2;else var e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b=b+String.fromCharCode((d&15)<<12|(e&63)<<6|f&63),c=c+3;return b};DataUtils.arraysEqual=function(a,b){if(a.length!=b.length)return!1;for(var c=0;c<a.length;++c)if(a[c]!=b[c])return!1;return!0};
-DataUtils.bigEndianToUnsignedInt=function(a){for(var b=0,c=0;c<a.length;++c)b<<=8,b+=a[c];return b};DataUtils.nonNegativeIntToBigEndian=function(a){a=Math.round(a);if(0>=a)return new Uint8Array(0);for(var b=new Uint8Array(8),c=0;0!=a;)++c,b[8-c]=a&255,a>>=8;return b.subarray(8-c,8)};DataUtils.shuffle=function(a){for(var b=a.length-1;1<=b;--b){var c=Math.floor(Math.random()*(b+1)),d=a[b];a[b]=a[c];a[c]=d}};function encodeToHexInterest(a){return DataUtils.toHex(encodeToBinaryInterest(a))}
-function encodeToBinaryInterest(a){var b=new BinaryXMLEncoder;a.to_ndnb(b);return b.getReducedOstream()}function encodeToHexContentObject(a){return DataUtils.toHex(encodeToBinaryContentObject(a))}function encodeToBinaryContentObject(a){var b=new BinaryXMLEncoder;a.to_ndnb(b);return b.getReducedOstream()}function encodeForwardingEntry(a){var b=new BinaryXMLEncoder;a.to_ndnb(b);return b.getReducedOstream()}
-function decodeHexFaceInstance(a){var b=DataUtils.toNumbers(a);a=new BinaryXMLDecoder(b);3<LOG&&console.log("DECODING HEX FACE INSTANCE  \n"+b);b=new FaceInstance;b.from_ndnb(a);return b}function decodeHexInterest(a){var b=DataUtils.toNumbers(a);a=new BinaryXMLDecoder(b);3<LOG&&console.log("DECODING HEX INTERST  \n"+b);b=new Interest;b.from_ndnb(a);return b}
-function decodeHexContentObject(a){var b=DataUtils.toNumbers(a);a=new BinaryXMLDecoder(b);3<LOG&&console.log("DECODED HEX CONTENT OBJECT \n"+b);b=new ContentObject;b.from_ndnb(a);return b}function decodeHexForwardingEntry(a){var b=DataUtils.toNumbers(a);a=new BinaryXMLDecoder(b);3<LOG&&console.log("DECODED HEX FORWARDING ENTRY \n"+b);b=new ForwardingEntry;b.from_ndnb(a);return b}
-function decodeSubjectPublicKeyInfo(a){a=DataUtils.toHex(a).toLowerCase();a=_x509_getPublicKeyHexArrayFromCertHex(a,_x509_getSubjectPublicKeyPosFromCertHex(a,0));var b=new RSAKey;b.setPublic(a[0],a[1]);return b}
-function contentObjectToHtml(a){var b="";if(-1==a)b+="NO CONTENT FOUND";else if(-2==a)b+="CONTENT NAME IS EMPTY";else{null!=a.name&&null!=a.name.components&&(b+="NAME: "+a.name.to_uri(),b+="<br /><br />");null!=a.content&&(b+="CONTENT(ASCII): "+DataUtils.toString(a.content),b+="<br />",b+="<br />");null!=a.content&&(b+="CONTENT(hex): "+DataUtils.toHex(a.content),b+="<br />",b+="<br />");null!=a.signature&&null!=a.signature.signature&&(b+="SIGNATURE(hex): "+DataUtils.toHex(a.signature.signature),b+=
-"<br />",b+="<br />");null!=a.signedInfo&&(null!=a.signedInfo.publisher&&null!=a.signedInfo.publisher.publisherPublicKeyDigest)&&(b+="Publisher Public Key Digest(hex): "+DataUtils.toHex(a.signedInfo.publisher.publisherPublicKeyDigest),b+="<br />",b+="<br />");if(null!=a.signedInfo&&null!=a.signedInfo.timestamp){var c=new Date;c.setTime(a.signedInfo.timestamp.msec);b+="TimeStamp: "+c;b+="<br />";b+="TimeStamp(number): "+a.signedInfo.timestamp.msec;b+="<br />"}null!=a.signedInfo&&null!=a.signedInfo.finalBlockID&&
-(b+="FinalBlockID: "+DataUtils.toHex(a.signedInfo.finalBlockID),b+="<br />");if(null!=a.signedInfo&&null!=a.signedInfo.locator&&null!=a.signedInfo.locator.certificate){var d=DataUtils.toHex(a.signedInfo.locator.certificate).toLowerCase(),c=DataUtils.toHex(a.signature.signature).toLowerCase(),e=DataUtils.toString(a.rawSignatureData),b=b+("Hex Certificate: "+d),b=b+"<br />",b=b+"<br />",e=new X509;e.readCertHex(d);b+="Public key (hex) modulus: "+e.subjectPublicKeyRSA.n.toString(16)+"<br/>";b+="exponent: "+
-e.subjectPublicKeyRSA.e.toString(16)+"<br/>";b+="<br/>";c=e.subjectPublicKeyRSA.verifyByteArray(a.rawSignatureData,null,c);2<LOG&&console.log("result is "+c);d=e.subjectPublicKeyRSA.n;e=e.subjectPublicKeyRSA.e;2<LOG&&console.log("PUBLIC KEY n after is ");2<LOG&&console.log(d);2<LOG&&console.log("EXPONENT e after is ");2<LOG&&console.log(e);b=c?b+"SIGNATURE VALID":b+"SIGNATURE INVALID";b+="<br />";b+="<br />"}if(null!=a.signedInfo&&null!=a.signedInfo.locator&&null!=a.signedInfo.locator.publicKey){var f=
-DataUtils.toHex(a.signedInfo.locator.publicKey).toLowerCase(),g=DataUtils.toString(a.signedInfo.locator.publicKey),c=DataUtils.toHex(a.signature.signature).toLowerCase(),e=DataUtils.toString(a.rawSignatureData),d=null,h="";null!=a.signature.Witness&&(d=new Witness,d.decode(a.signature.Witness),h=DataUtils.toHex(a.signature.Witness));b+="Public key: "+f;b+="<br />";b+="<br />";2<LOG&&console.log(" ContentName + SignedInfo + Content = "+e);2<LOG&&console.log(" PublicKeyHex = "+f);2<LOG&&console.log(" PublicKeyString = "+
-g);2<LOG&&console.log(" Signature "+c);2<LOG&&console.log(" Witness "+h);2<LOG&&console.log(" Signature NOW IS");2<LOG&&console.log(a.signature.signature);e=decodeSubjectPublicKeyInfo(a.signedInfo.locator.publicKey);b+="Public key (hex) modulus: "+e.n.toString(16)+"<br/>";b+="exponent: "+e.e.toString(16)+"<br/>";b+="<br/>";c=e.verifyByteArray(a.rawSignatureData,d,c);2<LOG&&console.log("PUBLIC KEY n after is ");2<LOG&&console.log(e.n);2<LOG&&console.log("EXPONENT e after is ");2<LOG&&console.log(e.e);
-b=c?b+"SIGNATURE VALID":b+"SIGNATURE INVALID";b+="<br />";b+="<br />"}}return b}
-var KeyManager=function(){this.certificate="MIIBmzCCAQQCCQC32FyQa61S7jANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdheGVsY2R2MB4XDTEyMDQyODIzNDQzN1oXDTEyMDUyODIzNDQzN1owEjEQMA4GA1UEAxMHYXhlbGNkdjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4X0wp9goqxuECxdULcr2IHr9Ih4Iaypg0Wy39URIup8/CLzQmdsh3RYqd55hqonu5VTTpH3iMLx6xZDVJAZ8OJi7pvXcQ2C4Re2kjL2c8SanI0RfDhlS1zJadfr1VhRPmpivcYawJ4aFuOLAi+qHFxtN7lhcGCgpW1OV60oXd58CAwEAATANBgkqhkiG9w0BAQUFAAOBgQDLOrA1fXzSrpftUB5Ro6DigX1Bjkf7F5Bkd69hSVp+jYeJFBBlsILQAfSxUZPQtD+2Yc3iCmSYNyxqu9PcufDRJlnvB7PG29+L3y9lR37tetzUV9eTscJ7rdp8Wt6AzpW32IJ/54yKNfP7S6ZIoIG+LP6EIxq6s8K1MXRt8uBJKw==";this.publicKey=
-"30819F300D06092A864886F70D010101050003818D0030818902818100E17D30A7D828AB1B840B17542DCAF6207AFD221E086B2A60D16CB7F54448BA9F3F08BCD099DB21DD162A779E61AA89EEE554D3A47DE230BC7AC590D524067C3898BBA6F5DC4360B845EDA48CBD9CF126A723445F0E1952D7325A75FAF556144F9A98AF7186B0278685B8E2C08BEA87171B4DEE585C1828295B5395EB4A17779F0203010001";this.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"};
-KeyManager.prototype.verify=function(a,b){var c=this.certificate,d=new X509;d.readCertPEM(c);return d.subjectPublicKeyRSA.verifyString(a,b)};KeyManager.prototype.sign=function(a){var b=this.privateKey,c=new RSAKey;c.readPrivateKeyFromPEMString(b);return c.signString(a,"sha256")};var globalKeyManager=new KeyManager,MerklePath=function(){this.index=null;this.digestList=[]},Witness=function(){this.oid=null;this.path=new MerklePath};
-function parseOID(a,b,c){for(var d,e=0,f=0;b<c;++b){var g=a[b],e=e<<7|g&127,f=f+7;g&128||(d=void 0==d?parseInt(e/40)+"."+e%40:d+("."+(31<=f?"bigint":e)),e=f=0);d+=String.fromCharCode()}return d}function parseInteger(a,b,c){for(var d=0;b<c;++b)d=d<<8|a[b];return d}
-Witness.prototype.decode=function(a){for(var b=0,c=0;b<a.length;){var d=0;if(48==a[b])0!=(a[b+1]&128)&&(d=a[b+1]&127),c++;else if(6==a[b])d=a[b+1],this.oid=parseOID(a,b+2,b+2+d);else if(2==a[b])d=a[b+1],this.path.index=parseInteger(a,b+2,b+2+d);else if(4==a[b]&&(0!=(a[b+1]&128)&&(d=a[b+1]&127),4==c)){var d=a[b+1],e=DataUtils.toHex(a.subarray(b+2,b+2+d));this.path.digestList.push(e)}b=b+2+d}};var hexcase=0,b64pad="";
-function hex_sha256_from_bytes(a){return rstr2hex(binb2rstr(binb_sha256(byteArray2binb(a),8*a.length)))}function hex_sha256(a){return rstr2hex(rstr_sha256(str2rstr_utf8(a)))}function b64_sha256(a){return rstr2b64(rstr_sha256(str2rstr_utf8(a)))}function any_sha256(a,b){return rstr2any(rstr_sha256(str2rstr_utf8(a)),b)}function hex_hmac_sha256(a,b){return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(a),str2rstr_utf8(b)))}
-function b64_hmac_sha256(a,b){return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(a),str2rstr_utf8(b)))}function any_hmac_sha256(a,b,c){return rstr2any(rstr_hmac_sha256(str2rstr_utf8(a),str2rstr_utf8(b)),c)}function sha256_vm_test(){return"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"==hex_sha256("abc").toLowerCase()}function rstr_sha256(a){return binb2rstr(binb_sha256(rstr2binb(a),8*a.length))}
-function rstr_hmac_sha256(a,b){var c=rstr2binb(a);16<c.length&&(c=binb_sha256(c,8*a.length));for(var d=Array(16),e=Array(16),f=0;16>f;f++)d[f]=c[f]^909522486,e[f]=c[f]^1549556828;c=binb_sha256(d.concat(rstr2binb(b)),512+8*b.length);return binb2rstr(binb_sha256(e.concat(c),768))}function rstr2hex(a){try{hexcase}catch(b){hexcase=0}for(var c=hexcase?"0123456789ABCDEF":"0123456789abcdef",d="",e,f=0;f<a.length;f++)e=a.charCodeAt(f),d+=c.charAt(e>>>4&15)+c.charAt(e&15);return d}
-function rstr2b64(a){try{b64pad}catch(b){b64pad=""}for(var c="",d=a.length,e=0;e<d;e+=3)for(var f=a.charCodeAt(e)<<16|(e+1<d?a.charCodeAt(e+1)<<8:0)|(e+2<d?a.charCodeAt(e+2):0),g=0;4>g;g++)c=8*e+6*g>8*a.length?c+b64pad:c+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(f>>>6*(3-g)&63);return c}
-function rstr2any(a,b){var c=b.length,d=[],e,f,g,h,j=Array(Math.ceil(a.length/2));for(e=0;e<j.length;e++)j[e]=a.charCodeAt(2*e)<<8|a.charCodeAt(2*e+1);for(;0<j.length;){h=[];for(e=g=0;e<j.length;e++)if(g=(g<<16)+j[e],f=Math.floor(g/c),g-=f*c,0<h.length||0<f)h[h.length]=f;d[d.length]=g;j=h}c="";for(e=d.length-1;0<=e;e--)c+=b.charAt(d[e]);d=Math.ceil(8*a.length/(Math.log(b.length)/Math.log(2)));for(e=c.length;e<d;e++)c=b[0]+c;return c}
-function str2rstr_utf8(a){for(var b="",c=-1,d,e;++c<a.length;)d=a.charCodeAt(c),e=c+1<a.length?a.charCodeAt(c+1):0,55296<=d&&(56319>=d&&56320<=e&&57343>=e)&&(d=65536+((d&1023)<<10)+(e&1023),c++),127>=d?b+=String.fromCharCode(d):2047>=d?b+=String.fromCharCode(192|d>>>6&31,128|d&63):65535>=d?b+=String.fromCharCode(224|d>>>12&15,128|d>>>6&63,128|d&63):2097151>=d&&(b+=String.fromCharCode(240|d>>>18&7,128|d>>>12&63,128|d>>>6&63,128|d&63));return b}
-function str2rstr_utf16le(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a.charCodeAt(c)&255,a.charCodeAt(c)>>>8&255);return b}function str2rstr_utf16be(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a.charCodeAt(c)>>>8&255,a.charCodeAt(c)&255);return b}function rstr2binb(a){for(var b=Array(a.length>>2),c=0;c<8*a.length;c+=8)b[c>>5]|=(a.charCodeAt(c/8)&255)<<24-c%32;return b}
-function byteArray2binb(a){for(var b=Array(a.length>>2),c=0;c<8*a.length;c+=8)b[c>>5]|=(a[c/8]&255)<<24-c%32;return b}function binb2rstr(a){for(var b="",c=0;c<32*a.length;c+=8)b+=String.fromCharCode(a[c>>5]>>>24-c%32&255);return b}function sha256_S(a,b){return a>>>b|a<<32-b}function sha256_R(a,b){return a>>>b}function sha256_Ch(a,b,c){return a&b^~a&c}function sha256_Maj(a,b,c){return a&b^a&c^b&c}function sha256_Sigma0256(a){return sha256_S(a,2)^sha256_S(a,13)^sha256_S(a,22)}
-function sha256_Sigma1256(a){return sha256_S(a,6)^sha256_S(a,11)^sha256_S(a,25)}function sha256_Gamma0256(a){return sha256_S(a,7)^sha256_S(a,18)^sha256_R(a,3)}function sha256_Gamma1256(a){return sha256_S(a,17)^sha256_S(a,19)^sha256_R(a,10)}function sha256_Sigma0512(a){return sha256_S(a,28)^sha256_S(a,34)^sha256_S(a,39)}function sha256_Sigma1512(a){return sha256_S(a,14)^sha256_S(a,18)^sha256_S(a,41)}function sha256_Gamma0512(a){return sha256_S(a,1)^sha256_S(a,8)^sha256_R(a,7)}
-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,l,n,m,p,k,q;e=c[0];f=c[1];g=c[2];h=c[3];j=c[4];l=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]),k=safe_add(safe_add(safe_add(safe_add(m,sha256_Sigma1256(j)),sha256_Ch(j,l,n)),sha256_K[p]),d[p]),q=safe_add(sha256_Sigma0256(e),sha256_Maj(e,f,g)),m=n,n=l,l=j,j=safe_add(h,k),h=g,g=f,f=e,e=safe_add(k,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(l,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};
-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="=";
-function hex2b64(a){var b,c,d="";for(b=0;b+3<=a.length;b+=3)c=parseInt(a.substring(b,b+3),16),d+=b64map.charAt(c>>6)+b64map.charAt(c&63);b+1==a.length?(c=parseInt(a.substring(b,b+1),16),d+=b64map.charAt(c<<2)):b+2==a.length&&(c=parseInt(a.substring(b,b+2),16),d+=b64map.charAt(c>>2)+b64map.charAt((c&3)<<4));for(;0<(d.length&3);)d+=b64pad;return d}
-function b64tohex(a){var b="",c,d=0,e;for(c=0;c<a.length&&a.charAt(c)!=b64pad;++c){var f=b64map.indexOf(a.charAt(c));0>f||(0==d?(b+=int2char(f>>2),e=f&3,d=1):1==d?(b+=int2char(e<<2|f>>4),e=f&15,d=2):2==d?(b+=int2char(e),b+=int2char(f>>2),e=f&3,d=3):(b+=int2char(e<<2|f>>4),b+=int2char(f&15),d=0))}1==d&&(b+=int2char(e<<2));return b}function b64toBA(a){a=b64tohex(a);var b,c=[];for(b=0;2*b<a.length;++b)c[b]=parseInt(a.substring(2*b,2*b+2),16);return c}
-function parseBigInt(a,b){return new BigInteger(a,b)}function linebrk(a,b){for(var c="",d=0;d+b<a.length;)c+=a.substring(d,d+b)+"\n",d+=b;return c+a.substring(d,a.length)}function byte2Hex(a){return 16>a?"0"+a.toString(16):a.toString(16)}
-function pkcs1pad2(a,b){if(b<a.length+11)return alert("Message too long for RSA"),null;for(var c=[],d=a.length-1;0<=d&&0<b;){var e=a.charCodeAt(d--);128>e?c[--b]=e:127<e&&2048>e?(c[--b]=e&63|128,c[--b]=e>>6|192):(c[--b]=e&63|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;d=new SecureRandom;for(e=[];2<b;){for(e[0]=0;0==e[0];)d.nextBytes(e);c[--b]=e[0]}c[--b]=2;c[--b]=0;return new BigInteger(c)}function RSAKey(){this.n=null;this.e=0;this.coeff=this.dmq1=this.dmp1=this.q=this.p=this.d=null}
-function RSASetPublic(a,b){null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16)):alert("Invalid RSA public key")}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}function RSAEncrypt(a){a=pkcs1pad2(a,this.n.bitLength()+7>>3);if(null==a)return null;a=this.doPublic(a);if(null==a)return null;a=a.toString(16);return 0==(a.length&1)?a:"0"+a}RSAKey.prototype.doPublic=RSADoPublic;RSAKey.prototype.setPublic=RSASetPublic;RSAKey.prototype.encrypt=RSAEncrypt;
+/*
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+  MIT
+ <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE">MIT License</a>
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+*/
+(function(a,b){"object"===typeof exports?module.exports.printStackTrace=b():"function"===typeof define&&define.amd?define(b):a.printStackTrace=b()})(this,function(){function a(b){b=b||{guess:!0};var c=b.e||null,d=!!b.guess,e=b.mode||null;b=new a.implementation;c=b.run(c,e);return d?b.guessAnonymousFunctions(c):c}a.implementation=function(){};a.implementation.prototype={run:function(a,c){a=a||this.createException();c=c||this.mode(a);return"other"===c?this.other(arguments.callee):this[c](a)},createException:function(){try{this.undef()}catch(a){return a}},
+mode:function(a){return"undefined"!==typeof window&&-1<window.navigator.userAgent.indexOf("PhantomJS")?"phantomjs":a.arguments&&a.stack?"chrome":a.stack&&a.sourceURL?"safari":a.stack&&a.number?"ie":a.stack&&a.fileName?"firefox":a.message&&a["opera#sourceloc"]?!a.stacktrace||-1<a.message.indexOf("\n")&&a.message.split("\n").length>a.stacktrace.split("\n").length?"opera9":"opera10a":a.message&&a.stack&&a.stacktrace?0>a.stacktrace.indexOf("called from line")?"opera10b":"opera11":a.stack&&!a.fileName?
+"chrome":"other"},instrumentFunction:function(b,c,d){b=b||window;var e=b[c];b[c]=function(){d.call(this,a().slice(4));return b[c]._instrumented.apply(this,arguments)};b[c]._instrumented=e},deinstrumentFunction:function(a,c){a[c].constructor===Function&&a[c]._instrumented&&a[c]._instrumented.constructor===Function&&(a[c]=a[c]._instrumented)},chrome:function(a){return(a.stack+"\n").replace(/^[\s\S]+?\s+at\s+/," at ").replace(/^\s+(at eval )?at\s+/gm,"").replace(/^([^\(]+?)([\n$])/gm,"{anonymous}() ($1)$2").replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm,
+"{anonymous}() ($1)").replace(/^(.+) \((.+)\)$/gm,"$1@$2").split("\n").slice(0,-1)},safari:function(a){return a.stack.replace(/\[native code\]\n/m,"").replace(/^(?=\w+Error\:).*$\n/m,"").replace(/^@/gm,"{anonymous}()@").split("\n")},ie:function(a){return a.stack.replace(/^\s*at\s+(.*)$/gm,"$1").replace(/^Anonymous function\s+/gm,"{anonymous}() ").replace(/^(.+)\s+\((.+)\)$/gm,"$1@$2").split("\n").slice(1)},firefox:function(a){return a.stack.replace(/(?:\n@:0)?\s+$/m,"").replace(/^(?:\((\S*)\))?@/gm,
+"{anonymous}($1)@").split("\n")},opera11:function(a){var c=/^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/;a=a.stacktrace.split("\n");for(var d=[],e=0,f=a.length;e<f;e+=2){var g=c.exec(a[e]);if(g){var h=g[4]+":"+g[1]+":"+g[2],g=g[3]||"global code",g=g.replace(/<anonymous function: (\S+)>/,"$1").replace(/<anonymous function>/,"{anonymous}");d.push(g+"@"+h+" -- "+a[e+1].replace(/^\s+/,""))}}return d},opera10b:function(a){var c=/^(.*)@(.+):(\d+)$/;a=a.stacktrace.split("\n");for(var d=[],e=0,f=
+a.length;e<f;e++){var g=c.exec(a[e]);g&&d.push((g[1]?g[1]+"()":"global code")+"@"+g[2]+":"+g[3])}return d},opera10a:function(a){var c=/Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;a=a.stacktrace.split("\n");for(var d=[],e=0,f=a.length;e<f;e+=2){var g=c.exec(a[e]);g&&d.push((g[3]||"{anonymous}")+"()@"+g[2]+":"+g[1]+" -- "+a[e+1].replace(/^\s+/,""))}return d},opera9:function(a){var c=/Line (\d+).*script (?:in )?(\S+)/i;a=a.message.split("\n");for(var d=[],e=2,f=a.length;e<f;e+=2){var g=
+c.exec(a[e]);g&&d.push("{anonymous}()@"+g[2]+":"+g[1]+" -- "+a[e+1].replace(/^\s+/,""))}return d},phantomjs:function(a){var c=/(\S+) \((\S+)\)/i;a=a.stack.split("\n");for(var d=[],e=1,f=a.length;e<f;e++){a[e]=a[e].replace(/^\s+at\s+/gm,"");var g=c.exec(a[e]);g?d.push(g[1]+"()@"+g[2]):d.push("{anonymous}()@"+a[e])}return d},other:function(a){for(var c=/function(?:\s+([\w$]+))?\s*\(/,d=[],e,f,g=Array.prototype.slice;a&&10>d.length;){e=c.test(a.toString())?RegExp.$1||"{anonymous}":"{anonymous}";try{f=
+g.call(a.arguments||[])}catch(h){f=["Cannot access arguments: "+h]}d[d.length]=e+"("+this.stringifyArguments(f)+")";try{a=a.caller}catch(k){d[d.length]="Cannot access caller: "+k;break}}return d},stringifyArguments:function(a){for(var c=[],d=Array.prototype.slice,e=0;e<a.length;++e){var f=a[e];void 0===f?c[e]="undefined":null===f?c[e]="null":f.constructor&&(c[e]=f.constructor===Array?3>f.length?"["+this.stringifyArguments(f)+"]":"["+this.stringifyArguments(d.call(f,0,1))+"..."+this.stringifyArguments(d.call(f,
+-1))+"]":f.constructor===Object?"#object":f.constructor===Function?"#function":f.constructor===String?'"'+f+'"':f.constructor===Number?f:"?")}return c.join(",")},sourceCache:{},ajax:function(a){var c=this.createXMLHTTPObject();if(c)try{return c.open("GET",a,!1),c.send(null),c.responseText}catch(d){}return""},createXMLHTTPObject:function(){for(var a,c=[function(){return new XMLHttpRequest},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml3.XMLHTTP")},
+function(){return new ActiveXObject("Microsoft.XMLHTTP")}],d=0;d<c.length;d++)try{return a=c[d](),this.createXMLHTTPObject=c[d],a}catch(e){}},isSameDomain:function(a){return"undefined"!==typeof location&&-1!==a.indexOf(location.hostname)},getSource:function(a){a in this.sourceCache||(this.sourceCache[a]=this.ajax(a).split("\n"));return this.sourceCache[a]},guessAnonymousFunctions:function(a){for(var c=0;c<a.length;++c){var d=/^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/,e=a[c],f=/\{anonymous\}\(.*\)@(.*)/.exec(e);
+if(f){var g=d.exec(f[1]);g&&(d=g[1],f=g[2],g=g[3]||0,d&&this.isSameDomain(d)&&f&&(d=this.guessAnonymousFunction(d,f,g),a[c]=e.replace("{anonymous}",d)))}}return a},guessAnonymousFunction:function(a,c,d){var e;try{e=this.findFunctionName(this.getSource(a),c)}catch(f){e="getSource failed with url: "+a+", exception: "+f.toString()}return e},findFunctionName:function(a,c){for(var d=/function\s+([^(]*?)\s*\(([^)]*)\)/,e=/['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*function\b/,f=/['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*(?:eval|new Function)\b/,
+g="",h,k=Math.min(c,20),l,m=0;m<k;++m)if(h=a[c-m-1],l=h.indexOf("//"),0<=l&&(h=h.substr(0,l)),h)if(g=h+g,(h=e.exec(g))&&h[1]||(h=d.exec(g))&&h[1]||(h=f.exec(g))&&h[1])return h[1];return"(?)"}};return a});var ndn=ndn||{},exports=ndn,module={};function require(){return ndn}exports.printStackTrace=printStackTrace;
+function DetectSubtleCrypto(){var a=!1;if("undefined"!==typeof crypto&&crypto&&crypto.subtle){var b={name:"RSASSA-PKCS1-v1_5",modulusLength:2048,hash:{name:"SHA-256"},publicExponent:new Uint8Array([1,0,1])},c;crypto.subtle.generateKey(b,!0,["sign","verify"]).then(function(a){c=a;return crypto.subtle.sign(b,a.privateKey,new Uint8Array([1,2,3,4,5]))}).then(function(a){return crypto.subtle.verify(b,c.publicKey,a,new Uint8Array([1,2,3,4,5]))}).then(function(a){return crypto.subtle.exportKey("pkcs8",c.privateKey)}).then(function(a){return crypto.subtle.importKey("pkcs8",
+a,b,!0,["sign"])}).then(function(a){return crypto.subtle.exportKey("spki",c.publicKey)}).then(function(a){return crypto.subtle.importKey("spki",a,b,!0,["verify"])}).then(function(a){a=new Uint8Array([1,2,3,4,5]);return crypto.subtle.digest({name:"SHA-256"},a.buffer)}).then(function(b){a=!0},function(a){console.log("DetectSubtleCrypto encountered error, not using crypto.subtle: ",a)})}return function(){return a}}var UseSubtleCrypto=DetectSubtleCrypto();exports.UseSubtleCrypto=UseSubtleCrypto;
+var CryptoJS=CryptoJS||function(a,b){var c={},d=c.lib={},e=d.Base=function(){function a(){}return{extend:function(b){a.prototype=this;var c=new a;b&&c.mixIn(b);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},
+clone:function(){return this.init.prototype.extend(this)}}}(),f=d.WordArray=e.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=b?c:4*a.length},toString:function(a){return(a||h).stringify(this)},concat:function(a){var b=this.words,c=a.words,d=this.sigBytes;a=a.sigBytes;this.clamp();if(d%4)for(var e=0;e<a;e++)b[d+e>>>2]|=(c[e>>>2]>>>24-e%4*8&255)<<24-(d+e)%4*8;else for(e=0;e<a;e+=4)b[d+e>>>2]=c[e>>>2];this.sigBytes+=a;return this},clamp:function(){var b=this.words,c=this.sigBytes;b[c>>>
+2]&=4294967295<<32-c%4*8;b.length=a.ceil(c/4)},clone:function(){var a=e.clone.call(this);a.words=this.words.slice(0);return a},random:function(b){for(var c=[],d=0;d<b;d+=4)c.push(4294967296*a.random()|0);return new f.init(c,b)}}),g=c.enc={},h=g.Hex={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],d=0;d<a;d++){var e=b[d>>>2]>>>24-d%4*8&255;c.push((e>>>4).toString(16));c.push((e&15).toString(16))}return c.join("")},parse:function(a){for(var b=a.length,c=[],d=0;d<b;d+=2)c[d>>>3]|=parseInt(a.substr(d,
+2),16)<<24-d%8*4;return new f.init(c,b/2)}},k=g.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],d=0;d<a;d++)c.push(String.fromCharCode(b[d>>>2]>>>24-d%4*8&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],d=0;d<b;d++)c[d>>>2]|=(a.charCodeAt(d)&255)<<24-d%4*8;return new f.init(c,b)}},l=g.Utf8={stringify:function(a){try{return decodeURIComponent(escape(k.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return k.parse(unescape(encodeURIComponent(a)))}},
+m=d.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new f.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=l.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(b){var c=this._data,d=c.words,e=c.sigBytes,g=this.blockSize,h=e/(4*g),h=b?a.ceil(h):a.max((h|0)-this._minBufferSize,0);b=h*g;e=a.min(4*b,e);if(b){for(var k=0;k<b;k+=g)this._doProcessBlock(d,k);k=d.splice(0,b);c.sigBytes-=e}return new f.init(k,e)},clone:function(){var a=e.clone.call(this);
+a._data=this._data.clone();return a},_minBufferSize:0});d.Hasher=m.extend({cfg:e.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){m.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,c){return(new a.init(c)).finalize(b)}},_createHmacHelper:function(a){return function(b,c){return(new q.HMAC.init(a,
+c)).finalize(b)}}});var q=c.algo={};return c}(Math);exports.CryptoJS=CryptoJS;module.exports=exports;var C=require("./core.js").CryptoJS;
+(function(a){var b=C.lib,c=b.WordArray,d=b.Hasher,b=C.algo,e=[],f=[];(function(){function b(c){for(var d=a.sqrt(c),e=2;e<=d;e++)if(!(c%e))return!1;return!0}function c(a){return 4294967296*(a-(a|0))|0}for(var d=2,g=0;64>g;)b(d)&&(8>g&&(e[g]=c(a.pow(d,0.5))),f[g]=c(a.pow(d,1/3)),g++),d++})();var g=[],b=b.SHA256=d.extend({_doReset:function(){this._hash=new c.init(e.slice(0))},_doProcessBlock:function(a,b){for(var c=this._hash.words,d=c[0],e=c[1],p=c[2],s=c[3],w=c[4],M=c[5],O=c[6],K=c[7],x=0;64>x;x++){if(16>
+x)g[x]=a[b+x]|0;else{var A=g[x-15],I=g[x-2];g[x]=((A<<25|A>>>7)^(A<<14|A>>>18)^A>>>3)+g[x-7]+((I<<15|I>>>17)^(I<<13|I>>>19)^I>>>10)+g[x-16]}A=K+((w<<26|w>>>6)^(w<<21|w>>>11)^(w<<7|w>>>25))+(w&M^~w&O)+f[x]+g[x];I=((d<<30|d>>>2)^(d<<19|d>>>13)^(d<<10|d>>>22))+(d&e^d&p^e&p);K=O;O=M;M=w;w=s+A|0;s=p;p=e;e=d;d=A+I|0}c[0]=c[0]+d|0;c[1]=c[1]+e|0;c[2]=c[2]+p|0;c[3]=c[3]+s|0;c[4]=c[4]+w|0;c[5]=c[5]+M|0;c[6]=c[6]+O|0;c[7]=c[7]+K|0},_doFinalize:function(){var b=this._data,c=b.words,d=8*this._nDataBytes,e=8*b.sigBytes;
+c[e>>>5]|=128<<24-e%32;c[(e+64>>>9<<4)+14]=a.floor(d/4294967296);c[(e+64>>>9<<4)+15]=d;b.sigBytes=4*c.length;this._process();return this._hash},clone:function(){var a=d.clone.call(this);a._hash=this._hash.clone();return a}});C.SHA256=d._createHelper(b);C.HmacSHA256=d._createHmacHelper(b)})(Math);exports.CryptoJS=C;module.exports=exports;
+(function(){var a=CryptoJS,b=a.enc.Utf8;a.algo.HMAC=a.lib.Base.extend({init:function(a,d){a=this._hasher=new a.init;"string"==typeof d&&(d=b.parse(d));var e=a.blockSize,f=4*e;d.sigBytes>f&&(d=a.finalize(d));d.clamp();for(var g=this._oKey=d.clone(),h=this._iKey=d.clone(),k=g.words,l=h.words,m=0;m<e;m++)k[m]^=1549556828,l[m]^=909522486;g.sigBytes=h.sigBytes=f;this.reset()},reset:function(){var a=this._hasher;a.reset();a.update(this._iKey)},update:function(a){this._hasher.update(a);return this},finalize:function(a){var b=
+this._hasher;a=b.finalize(a);b.reset();return b.finalize(this._oKey.clone().concat(a))}})})();var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b64pad="=";
+function hex2b64(a){var b,c,d="";for(b=0;b+3<=a.length;b+=3)c=parseInt(a.substring(b,b+3),16),d+=b64map.charAt(c>>6)+b64map.charAt(c&63);b+1==a.length?(c=parseInt(a.substring(b,b+1),16),d+=b64map.charAt(c<<2)):b+2==a.length&&(c=parseInt(a.substring(b,b+2),16),d+=b64map.charAt(c>>2)+b64map.charAt((c&3)<<4));if(b64pad)for(;0<(d.length&3);)d+=b64pad;return d}
+function b64tohex(a){var b="",c,d=0,e,f;for(c=0;c<a.length&&a.charAt(c)!=b64pad;++c)f=b64map.indexOf(a.charAt(c)),0>f||(0==d?(b+=int2char(f>>2),e=f&3,d=1):1==d?(b+=int2char(e<<2|f>>4),e=f&15,d=2):2==d?(b+=int2char(e),b+=int2char(f>>2),e=f&3,d=3):(b+=int2char(e<<2|f>>4),b+=int2char(f&15),d=0));1==d&&(b+=int2char(e<<2));return b}function b64toBA(a){a=b64tohex(a);var b,c=[];for(b=0;2*b<a.length;++b)c[b]=parseInt(a.substring(2*b,2*b+2),16);return c}exports.b64tohex=b64tohex;exports.b64toBA=b64toBA;
+exports.hex2b64=hex2b64;module.exports=exports;function Arcfour(){this.j=this.i=0;this.S=[]}function ARC4init(a){var b,c,d;for(b=0;256>b;++b)this.S[b]=b;for(b=c=0;256>b;++b)c=c+this.S[b]+a[b%a.length]&255,d=this.S[b],this.S[b]=this.S[c],this.S[c]=d;this.j=this.i=0}function ARC4next(){var a;this.i=this.i+1&255;this.j=this.j+this.S[this.i]&255;a=this.S[this.i];this.S[this.i]=this.S[this.j];this.S[this.j]=a;return this.S[a+this.S[this.i]&255]}Arcfour.prototype.init=ARC4init;Arcfour.prototype.next=ARC4next;
+function prng_newstate(){return new Arcfour}var rng_psize=256,rng_state,rng_pool,rng_pptr;function rng_seed_int(a){rng_pool[rng_pptr++]^=a&255;rng_pool[rng_pptr++]^=a>>8&255;rng_pool[rng_pptr++]^=a>>16&255;rng_pool[rng_pptr++]^=a>>24&255;rng_pptr>=rng_psize&&(rng_pptr-=rng_psize)}function rng_seed_time(){rng_seed_int((new Date).getTime())}
+if(null==rng_pool){rng_pool=[];rng_pptr=0;var t;if("Netscape"==navigator.appName&&"5">navigator.appVersion&&window.crypto){var z=window.crypto.random(32);for(t=0;t<z.length;++t)rng_pool[rng_pptr++]=z.charCodeAt(t)&255}for(;rng_pptr<rng_psize;)t=Math.floor(65536*Math.random()),rng_pool[rng_pptr++]=t>>>8,rng_pool[rng_pptr++]=t&255;rng_pptr=0;rng_seed_time()}
+function rng_get_byte(){if(null==rng_state){rng_seed_time();rng_state=prng_newstate();rng_state.init(rng_pool);for(rng_pptr=0;rng_pptr<rng_pool.length;++rng_pptr)rng_pool[rng_pptr]=0;rng_pptr=0}return rng_state.next()}function rng_get_bytes(a){var b;for(b=0;b<a.length;++b)a[b]=rng_get_byte()}function SecureRandom(){}SecureRandom.prototype.nextBytes=rng_get_bytes;var intShim=require("jsbn");function parseBigInt(a,b){return new BigInteger(a,b)}
+function linebrk(a,b){for(var c="",d=0;d+b<a.length;)c+=a.substring(d,d+b)+"\n",d+=b;return c+a.substring(d,a.length)}function byte2Hex(a){return 16>a?"0"+a.toString(16):a.toString(16)}
+function pkcs1pad2(a,b){if(b<a.length+11)return alert("Message too long for RSA"),null;for(var c=[],d=a.length-1;0<=d&&0<b;){var e=a.charCodeAt(d--);128>e?c[--b]=e:127<e&&2048>e?(c[--b]=e&63|128,c[--b]=e>>6|192):(c[--b]=e&63|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;d=new SecureRandom;for(e=[];2<b;){for(e[0]=0;0==e[0];)d.nextBytes(e);c[--b]=e[0]}c[--b]=2;c[--b]=0;return new BigInteger(c)}
+function oaep_mgf1_arr(a,b,c){for(var d="",e=0;d.length<b;)d+=c(String.fromCharCode.apply(String,a.concat([(e&4278190080)>>24,(e&16711680)>>16,(e&65280)>>8,e&255]))),e+=1;return d}var SHA1_SIZE=20;
+function oaep_pad(a,b,c){if(a.length+2*SHA1_SIZE+2>b)throw"Message too long for RSA";var d="",e;for(e=0;e<b-a.length-2*SHA1_SIZE-2;e+=1)d+="\x00";b=rstr_sha1("")+d+"\u0001"+a;a=Array(SHA1_SIZE);(new SecureRandom).nextBytes(a);d=oaep_mgf1_arr(a,b.length,c||rstr_sha1);c=[];for(e=0;e<b.length;e+=1)c[e]=b.charCodeAt(e)^d.charCodeAt(e);b=oaep_mgf1_arr(c,a.length,rstr_sha1);d=[0];for(e=0;e<a.length;e+=1)d[e+1]=a[e]^b.charCodeAt(e);return new BigInteger(d.concat(c))}
+function RSAKey(){this.n=null;this.e=0;this.coeff=this.dmq1=this.dmp1=this.q=this.p=this.d=null}function RSASetPublic(a,b){this.isPublic=!0;"string"!==typeof a?(this.n=a,this.e=b):null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16)):alert("Invalid RSA public key")}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}
+function RSAEncrypt(a){a=pkcs1pad2(a,this.n.bitLength()+7>>3);if(null==a)return null;a=this.doPublic(a);if(null==a)return null;a=a.toString(16);return 0==(a.length&1)?a:"0"+a}function RSAEncryptOAEP(a,b){var c=oaep_pad(a,this.n.bitLength()+7>>3,b);if(null==c)return null;c=this.doPublic(c);if(null==c)return null;c=c.toString(16);return 0==(c.length&1)?c:"0"+c}RSAKey.prototype.doPublic=RSADoPublic;RSAKey.prototype.setPublic=RSASetPublic;RSAKey.prototype.encrypt=RSAEncrypt;
+RSAKey.prototype.encryptOAEP=RSAEncryptOAEP;RSAKey.prototype.type="RSA";exports.RSAKey=RSAKey;module.exports=exports;var intShim=require("jsbn"),BigInteger=intShim.BigInteger?intShim.BigInteger:intShim,RSAKey=require("./rsa.js").RSAKey;
 function pkcs1unpad2(a,b){for(var c=a.toByteArray(),d=0;d<c.length&&0==c[d];)++d;if(c.length-d!=b-1||2!=c[d])return null;for(++d;0!=c[d];)if(++d>=c.length)return null;for(var e="";++d<c.length;){var f=c[d]&255;128>f?e+=String.fromCharCode(f):191<f&&224>f?(e+=String.fromCharCode((f&31)<<6|c[d+1]&63),++d):(e+=String.fromCharCode((f&15)<<12|(c[d+1]&63)<<6|c[d+2]&63),d+=2)}return e}
-function RSASetPrivate(a,b,c){null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16)):alert("Invalid RSA private key")}
-function RSASetPrivateEx(a,b,c,d,e,f,g,h){null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16),this.p=parseBigInt(d,16),this.q=parseBigInt(e,16),this.dmp1=parseBigInt(f,16),this.dmq1=parseBigInt(g,16),this.coeff=parseBigInt(h,16)):alert("Invalid RSA private key")}
-function RSAGenerate(a,b){var c=new SecureRandom,d=a>>1;this.e=parseInt(b,16);for(var e=new BigInteger(b,16);;){for(;!(this.p=new BigInteger(a-d,1,c),0==this.p.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)&&this.p.isProbablePrime(10)););for(;!(this.q=new BigInteger(d,1,c),0==this.q.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)&&this.q.isProbablePrime(10)););if(0>=this.p.compareTo(this.q)){var f=this.p;this.p=this.q;this.q=f}var f=this.p.subtract(BigInteger.ONE),g=this.q.subtract(BigInteger.ONE),
-h=f.multiply(g);if(0==h.gcd(e).compareTo(BigInteger.ONE)){this.n=this.p.multiply(this.q);this.d=e.modInverse(h);this.dmp1=this.d.mod(f);this.dmq1=this.d.mod(g);this.coeff=this.q.modInverse(this.p);break}}}function RSADoPrivate(a){if(null==this.p||null==this.q)return a.modPow(this.d,this.n);var b=a.mod(this.p).modPow(this.dmp1,this.p);for(a=a.mod(this.q).modPow(this.dmq1,this.q);0>b.compareTo(a);)b=b.add(this.p);return b.subtract(a).multiply(this.coeff).mod(this.p).multiply(this.q).add(a)}
-function RSADecrypt(a){a=parseBigInt(a,16);a=this.doPrivate(a);return null==a?null:pkcs1unpad2(a,this.n.bitLength()+7>>3)}RSAKey.prototype.doPrivate=RSADoPrivate;RSAKey.prototype.setPrivate=RSASetPrivate;RSAKey.prototype.setPrivateEx=RSASetPrivateEx;RSAKey.prototype.generate=RSAGenerate;RSAKey.prototype.decrypt=RSADecrypt;function _rsapem_pemToBase64(a){a=a.replace("-----BEGIN RSA PRIVATE KEY-----","");a=a.replace("-----END RSA PRIVATE KEY-----","");return a=a.replace(/[ \n]+/g,"")}
-function _rsapem_getPosArrayOfChildrenFromHex(a){var b=[],c=ASN1HEX.getStartPosOfV_AtObj(a,0),d=ASN1HEX.getPosOfNextSibling_AtObj(a,c),e=ASN1HEX.getPosOfNextSibling_AtObj(a,d),f=ASN1HEX.getPosOfNextSibling_AtObj(a,e),g=ASN1HEX.getPosOfNextSibling_AtObj(a,f),h=ASN1HEX.getPosOfNextSibling_AtObj(a,g),j=ASN1HEX.getPosOfNextSibling_AtObj(a,h),l=ASN1HEX.getPosOfNextSibling_AtObj(a,j);a=ASN1HEX.getPosOfNextSibling_AtObj(a,l);b.push(c,d,e,f,g,h,j,l,a);return b}
-function _rsapem_getHexValueArrayOfChildrenFromHex(a){var b=_rsapem_getPosArrayOfChildrenFromHex(a),c=ASN1HEX.getHexOfV_AtObj(a,b[0]),d=ASN1HEX.getHexOfV_AtObj(a,b[1]),e=ASN1HEX.getHexOfV_AtObj(a,b[2]),f=ASN1HEX.getHexOfV_AtObj(a,b[3]),g=ASN1HEX.getHexOfV_AtObj(a,b[4]),h=ASN1HEX.getHexOfV_AtObj(a,b[5]),j=ASN1HEX.getHexOfV_AtObj(a,b[6]),l=ASN1HEX.getHexOfV_AtObj(a,b[7]);a=ASN1HEX.getHexOfV_AtObj(a,b[8]);b=[];b.push(c,d,e,f,g,h,j,l,a);return b}
-function _rsapem_readPrivateKeyFromPEMString(a){a=_rsapem_pemToBase64(a);a=b64tohex(a);a=_rsapem_getHexValueArrayOfChildrenFromHex(a);this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])}RSAKey.prototype.readPrivateKeyFromPEMString=_rsapem_readPrivateKeyFromPEMString;var _RSASIGN_DIHEAD=[];_RSASIGN_DIHEAD.sha1="3021300906052b0e03021a05000414";_RSASIGN_DIHEAD.sha256="3031300d060960864801650304020105000420";_RSASIGN_DIHEAD.sha384="3041300d060960864801650304020205000430";
-_RSASIGN_DIHEAD.sha512="3051300d060960864801650304020305000440";_RSASIGN_DIHEAD.md2="3020300c06082a864886f70d020205000410";_RSASIGN_DIHEAD.md5="3020300c06082a864886f70d020505000410";_RSASIGN_DIHEAD.ripemd160="3021300906052b2403020105000414";var _RSASIGN_HASHHEXFUNC=[];_RSASIGN_HASHHEXFUNC.sha1=function(a){return hex_sha1(a)};_RSASIGN_HASHHEXFUNC.sha256=function(a){return hex_sha256(a)};_RSASIGN_HASHHEXFUNC.sha512=function(a){return hex_sha512(a)};_RSASIGN_HASHHEXFUNC.md5=function(a){return hex_md5(a)};
-_RSASIGN_HASHHEXFUNC.ripemd160=function(a){return hex_rmd160(a)};var _RSASIGN_HASHBYTEFUNC=[];_RSASIGN_HASHBYTEFUNC.sha256=function(a){return hex_sha256_from_bytes(a)};var _RE_HEXDECONLY=RegExp("");_RE_HEXDECONLY.compile("[^0-9a-f]","gi");function _rsasign_getHexPaddedDigestInfoForString(a,b,c){b/=4;a=(0,_RSASIGN_HASHHEXFUNC[c])(a);c="00"+_RSASIGN_DIHEAD[c]+a;a="";b=b-4-c.length;for(var d=0;d<b;d+=2)a+="ff";return sPaddedMessageHex="0001"+a+c}
-function _rsasign_getHexPaddedDigestInfoForStringHEX(a,b,c){b/=4;a=(0,_RSASIGN_HASHHEXFUNC[c])(a);c="00"+_RSASIGN_DIHEAD[c]+a;a="";b=b-4-c.length;for(var d=0;d<b;d+=2)a+="ff";return sPaddedMessageHex="0001"+a+c}function _rsasign_getHexPaddedDigestInfoForByteArray(a,b,c){b/=4;a=(0,_RSASIGN_HASHBYTEFUNC[c])(a);c="00"+_RSASIGN_DIHEAD[c]+a;a="";b=b-4-c.length;for(var d=0;d<b;d+=2)a+="ff";return sPaddedMessageHex="0001"+a+c}
-function _zeroPaddingOfSignature(a,b){for(var c="",d=b/4-a.length,e=0;e<d;e++)c+="0";return c+a}function _rsasign_signString(a,b){var c=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),b),c=parseBigInt(c,16),c=this.doPrivate(c).toString(16);return _zeroPaddingOfSignature(c,this.n.bitLength())}
-function _rsasign_signStringHEX(a,b){var c=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),b),c=parseBigInt(c,16),c=this.doPrivate(c).toString(16);return _zeroPaddingOfSignature(c,this.n.bitLength())}function _rsasign_signByteArray(a,b,c){a=_rsasign_getHexPaddedDigestInfoForByteArray(a,c.n.bitLength(),b);a=parseBigInt(a,16);a=c.doPrivate(a).toString(16);return _zeroPaddingOfSignature(a,c.n.bitLength())}
-function _rsasign_signByteArrayWithSHA256(a){return _rsasign_signByteArray(a,"sha256",this)}function _rsasign_signStringWithSHA1(a){return _rsasign_signString(a,"sha1")}function _rsasign_signStringWithSHA256(a){return _rsasign_signString(a,"sha256")}function _rsasign_getDecryptSignatureBI(a,b,c){var d=new RSAKey;d.setPublic(b,c);return d.doPublic(a)}function _rsasign_getHexDigestInfoFromSig(a,b,c){return _rsasign_getDecryptSignatureBI(a,b,c).toString(16).replace(/^1f+00/,"")}
-function _rsasign_getAlgNameAndHashFromHexDisgestInfo(a){for(var b in _RSASIGN_DIHEAD){var c=_RSASIGN_DIHEAD[b],d=c.length;if(a.substring(0,d)==c)return[b,a.substring(d)]}return[]}function _rsasign_verifySignatureWithArgs(a,b,c,d){b=_rsasign_getHexDigestInfoFromSig(b,c,d);c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(b);if(0==c.length)return!1;b=c[1];a=(0,_RSASIGN_HASHHEXFUNC[c[0]])(a);return b==a}
-function _rsasign_verifyHexSignatureForMessage(a,b){var c=parseBigInt(a,16);return _rsasign_verifySignatureWithArgs(b,c,this.n.toString(16),this.e.toString(16))}
-function _rsasign_verifyString(a,b){b=b.replace(_RE_HEXDECONLY,"");3<LOG&&console.log("n is "+this.n);3<LOG&&console.log("e is "+this.e);if(b.length!=this.n.bitLength()/4)return 0;b=b.replace(/[ \n]+/g,"");var c=parseBigInt(b,16),c=this.doPublic(c).toString(16).replace(/^1f+00/,""),d=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);if(0==d.length)return!1;c=d[1];d=(0,_RSASIGN_HASHHEXFUNC[d[0]])(a);return c==d}
-function _rsasign_verifyByteArray(a,b,c){c=c.replace(_RE_HEXDECONLY,"");3<LOG&&console.log("n is "+this.n);3<LOG&&console.log("e is "+this.e);if(c.length!=this.n.bitLength()/4)return 0;c=c.replace(/[ \n]+/g,"");c=parseBigInt(c,16);c=this.doPublic(c).toString(16).replace(/^1f+00/,"");c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);if(0==c.length)return!1;var d=c[0];c=c[1];var e=null;if(null==b)e=(0,_RSASIGN_HASHBYTEFUNC[d])(a);else{a=hex_sha256_from_bytes(a);d=b.path.index;for(e=b.path.digestList.length-
-1;0<=e;e--){var f="",f=0==d%2?a+b.path.digestList[e]:b.path.digestList[e]+a;a=hex_sha256_from_bytes(DataUtils.toNumbers(f));d=Math.floor(d/2)}e=hex_sha256_from_bytes(DataUtils.toNumbers(a))}return c==e}RSAKey.prototype.signString=_rsasign_signString;RSAKey.prototype.signByteArray=_rsasign_signByteArray;RSAKey.prototype.signByteArrayWithSHA256=_rsasign_signByteArrayWithSHA256;RSAKey.prototype.signStringWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signStringWithSHA256=_rsasign_signStringWithSHA256;
-RSAKey.prototype.sign=_rsasign_signString;RSAKey.prototype.signWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signWithSHA256=_rsasign_signStringWithSHA256;RSAKey.prototype.verifyByteArray=_rsasign_verifyByteArray;RSAKey.prototype.verifyString=_rsasign_verifyString;RSAKey.prototype.verifyHexSignatureForMessage=_rsasign_verifyHexSignatureForMessage;RSAKey.prototype.verify=_rsasign_verifyString;RSAKey.prototype.verifyHexSignatureForByteArrayMessage=_rsasign_verifyHexSignatureForMessage;
-function _asnhex_getByteLengthOfL_AtObj(a,b){if("8"!=a.substring(b+2,b+3))return 1;var c=parseInt(a.substring(b+3,b+4));return 0==c?-1:0<c&&10>c?c+1:-2}function _asnhex_getHexOfL_AtObj(a,b){var c=_asnhex_getByteLengthOfL_AtObj(a,b);return 1>c?"":a.substring(b+2,b+2+2*c)}function _asnhex_getIntOfL_AtObj(a,b){var c=_asnhex_getHexOfL_AtObj(a,b);return""==c?-1:(8>parseInt(c.substring(0,1))?parseBigInt(c,16):parseBigInt(c.substring(2),16)).intValue()}
-function _asnhex_getStartPosOfV_AtObj(a,b){var c=_asnhex_getByteLengthOfL_AtObj(a,b);return 0>c?c:b+2*(c+1)}function _asnhex_getHexOfV_AtObj(a,b){var c=_asnhex_getStartPosOfV_AtObj(a,b),d=_asnhex_getIntOfL_AtObj(a,b);return a.substring(c,c+2*d)}function _asnhex_getHexOfTLV_AtObj(a,b){var c=a.substr(b,2),d=_asnhex_getHexOfL_AtObj(a,b),e=_asnhex_getHexOfV_AtObj(a,b);return c+d+e}
-function _asnhex_getPosOfNextSibling_AtObj(a,b){var c=_asnhex_getStartPosOfV_AtObj(a,b),d=_asnhex_getIntOfL_AtObj(a,b);return c+2*d}function _asnhex_getPosArrayOfChildren_AtObj(a,b){var c=[],d=_asnhex_getStartPosOfV_AtObj(a,b);c.push(d);for(var e=_asnhex_getIntOfL_AtObj(a,b),f=d,g=0;;){f=_asnhex_getPosOfNextSibling_AtObj(a,f);if(null==f||f-d>=2*e)break;if(200<=g)break;c.push(f);g++}return c}function _asnhex_getNthChildIndex_AtObj(a,b,c){return _asnhex_getPosArrayOfChildren_AtObj(a,b)[c]}
-function _asnhex_getDecendantIndexByNthList(a,b,c){if(0==c.length)return b;var d=c.shift();b=_asnhex_getPosArrayOfChildren_AtObj(a,b);return _asnhex_getDecendantIndexByNthList(a,b[d],c)}function _asnhex_getDecendantHexTLVByNthList(a,b,c){b=_asnhex_getDecendantIndexByNthList(a,b,c);return _asnhex_getHexOfTLV_AtObj(a,b)}function _asnhex_getDecendantHexVByNthList(a,b,c){b=_asnhex_getDecendantIndexByNthList(a,b,c);return _asnhex_getHexOfV_AtObj(a,b)}function ASN1HEX(){return ASN1HEX}
-ASN1HEX.getByteLengthOfL_AtObj=_asnhex_getByteLengthOfL_AtObj;ASN1HEX.getHexOfL_AtObj=_asnhex_getHexOfL_AtObj;ASN1HEX.getIntOfL_AtObj=_asnhex_getIntOfL_AtObj;ASN1HEX.getStartPosOfV_AtObj=_asnhex_getStartPosOfV_AtObj;ASN1HEX.getHexOfV_AtObj=_asnhex_getHexOfV_AtObj;ASN1HEX.getHexOfTLV_AtObj=_asnhex_getHexOfTLV_AtObj;ASN1HEX.getPosOfNextSibling_AtObj=_asnhex_getPosOfNextSibling_AtObj;ASN1HEX.getPosArrayOfChildren_AtObj=_asnhex_getPosArrayOfChildren_AtObj;ASN1HEX.getNthChildIndex_AtObj=_asnhex_getNthChildIndex_AtObj;
-ASN1HEX.getDecendantIndexByNthList=_asnhex_getDecendantIndexByNthList;ASN1HEX.getDecendantHexVByNthList=_asnhex_getDecendantHexVByNthList;ASN1HEX.getDecendantHexTLVByNthList=_asnhex_getDecendantHexTLVByNthList;function _x509_pemToBase64(a){a=a.replace("-----BEGIN CERTIFICATE-----","");a=a.replace("-----END CERTIFICATE-----","");return a=a.replace(/[ \n]+/g,"")}function _x509_pemToHex(a){a=_x509_pemToBase64(a);return b64tohex(a)}
-function _x509_getHexTbsCertificateFromCert(a){return ASN1HEX.getStartPosOfV_AtObj(a,0)}function _x509_getSubjectPublicKeyInfoPosFromCertHex(a){var b=ASN1HEX.getStartPosOfV_AtObj(a,0),b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);return 1>b.length?-1:"a003020102"==a.substring(b[0],b[0]+10)?6>b.length?-1:b[6]:5>b.length?-1:b[5]}
-function _x509_getSubjectPublicKeyPosFromCertHex(a,b){null==b&&(b=_x509_getSubjectPublicKeyInfoPosFromCertHex(a));if(-1==b)return-1;var c=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);if(2!=c.length)return-1;c=c[1];if("03"!=a.substring(c,c+2))return-1;c=ASN1HEX.getStartPosOfV_AtObj(a,c);return"00"!=a.substring(c,c+2)?-1:c+2}
-function _x509_getPublicKeyHexArrayFromCertHex(a,b){null==b&&(b=_x509_getSubjectPublicKeyPosFromCertHex(a));var c=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);4<LOG&&(console.log("a is now"),console.log(c));if(2>c.length)return[];var d=ASN1HEX.getHexOfV_AtObj(a,c[0]),c=ASN1HEX.getHexOfV_AtObj(a,c[1]);return null!=d&&null!=c?[d,c]:[]}function _x509_getPublicKeyHexArrayFromCertPEM(a){a=_x509_pemToHex(a);return _x509_getPublicKeyHexArrayFromCertHex(a)}
-function _x509_getSerialNumberHex(){return ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,1])}function _x509_getIssuerHex(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3])}function _x509_getIssuerString(){return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3]))}function _x509_getSubjectHex(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5])}function _x509_getSubjectString(){return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5]))}
-function _x509_getNotBefore(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,0]),a=a.replace(/(..)/g,"%$1");return a=decodeURIComponent(a)}function _x509_getNotAfter(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,1]),a=a.replace(/(..)/g,"%$1");return a=decodeURIComponent(a)}_x509_DN_ATTRHEX={"0603550406":"C","060355040a":"O","060355040b":"OU","0603550403":"CN","0603550405":"SN","0603550408":"ST","0603550407":"L"};
-function _x509_hex2dn(a){for(var b="",c=ASN1HEX.getPosArrayOfChildren_AtObj(a,0),d=0;d<c.length;d++)var e=ASN1HEX.getHexOfTLV_AtObj(a,c[d]),b=b+"/"+_x509_hex2rdn(e);return b}function _x509_hex2rdn(a){var b=ASN1HEX.getDecendantHexTLVByNthList(a,0,[0,0]),c=ASN1HEX.getDecendantHexVByNthList(a,0,[0,1]);a="";try{a=_x509_DN_ATTRHEX[b]}catch(d){a=b}c=c.replace(/(..)/g,"%$1");b=decodeURIComponent(c);return a+"="+b}
-function _x509_readCertPEM(a){a=_x509_pemToHex(a);var b=_x509_getPublicKeyHexArrayFromCertHex(a);4<LOG&&(console.log("HEX VALUE IS "+a),console.log("type of a"+typeof b),console.log("a VALUE IS "),console.log(b),console.log("a[0] VALUE IS "+b[0]),console.log("a[1] VALUE IS "+b[1]));var c=new RSAKey;c.setPublic(b[0],b[1]);this.subjectPublicKeyRSA=c;this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a}
-function _x509_readCertHex(a){a=a.toLowerCase();var b=_x509_getPublicKeyHexArrayFromCertHex(a),c=new RSAKey;c.setPublic(b[0],b[1]);this.subjectPublicKeyRSA=c;this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a}function _x509_readCertPEMWithoutRSAInit(a){a=_x509_pemToHex(a);var b=_x509_getPublicKeyHexArrayFromCertHex(a);this.subjectPublicKeyRSA.setPublic(b[0],b[1]);this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a}
-function X509(){this.hex=this.subjectPublicKeyRSA_hE=this.subjectPublicKeyRSA_hN=this.subjectPublicKeyRSA=null}X509.prototype.readCertPEM=_x509_readCertPEM;X509.prototype.readCertHex=_x509_readCertHex;X509.prototype.readCertPEMWithoutRSAInit=_x509_readCertPEMWithoutRSAInit;X509.prototype.getSerialNumberHex=_x509_getSerialNumberHex;X509.prototype.getIssuerHex=_x509_getIssuerHex;X509.prototype.getSubjectHex=_x509_getSubjectHex;X509.prototype.getIssuerString=_x509_getIssuerString;
-X509.prototype.getSubjectString=_x509_getSubjectString;X509.prototype.getNotBefore=_x509_getNotBefore;X509.prototype.getNotAfter=_x509_getNotAfter;var dbits,canary=0xdeadbeefcafe,j_lm=15715070==(canary&16777215);function BigInteger(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}
-function am1(a,b,c,d,e,f){for(;0<=--f;){var g=b*this[a++]+c[d]+e;e=Math.floor(g/67108864);c[d++]=g&67108863}return e}function am2(a,b,c,d,e,f){var g=b&32767;for(b>>=15;0<=--f;){var h=this[a]&32767,j=this[a++]>>15,l=b*h+j*g,h=g*h+((l&32767)<<15)+c[d]+(e&1073741823);e=(h>>>30)+(l>>>15)+b*j+(e>>>30);c[d++]=h&1073741823}return e}
-function am3(a,b,c,d,e,f){var g=b&16383;for(b>>=14;0<=--f;){var h=this[a]&16383,j=this[a++]>>14,l=b*h+j*g,h=g*h+((l&16383)<<14)+c[d]+e;e=(h>>28)+(l>>14)+b*j;c[d++]=h&268435455}return e}j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28);BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;
+function oaep_mgf1_str(a,b,c){for(var d="",e=0;d.length<b;)d+=c(a+String.fromCharCode.apply(String,[(e&4278190080)>>24,(e&16711680)>>16,(e&65280)>>8,e&255])),e+=1;return d}SHA1_SIZE=20;
+function oaep_unpad(a,b,c){a=a.toByteArray();var d;for(d=0;d<a.length;d+=1)a[d]&=255;for(;a.length<b;)a.unshift(0);a=String.fromCharCode.apply(String,a);if(a.length<2*SHA1_SIZE+2)throw"Cipher too short";var e=a.substr(1,SHA1_SIZE);b=a.substr(SHA1_SIZE+1);c=oaep_mgf1_str(b,SHA1_SIZE,c||rstr_sha1);var f=[];for(d=0;d<e.length;d+=1)f[d]=e.charCodeAt(d)^c.charCodeAt(d);e=oaep_mgf1_str(String.fromCharCode.apply(String,f),a.length-SHA1_SIZE,rstr_sha1);a=[];for(d=0;d<b.length;d+=1)a[d]=b.charCodeAt(d)^e.charCodeAt(d);
+a=String.fromCharCode.apply(String,a);if(a.substr(0,SHA1_SIZE)!==rstr_sha1(""))throw"Hash mismatch";a=a.substr(SHA1_SIZE);d=a.indexOf("\u0001");if((-1!=d?a.substr(0,d).lastIndexOf("\x00"):-1)+1!=d)throw"Malformed data";return a.substr(d+1)}function RSASetPrivate(a,b,c){this.isPrivate=!0;"string"!==typeof a?(this.n=a,this.e=b,this.d=c):null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16)):alert("Invalid RSA private key")}
+function RSASetPrivateEx(a,b,c,d,e,f,g,h){this.isPrivate=!0;if(null==a)throw"RSASetPrivateEx N == null";if(null==b)throw"RSASetPrivateEx E == null";if(0==a.length)throw"RSASetPrivateEx N.length == 0";if(0==b.length)throw"RSASetPrivateEx E.length == 0";null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16),this.p=parseBigInt(d,16),this.q=parseBigInt(e,16),this.dmp1=parseBigInt(f,16),this.dmq1=parseBigInt(g,16),this.coeff=parseBigInt(h,16)):
+alert("Invalid RSA private key in RSASetPrivateEx")}
+function RSAGenerate(a,b){var c=new SecureRandom,d=a>>1;this.e=parseInt(b,16);for(var e=new BigInteger(b,16);;){for(;this.p=new BigInteger(a-d,1,c),0!=this.p.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)||!this.p.isProbablePrime(10););for(;this.q=new BigInteger(d,1,c),0!=this.q.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)||!this.q.isProbablePrime(10););if(0>=this.p.compareTo(this.q)){var f=this.p;this.p=this.q;this.q=f}var f=this.p.subtract(BigInteger.ONE),g=this.q.subtract(BigInteger.ONE),
+h=f.multiply(g);if(0==h.gcd(e).compareTo(BigInteger.ONE)){this.n=this.p.multiply(this.q);this.d=e.modInverse(h);this.dmp1=this.d.mod(f);this.dmq1=this.d.mod(g);this.coeff=this.q.modInverse(this.p);break}}this.isPrivate=!0}
+function RSADoPrivate(a){if(null==this.p||null==this.q)return a.modPow(this.d,this.n);var b=a.mod(this.p).modPow(this.dmp1,this.p);for(a=a.mod(this.q).modPow(this.dmq1,this.q);0>b.compareTo(a);)b=b.add(this.p);return b.subtract(a).multiply(this.coeff).mod(this.p).multiply(this.q).add(a)}function RSADecrypt(a){a=parseBigInt(a,16);a=this.doPrivate(a);return null==a?null:pkcs1unpad2(a,this.n.bitLength()+7>>3)}
+function RSADecryptOAEP(a,b){var c=parseBigInt(a,16),c=this.doPrivate(c);return null==c?null:oaep_unpad(c,this.n.bitLength()+7>>3,b)}RSAKey.prototype.doPrivate=RSADoPrivate;RSAKey.prototype.setPrivate=RSASetPrivate;RSAKey.prototype.setPrivateEx=RSASetPrivateEx;RSAKey.prototype.generate=RSAGenerate;RSAKey.prototype.decrypt=RSADecrypt;RSAKey.prototype.decryptOAEP=RSADecryptOAEP;exports.RSAKey=RSAKey;module.exports=exports;CryptoJS=require("./sha256.js").CryptoJS;intShim=require("jsbn");
+"undefined"!=typeof KJUR&&KJUR||(KJUR={});"undefined"!=typeof KJUR.crypto&&KJUR.crypto||(KJUR.crypto={});
+KJUR.crypto.Util=new function(){this.DIGESTINFOHEAD={sha1:"3021300906052b0e03021a05000414",sha224:"302d300d06096086480165030402040500041c",sha256:"3031300d060960864801650304020105000420",sha384:"3041300d060960864801650304020205000430",sha512:"3051300d060960864801650304020305000440",md2:"3020300c06082a864886f70d020205000410",md5:"3020300c06082a864886f70d020505000410",ripemd160:"3021300906052b2403020105000414"};this.DEFAULTPROVIDER={md5:"cryptojs",sha1:"cryptojs",sha224:"cryptojs",sha256:"cryptojs",
+sha384:"cryptojs",sha512:"cryptojs",ripemd160:"cryptojs",hmacmd5:"cryptojs",hmacsha1:"cryptojs",hmacsha224:"cryptojs",hmacsha256:"cryptojs",hmacsha384:"cryptojs",hmacsha512:"cryptojs",hmacripemd160:"cryptojs",MD5withRSA:"cryptojs/jsrsa",SHA1withRSA:"cryptojs/jsrsa",SHA224withRSA:"cryptojs/jsrsa",SHA256withRSA:"cryptojs/jsrsa",SHA384withRSA:"cryptojs/jsrsa",SHA512withRSA:"cryptojs/jsrsa",RIPEMD160withRSA:"cryptojs/jsrsa",MD5withECDSA:"cryptojs/jsrsa",SHA1withECDSA:"cryptojs/jsrsa",SHA224withECDSA:"cryptojs/jsrsa",
+SHA256withECDSA:"cryptojs/jsrsa",SHA384withECDSA:"cryptojs/jsrsa",SHA512withECDSA:"cryptojs/jsrsa",RIPEMD160withECDSA:"cryptojs/jsrsa",SHA1withDSA:"cryptojs/jsrsa",SHA224withDSA:"cryptojs/jsrsa",SHA256withDSA:"cryptojs/jsrsa",MD5withRSAandMGF1:"cryptojs/jsrsa",SHA1withRSAandMGF1:"cryptojs/jsrsa",SHA224withRSAandMGF1:"cryptojs/jsrsa",SHA256withRSAandMGF1:"cryptojs/jsrsa",SHA384withRSAandMGF1:"cryptojs/jsrsa",SHA512withRSAandMGF1:"cryptojs/jsrsa",RIPEMD160withRSAandMGF1:"cryptojs/jsrsa"};this.CRYPTOJSMESSAGEDIGESTNAME=
+{md5:"CryptoJS.algo.MD5",sha1:"CryptoJS.algo.SHA1",sha224:"CryptoJS.algo.SHA224",sha256:"CryptoJS.algo.SHA256",sha384:"CryptoJS.algo.SHA384",sha512:"CryptoJS.algo.SHA512",ripemd160:"CryptoJS.algo.RIPEMD160"};this.getDigestInfoHex=function(a,b){if("undefined"==typeof this.DIGESTINFOHEAD[b])throw"alg not supported in Util.DIGESTINFOHEAD: "+b;return this.DIGESTINFOHEAD[b]+a};this.getPaddedDigestInfoHex=function(a,b,c){var d=this.getDigestInfoHex(a,b);a=c/4;if(d.length+22>a)throw"key is too short for SigAlg: keylen="+
+c+","+b;b="00"+d;c="";a=a-4-b.length;for(d=0;d<a;d+=2)c+="ff";return"0001"+c+b};this.hashString=function(a,b){return(new KJUR.crypto.MessageDigest({alg:b})).digestString(a)};this.hashHex=function(a,b){return(new KJUR.crypto.MessageDigest({alg:b})).digestHex(a)};this.sha1=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha1",prov:"cryptojs"})).digestString(a)};this.sha256=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha256",prov:"cryptojs"})).digestString(a)};this.sha256Hex=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha256",
+prov:"cryptojs"})).digestHex(a)};this.sha512=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha512",prov:"cryptojs"})).digestString(a)};this.sha512Hex=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha512",prov:"cryptojs"})).digestHex(a)};this.md5=function(a){return(new KJUR.crypto.MessageDigest({alg:"md5",prov:"cryptojs"})).digestString(a)};this.ripemd160=function(a){return(new KJUR.crypto.MessageDigest({alg:"ripemd160",prov:"cryptojs"})).digestString(a)};this.getCryptoJSMDByName=
+function(a){}};
+KJUR.crypto.MessageDigest=function(a){this.setAlgAndProvider=function(a,c){null!=a&&void 0===c&&(c=KJUR.crypto.Util.DEFAULTPROVIDER[a]);if(-1!=":md5:sha1:sha224:sha256:sha384:sha512:ripemd160:".indexOf(a)&&"cryptojs"==c){try{this.md=eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[a]).create()}catch(d){throw"setAlgAndProvider hash alg set fail alg="+a+"/"+d;}this.updateString=function(a){this.md.update(a)};this.updateHex=function(a){a=CryptoJS.enc.Hex.parse(a);this.md.update(a)};this.digest=function(){return this.md.finalize().toString(CryptoJS.enc.Hex)};
+this.digestString=function(a){this.updateString(a);return this.digest()};this.digestHex=function(a){this.updateHex(a);return this.digest()}}if(-1!=":sha256:".indexOf(a)&&"sjcl"==c){try{this.md=new sjcl.hash.sha256}catch(e){throw"setAlgAndProvider hash alg set fail alg="+a+"/"+e;}this.updateString=function(a){this.md.update(a)};this.updateHex=function(a){a=sjcl.codec.hex.toBits(a);this.md.update(a)};this.digest=function(){var a=this.md.finalize();return sjcl.codec.hex.fromBits(a)};this.digestString=
+function(a){this.updateString(a);return this.digest()};this.digestHex=function(a){this.updateHex(a);return this.digest()}}};this.updateString=function(a){throw"updateString(str) not supported for this alg/prov: "+this.algName+"/"+this.provName;};this.updateHex=function(a){throw"updateHex(hex) not supported for this alg/prov: "+this.algName+"/"+this.provName;};this.digest=function(){throw"digest() not supported for this alg/prov: "+this.algName+"/"+this.provName;};this.digestString=function(a){throw"digestString(str) not supported for this alg/prov: "+
+this.algName+"/"+this.provName;};this.digestHex=function(a){throw"digestHex(hex) not supported for this alg/prov: "+this.algName+"/"+this.provName;};void 0!==a&&void 0!==a.alg&&(this.algName=a.alg,void 0===a.prov&&(this.provName=KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]),this.setAlgAndProvider(this.algName,this.provName))};
+KJUR.crypto.Mac=function(a){this.setAlgAndProvider=function(a,c){a=a.toLowerCase();null==a&&(a="hmacsha1");a=a.toLowerCase();if("hmac"!=a.substr(0,4))throw"setAlgAndProvider unsupported HMAC alg: "+a;void 0===c&&(c=KJUR.crypto.Util.DEFAULTPROVIDER[a]);this.algProv=a+"/"+c;var d=a.substr(4);if(-1!=":md5:sha1:sha224:sha256:sha384:sha512:ripemd160:".indexOf(d)&&"cryptojs"==c){try{var e=eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[d]);this.mac=CryptoJS.algo.HMAC.create(e,this.pass)}catch(f){throw"setAlgAndProvider hash alg set fail hashAlg="+
+d+"/"+f;}this.updateString=function(a){this.mac.update(a)};this.updateHex=function(a){a=CryptoJS.enc.Hex.parse(a);this.mac.update(a)};this.doFinal=function(){return this.mac.finalize().toString(CryptoJS.enc.Hex)};this.doFinalString=function(a){this.updateString(a);return this.doFinal()};this.doFinalHex=function(a){this.updateHex(a);return this.doFinal()}}};this.updateString=function(a){throw"updateString(str) not supported for this alg/prov: "+this.algProv;};this.updateHex=function(a){throw"updateHex(hex) not supported for this alg/prov: "+
+this.algProv;};this.doFinal=function(){throw"digest() not supported for this alg/prov: "+this.algProv;};this.doFinalString=function(a){throw"digestString(str) not supported for this alg/prov: "+this.algProv;};this.doFinalHex=function(a){throw"digestHex(hex) not supported for this alg/prov: "+this.algProv;};this.setPassword=function(a){if("string"==typeof a){var c=a;1!=a.length%2&&a.match(/^[0-9A-Fa-f]+$/)||(c=rstrtohex(a))}else{if("object"!=typeof a)throw"KJUR.crypto.Mac unsupported password type: "+
+a;c=null;if(void 0!==a.hex){if(0!=a.hex.length%2||!a.hex.match(/^[0-9A-Fa-f]+$/))throw"Mac: wrong hex password: "+a.hex;c=a.hex}void 0!==a.utf8&&(c=utf8tohex(a.utf8));void 0!==a.rstr&&(c=rstrtohex(a.rstr));void 0!==a.b64&&(c=b64tohex(a.b64));void 0!==a.b64u&&(c=b64utohex(a.b64u));if(null==c)throw"KJUR.crypto.Mac unsupported password type: "+a;}this.pass=CryptoJS.enc.Hex.parse(c)};void 0!==a&&(void 0!==a.pass&&this.setPassword(a.pass),void 0!==a.alg&&(this.algName=a.alg,void 0===a.prov&&(this.provName=
+KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]),this.setAlgAndProvider(this.algName,this.provName)))};
+KJUR.crypto.Signature=function(a){var b=null;this._setAlgNames=function(){this.algName.match(/^(.+)with(.+)$/)&&(this.mdAlgName=RegExp.$1.toLowerCase(),this.pubkeyAlgName=RegExp.$2.toLowerCase())};this._zeroPaddingOfSignature=function(a,b){for(var c="",g=b/4-a.length,h=0;h<g;h++)c+="0";return c+a};this.setAlgAndProvider=function(a,b){this._setAlgNames();if("cryptojs/jsrsa"!=b)throw"provider not supported: "+b;if(-1!=":md5:sha1:sha224:sha256:sha384:sha512:ripemd160:".indexOf(this.mdAlgName)){try{this.md=
+new KJUR.crypto.MessageDigest({alg:this.mdAlgName})}catch(c){throw"setAlgAndProvider hash alg set fail alg="+this.mdAlgName+"/"+c;}this.init=function(a,b){var c=null;try{c=void 0===b?KEYUTIL.getKey(a):KEYUTIL.getKey(a,b)}catch(d){throw"init failed:"+d;}if(!0===c.isPrivate)this.prvKey=c,this.state="SIGN";else if(!0===c.isPublic)this.pubKey=c,this.state="VERIFY";else throw"init failed.:"+c;};this.initSign=function(a){"string"==typeof a.ecprvhex&&"string"==typeof a.eccurvename?(this.ecprvhex=a.ecprvhex,
+this.eccurvename=a.eccurvename):this.prvKey=a;this.state="SIGN"};this.initVerifyByPublicKey=function(a){"string"==typeof a.ecpubhex&&"string"==typeof a.eccurvename?(this.ecpubhex=a.ecpubhex,this.eccurvename=a.eccurvename):a instanceof KJUR.crypto.ECDSA?this.pubKey=a:a instanceof RSAKey&&(this.pubKey=a);this.state="VERIFY"};this.initVerifyByCertificatePEM=function(a){var b=new X509;b.readCertPEM(a);this.pubKey=b.subjectPublicKeyRSA;this.state="VERIFY"};this.updateString=function(a){this.md.updateString(a)};
+this.updateHex=function(a){this.md.updateHex(a)};this.sign=function(){this.sHashHex=this.md.digest();if("undefined"!=typeof this.ecprvhex&&"undefined"!=typeof this.eccurvename)this.hSign=(new KJUR.crypto.ECDSA({curve:this.eccurvename})).signHex(this.sHashHex,this.ecprvhex);else if(this.prvKey instanceof RSAKey&&"rsaandmgf1"==this.pubkeyAlgName)this.hSign=this.prvKey.signWithMessageHashPSS(this.sHashHex,this.mdAlgName,this.pssSaltLen);else if(this.prvKey instanceof RSAKey&&"rsa"==this.pubkeyAlgName)this.hSign=
+this.prvKey.signWithMessageHash(this.sHashHex,this.mdAlgName);else if(this.prvKey instanceof KJUR.crypto.ECDSA)this.hSign=this.prvKey.signWithMessageHash(this.sHashHex);else if(this.prvKey instanceof KJUR.crypto.DSA)this.hSign=this.prvKey.signWithMessageHash(this.sHashHex);else throw"Signature: unsupported public key alg: "+this.pubkeyAlgName;return this.hSign};this.signString=function(a){this.updateString(a);return this.sign()};this.signHex=function(a){this.updateHex(a);return this.sign()};this.verify=
+function(a){this.sHashHex=this.md.digest();if("undefined"!=typeof this.ecpubhex&&"undefined"!=typeof this.eccurvename)return(new KJUR.crypto.ECDSA({curve:this.eccurvename})).verifyHex(this.sHashHex,a,this.ecpubhex);if(this.pubKey instanceof RSAKey&&"rsaandmgf1"==this.pubkeyAlgName)return this.pubKey.verifyWithMessageHashPSS(this.sHashHex,a,this.mdAlgName,this.pssSaltLen);if(this.pubKey instanceof RSAKey&&"rsa"==this.pubkeyAlgName||this.pubKey instanceof KJUR.crypto.ECDSA||this.pubKey instanceof KJUR.crypto.DSA)return this.pubKey.verifyWithMessageHash(this.sHashHex,
+a);throw"Signature: unsupported public key alg: "+this.pubkeyAlgName;}}};this.init=function(a,b){throw"init(key, pass) not supported for this alg:prov="+this.algProvName;};this.initVerifyByPublicKey=function(a){throw"initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov="+this.algProvName;};this.initVerifyByCertificatePEM=function(a){throw"initVerifyByCertificatePEM(certPEM) not supported for this alg:prov="+this.algProvName;};this.initSign=function(a){throw"initSign(prvKey) not supported for this alg:prov="+
+this.algProvName;};this.updateString=function(a){throw"updateString(str) not supported for this alg:prov="+this.algProvName;};this.updateHex=function(a){throw"updateHex(hex) not supported for this alg:prov="+this.algProvName;};this.sign=function(){throw"sign() not supported for this alg:prov="+this.algProvName;};this.signString=function(a){throw"digestString(str) not supported for this alg:prov="+this.algProvName;};this.signHex=function(a){throw"digestHex(hex) not supported for this alg:prov="+this.algProvName;
+};this.verify=function(a){throw"verify(hSigVal) not supported for this alg:prov="+this.algProvName;};this.initParams=a;if(void 0!==a&&(void 0!==a.alg&&(this.algName=a.alg,this.provName=void 0===a.prov?KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]:a.prov,this.algProvName=this.algName+":"+this.provName,this.setAlgAndProvider(this.algName,this.provName),this._setAlgNames()),void 0!==a.psssaltlen&&(this.pssSaltLen=a.psssaltlen),void 0!==a.prvkeypem)){if(void 0!==a.prvkeypas)throw"both prvkeypem and prvkeypas parameters not supported";
+try{b=new RSAKey,b.readPrivateKeyFromPEMString(a.prvkeypem),this.initSign(b)}catch(c){throw"fatal error to load pem private key: "+c;}}};
+KJUR.crypto.OID=new function(){this.oidhex2name={"2a864886f70d010101":"rsaEncryption","2a8648ce3d0201":"ecPublicKey","2a8648ce380401":"dsa","2a8648ce3d030107":"secp256r1","2b8104001f":"secp192k1","2b81040021":"secp224r1","2b8104000a":"secp256k1","2b81040023":"secp521r1","2b81040022":"secp384r1","2a8648ce380403":"SHA1withDSA","608648016503040301":"SHA224withDSA","608648016503040302":"SHA256withDSA"}};exports.KJUR=KJUR;module.exports=exports;
+var ASN1HEX=require("./asn1hex-1.1.js").ASN1HEX,b64tohex=require("./base64.js").b64tohex,RSAKey=require("./rsa2.js").RSAKey;function _rsapem_pemToBase64(a){a=a.replace("-----BEGIN RSA PRIVATE KEY-----","");a=a.replace("-----END RSA PRIVATE KEY-----","");return a=a.replace(/[ \n]+/g,"")}
+function _rsapem_getPosArrayOfChildrenFromHex(a){var b=[],c=ASN1HEX.getStartPosOfV_AtObj(a,0),d=ASN1HEX.getPosOfNextSibling_AtObj(a,c),e=ASN1HEX.getPosOfNextSibling_AtObj(a,d),f=ASN1HEX.getPosOfNextSibling_AtObj(a,e),g=ASN1HEX.getPosOfNextSibling_AtObj(a,f),h=ASN1HEX.getPosOfNextSibling_AtObj(a,g),k=ASN1HEX.getPosOfNextSibling_AtObj(a,h),l=ASN1HEX.getPosOfNextSibling_AtObj(a,k);a=ASN1HEX.getPosOfNextSibling_AtObj(a,l);b.push(c,d,e,f,g,h,k,l,a);return b}
+function _rsapem_getHexValueArrayOfChildrenFromHex(a){var b=_rsapem_getPosArrayOfChildrenFromHex(a),c=ASN1HEX.getHexOfV_AtObj(a,b[0]),d=ASN1HEX.getHexOfV_AtObj(a,b[1]),e=ASN1HEX.getHexOfV_AtObj(a,b[2]),f=ASN1HEX.getHexOfV_AtObj(a,b[3]),g=ASN1HEX.getHexOfV_AtObj(a,b[4]),h=ASN1HEX.getHexOfV_AtObj(a,b[5]),k=ASN1HEX.getHexOfV_AtObj(a,b[6]),l=ASN1HEX.getHexOfV_AtObj(a,b[7]);a=ASN1HEX.getHexOfV_AtObj(a,b[8]);b=[];b.push(c,d,e,f,g,h,k,l,a);return b}
+function _rsapem_readPrivateKeyFromASN1HexString(a){a=_rsapem_getHexValueArrayOfChildrenFromHex(a);this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])}function _rsapem_readPrivateKeyFromPEMString(a){a=_rsapem_pemToBase64(a);a=b64tohex(a);a=_rsapem_getHexValueArrayOfChildrenFromHex(a);this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])}RSAKey.prototype.readPrivateKeyFromPEMString=_rsapem_readPrivateKeyFromPEMString;RSAKey.prototype.readPrivateKeyFromASN1HexString=_rsapem_readPrivateKeyFromASN1HexString;
+exports.RSAKey=RSAKey;module.exports=exports;var intShim=require("jsbn"),BigInteger=intShim.BigInteger?intShim.BigInteger:intShim,RSAKey=require("./rsapem-1.1.js").RSAKey,_RE_HEXDECONLY=RegExp("");_RE_HEXDECONLY.compile("[^0-9a-f]","gi");function _rsasign_getHexPaddedDigestInfoForString(a,b,c){a=KJUR.crypto.Util.hashString(a,c);return KJUR.crypto.Util.getPaddedDigestInfoHex(a,c,b)}function _zeroPaddingOfSignature(a,b){for(var c="",d=b/4-a.length,e=0;e<d;e++)c+="0";return c+a}
+function _rsasign_signString(a,b){var c=KJUR.crypto.Util.hashString(a,b);return this.signWithMessageHash(c,b)}function _rsasign_signWithMessageHash(a,b){var c=KJUR.crypto.Util.getPaddedDigestInfoHex(a,b,this.n.bitLength()),c=parseBigInt(c,16),c=this.doPrivate(c).toString(16);return _zeroPaddingOfSignature(c,this.n.bitLength())}function _rsasign_signStringWithSHA1(a){return _rsasign_signString.call(this,a,"sha1")}
+function _rsasign_signStringWithSHA256(a){return _rsasign_signString.call(this,a,"sha256")}function pss_mgf1_str(a,b,c){for(var d="",e=0;d.length<b;)d+=hextorstr(c(rstrtohex(a+String.fromCharCode.apply(String,[(e&4278190080)>>24,(e&16711680)>>16,(e&65280)>>8,e&255])))),e+=1;return d}function _rsasign_signStringPSS(a,b,c){a=rstrtohex(a);a=KJUR.crypto.Util.hashHex(a,b);void 0===c&&(c=-1);return this.signWithMessageHashPSS(a,b,c)}
+function _rsasign_signWithMessageHashPSS(a,b,c){var d=hextorstr(a);a=d.length;var e=this.n.bitLength()-1,f=Math.ceil(e/8),g=function(a){return KJUR.crypto.Util.hashHex(a,b)};if(-1===c||void 0===c)c=a;else if(-2===c)c=f-a-2;else if(-2>c)throw"invalid salt length";if(f<a+c+2)throw"data too long";var h="";0<c&&(h=Array(c),(new SecureRandom).nextBytes(h),h=String.fromCharCode.apply(String,h));for(var k=hextorstr(g(rstrtohex("\x00\x00\x00\x00\x00\x00\x00\x00"+d+h))),l=[],d=0;d<f-c-a-2;d+=1)l[d]=0;c=String.fromCharCode.apply(String,
+l)+"\u0001"+h;g=pss_mgf1_str(k,c.length,g);h=[];for(d=0;d<c.length;d+=1)h[d]=c.charCodeAt(d)^g.charCodeAt(d);h[0]&=~(65280>>8*f-e&255);for(d=0;d<a;d++)h.push(k.charCodeAt(d));h.push(188);return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(h)).toString(16),this.n.bitLength())}function _rsasign_getDecryptSignatureBI(a,b,c){var d=new RSAKey;d.setPublic(b,c);return d.doPublic(a)}
+function _rsasign_getHexDigestInfoFromSig(a,b,c){return _rsasign_getDecryptSignatureBI(a,b,c).toString(16).replace(/^1f+00/,"")}function _rsasign_getAlgNameAndHashFromHexDisgestInfo(a){for(var b in KJUR.crypto.Util.DIGESTINFOHEAD){var c=KJUR.crypto.Util.DIGESTINFOHEAD[b],d=c.length;if(a.substring(0,d)==c)return[b,a.substring(d)]}return[]}
+function _rsasign_verifySignatureWithArgs(a,b,c,d){b=_rsasign_getHexDigestInfoFromSig(b,c,d);c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(b);if(0==c.length)return!1;b=c[1];a=KJUR.crypto.Util.hashString(a,c[0]);return b==a}function _rsasign_verifyHexSignatureForMessage(a,b){var c=parseBigInt(a,16);return _rsasign_verifySignatureWithArgs(b,c,this.n.toString(16),this.e.toString(16))}
+function _rsasign_verifyString(a,b){b=b.replace(_RE_HEXDECONLY,"");b=b.replace(/[ \n]+/g,"");var c=parseBigInt(b,16);if(c.bitLength()>this.n.bitLength())return 0;var c=this.doPublic(c).toString(16).replace(/^1f+00/,""),d=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);if(0==d.length)return!1;c=d[1];d=KJUR.crypto.Util.hashString(a,d[0]);return c==d}
+function _rsasign_verifyWithMessageHash(a,b){b=b.replace(_RE_HEXDECONLY,"");b=b.replace(/[ \n]+/g,"");var c=parseBigInt(b,16);if(c.bitLength()>this.n.bitLength())return 0;c=this.doPublic(c).toString(16).replace(/^1f+00/,"");c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);return 0==c.length?!1:c[1]==a}function _rsasign_verifyStringPSS(a,b,c,d){a=rstrtohex(a);a=KJUR.crypto.Util.hashHex(a,c);void 0===d&&(d=-1);return this.verifyWithMessageHashPSS(a,b,c,d)}
+function _rsasign_verifyWithMessageHashPSS(a,b,c,d){var e=new BigInteger(b,16);if(e.bitLength()>this.n.bitLength())return!1;b=function(a){return KJUR.crypto.Util.hashHex(a,c)};a=hextorstr(a);var f=a.length,g=this.n.bitLength()-1,h=Math.ceil(g/8);if(-1===d||void 0===d)d=f;else if(-2===d)d=h-f-2;else if(-2>d)throw"invalid salt length";if(h<f+d+2)throw"data too long";for(var k=this.doPublic(e).toByteArray(),e=0;e<k.length;e+=1)k[e]&=255;for(;k.length<h;)k.unshift(0);if(188!==k[h-1])throw"encoded message does not end in 0xbc";
+var k=String.fromCharCode.apply(String,k),l=k.substr(0,h-f-1),k=k.substr(l.length,f),m=65280>>8*h-g&255;if(0!==(l.charCodeAt(0)&m))throw"bits beyond keysize not zero";for(var q=pss_mgf1_str(k,l.length,b),g=[],e=0;e<l.length;e+=1)g[e]=l.charCodeAt(e)^q.charCodeAt(e);g[0]&=~m;f=h-f-d-2;for(e=0;e<f;e+=1)if(0!==g[e])throw"leftmost octets not zero";if(1!==g[f])throw"0x01 marker not found";return k===hextorstr(b(rstrtohex("\x00\x00\x00\x00\x00\x00\x00\x00"+a+String.fromCharCode.apply(String,g.slice(-d)))))}
+RSAKey.prototype.signWithMessageHash=_rsasign_signWithMessageHash;RSAKey.prototype.signString=_rsasign_signString;RSAKey.prototype.signStringWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signStringWithSHA256=_rsasign_signStringWithSHA256;RSAKey.prototype.sign=_rsasign_signString;RSAKey.prototype.signWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signWithSHA256=_rsasign_signStringWithSHA256;RSAKey.prototype.signWithMessageHashPSS=_rsasign_signWithMessageHashPSS;
+RSAKey.prototype.signStringPSS=_rsasign_signStringPSS;RSAKey.prototype.signPSS=_rsasign_signStringPSS;RSAKey.SALT_LEN_HLEN=-1;RSAKey.SALT_LEN_MAX=-2;RSAKey.prototype.verifyWithMessageHash=_rsasign_verifyWithMessageHash;RSAKey.prototype.verifyString=_rsasign_verifyString;RSAKey.prototype.verifyHexSignatureForMessage=_rsasign_verifyHexSignatureForMessage;RSAKey.prototype.verify=_rsasign_verifyString;RSAKey.prototype.verifyHexSignatureForByteArrayMessage=_rsasign_verifyHexSignatureForMessage;
+RSAKey.prototype.verifyWithMessageHashPSS=_rsasign_verifyWithMessageHashPSS;RSAKey.prototype.verifyStringPSS=_rsasign_verifyStringPSS;RSAKey.prototype.verifyPSS=_rsasign_verifyStringPSS;RSAKey.SALT_LEN_RECOVER=-2;exports.RSAKey=RSAKey;module.exports=exports;"undefined"!=typeof KJUR&&KJUR||(KJUR={});"undefined"!=typeof KJUR.crypto&&KJUR.crypto||(KJUR.crypto={});
+KJUR.crypto.ECDSA=function(a){var b=new SecureRandom;this.type="EC";this.getBigRandom=function(a){return(new BigInteger(a.bitLength(),b)).mod(a.subtract(BigInteger.ONE)).add(BigInteger.ONE)};this.setNamedCurve=function(a){this.ecparams=KJUR.crypto.ECParameterDB.getByName(a);this.pubKeyHex=this.prvKeyHex=null;this.curveName=a};this.setPrivateKeyHex=function(a){this.isPrivate=!0;this.prvKeyHex=a};this.setPublicKeyHex=function(a){this.isPublic=!0;this.pubKeyHex=a};this.generateKeyPairHex=function(){var a=
+this.getBigRandom(this.ecparams.n),b=this.ecparams.G.multiply(a),e=b.getX().toBigInteger(),b=b.getY().toBigInteger(),f=this.ecparams.keylen/4,a=("0000000000"+a.toString(16)).slice(-f),e=("0000000000"+e.toString(16)).slice(-f),b=("0000000000"+b.toString(16)).slice(-f),e="04"+e+b;this.setPrivateKeyHex(a);this.setPublicKeyHex(e);return{ecprvhex:a,ecpubhex:e}};this.signWithMessageHash=function(a){return this.signHex(a,this.prvKeyHex)};this.signHex=function(a,b){var e=new BigInteger(b,16),f=this.ecparams.n,
+g=new BigInteger(a,16);do var h=this.getBigRandom(f),k=this.ecparams.G.multiply(h).getX().toBigInteger().mod(f);while(0>=k.compareTo(BigInteger.ZERO));e=h.modInverse(f).multiply(g.add(e.multiply(k))).mod(f);return KJUR.crypto.ECDSA.biRSSigToASN1Sig(k,e)};this.sign=function(a,b){var e=this.ecparams.n,f=BigInteger.fromByteArrayUnsigned(a);do var g=this.getBigRandom(e),h=this.ecparams.G.multiply(g).getX().toBigInteger().mod(e);while(0>=h.compareTo(BigInteger.ZERO));e=g.modInverse(e).multiply(f.add(b.multiply(h))).mod(e);
+return this.serializeSig(h,e)};this.verifyWithMessageHash=function(a,b){return this.verifyHex(a,b,this.pubKeyHex)};this.verifyHex=function(a,b,e){var f;f=KJUR.crypto.ECDSA.parseSigHex(b);b=f.r;f=f.s;e=ECPointFp.decodeFromHex(this.ecparams.curve,e);a=new BigInteger(a,16);return this.verifyRaw(a,b,f,e)};this.verify=function(a,b,e){var f;if(Bitcoin.Util.isArray(b))b=this.parseSig(b),f=b.r,b=b.s;else if("object"===typeof b&&b.r&&b.s)f=b.r,b=b.s;else throw"Invalid value for signature";if(!(e instanceof
+ECPointFp))if(Bitcoin.Util.isArray(e))e=ECPointFp.decodeFrom(this.ecparams.curve,e);else throw"Invalid format for pubkey value, must be byte array or ECPointFp";a=BigInteger.fromByteArrayUnsigned(a);return this.verifyRaw(a,f,b,e)};this.verifyRaw=function(a,b,e,f){var g=this.ecparams.n,h=this.ecparams.G;if(0>b.compareTo(BigInteger.ONE)||0<=b.compareTo(g)||0>e.compareTo(BigInteger.ONE)||0<=e.compareTo(g))return!1;e=e.modInverse(g);a=a.multiply(e).mod(g);e=b.multiply(e).mod(g);return h.multiply(a).add(f.multiply(e)).getX().toBigInteger().mod(g).equals(b)};
+this.serializeSig=function(a,b){var e=a.toByteArraySigned(),f=b.toByteArraySigned(),g=[];g.push(2);g.push(e.length);g=g.concat(e);g.push(2);g.push(f.length);g=g.concat(f);g.unshift(g.length);g.unshift(48);return g};this.parseSig=function(a){var b;if(48!=a[0])throw Error("Signature not a valid DERSequence");b=2;if(2!=a[b])throw Error("First element in signature must be a DERInteger");var e=a.slice(b+2,b+2+a[b+1]);b+=2+a[b+1];if(2!=a[b])throw Error("Second element in signature must be a DERInteger");
+a=a.slice(b+2,b+2+a[b+1]);e=BigInteger.fromByteArrayUnsigned(e);a=BigInteger.fromByteArrayUnsigned(a);return{r:e,s:a}};this.parseSigCompact=function(a){if(65!==a.length)throw"Signature has the wrong length";var b=a[0]-27;if(0>b||7<b)throw"Invalid signature type";var e=this.ecparams.n,f=BigInteger.fromByteArrayUnsigned(a.slice(1,33)).mod(e);a=BigInteger.fromByteArrayUnsigned(a.slice(33,65)).mod(e);return{r:f,s:a,i:b}};void 0!==a&&void 0!==a.curve&&(this.curveName=a.curve);void 0===this.curveName&&
+(this.curveName="secp256r1");this.setNamedCurve(this.curveName);void 0!==a&&(void 0!==a.prv&&this.setPrivateKeyHex(a.prv),void 0!==a.pub&&this.setPublicKeyHex(a.pub))};KJUR.crypto.ECDSA.parseSigHex=function(a){var b=KJUR.crypto.ECDSA.parseSigHexInHexRS(a);a=new BigInteger(b.r,16);b=new BigInteger(b.s,16);return{r:a,s:b}};
+KJUR.crypto.ECDSA.parseSigHexInHexRS=function(a){if("30"!=a.substr(0,2))throw"signature is not a ASN.1 sequence";var b=ASN1HEX.getPosArrayOfChildren_AtObj(a,0);if(2!=b.length)throw"number of signature ASN.1 sequence elements seem wrong";var c=b[0],b=b[1];if("02"!=a.substr(c,2))throw"1st item of sequene of signature is not ASN.1 integer";if("02"!=a.substr(b,2))throw"2nd item of sequene of signature is not ASN.1 integer";c=ASN1HEX.getHexOfV_AtObj(a,c);a=ASN1HEX.getHexOfV_AtObj(a,b);return{r:c,s:a}};
+KJUR.crypto.ECDSA.asn1SigToConcatSig=function(a){var b=KJUR.crypto.ECDSA.parseSigHexInHexRS(a);a=b.r;b=b.s;"00"==a.substr(0,2)&&8==a.length/2*8%128&&(a=a.substr(2));"00"==b.substr(0,2)&&8==b.length/2*8%128&&(b=b.substr(2));if(0!=a.length/2*8%128)throw"unknown ECDSA sig r length error";if(0!=b.length/2*8%128)throw"unknown ECDSA sig s length error";return a+b};
+KJUR.crypto.ECDSA.concatSigToASN1Sig=function(a){if(0!=a.length/2*8%128)throw"unknown ECDSA concatinated r-s sig  length error";var b=a.substr(0,a.length/2);a=a.substr(a.length/2);return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(b,a)};KJUR.crypto.ECDSA.hexRSSigToASN1Sig=function(a,b){var c=new BigInteger(a,16),d=new BigInteger(b,16);return KJUR.crypto.ECDSA.biRSSigToASN1Sig(c,d)};
+KJUR.crypto.ECDSA.biRSSigToASN1Sig=function(a,b){var c=new KJUR.asn1.DERInteger({bigint:a}),d=new KJUR.asn1.DERInteger({bigint:b});return(new KJUR.asn1.DERSequence({array:[c,d]})).getEncodedHex()};intShim=require("jsbn");
+ASN1HEX=new function(){this.getByteLengthOfL_AtObj=function(a,b){if("8"!=a.substring(b+2,b+3))return 1;var c=parseInt(a.substring(b+3,b+4));return 0==c?-1:0<c&&10>c?c+1:-2};this.getHexOfL_AtObj=function(a,b){var c=this.getByteLengthOfL_AtObj(a,b);return 1>c?"":a.substring(b+2,b+2+2*c)};this.getIntOfL_AtObj=function(a,b){var c=this.getHexOfL_AtObj(a,b);return""==c?-1:(8>parseInt(c.substring(0,1))?new BigInteger(c,16):new BigInteger(c.substring(2),16)).intValue()};this.getStartPosOfV_AtObj=function(a,
+b){var c=this.getByteLengthOfL_AtObj(a,b);return 0>c?c:b+2*(c+1)};this.getHexOfV_AtObj=function(a,b){var c=this.getStartPosOfV_AtObj(a,b),d=this.getIntOfL_AtObj(a,b);return a.substring(c,c+2*d)};this.getHexOfTLV_AtObj=function(a,b){var c=a.substr(b,2),d=this.getHexOfL_AtObj(a,b),e=this.getHexOfV_AtObj(a,b);return c+d+e};this.getPosOfNextSibling_AtObj=function(a,b){var c=this.getStartPosOfV_AtObj(a,b),d=this.getIntOfL_AtObj(a,b);return c+2*d};this.getPosArrayOfChildren_AtObj=function(a,b){var c=[],
+d=this.getStartPosOfV_AtObj(a,b);c.push(d);for(var e=this.getIntOfL_AtObj(a,b),f=d,g=0;;){f=this.getPosOfNextSibling_AtObj(a,f);if(null==f||f-d>=2*e)break;if(200<=g)break;c.push(f);g++}return c};this.getNthChildIndex_AtObj=function(a,b,c){return this.getPosArrayOfChildren_AtObj(a,b)[c]};this.getDecendantIndexByNthList=function(a,b,c){if(0==c.length)return b;var d=c.shift();b=this.getPosArrayOfChildren_AtObj(a,b);return this.getDecendantIndexByNthList(a,b[d],c)};this.getDecendantHexTLVByNthList=function(a,
+b,c){b=this.getDecendantIndexByNthList(a,b,c);return this.getHexOfTLV_AtObj(a,b)};this.getDecendantHexVByNthList=function(a,b,c){b=this.getDecendantIndexByNthList(a,b,c);return this.getHexOfV_AtObj(a,b)}};ASN1HEX.getVbyList=function(a,b,c,d){b=this.getDecendantIndexByNthList(a,b,c);if(void 0===b)throw"can't find nthList object";if(void 0!==d&&a.substr(b,2)!=d)throw"checking tag doesn't match: "+a.substr(b,2)+"!="+d;return this.getHexOfV_AtObj(a,b)};
+ASN1HEX.hextooidstr=function(a){var b=function(a,b){return a.length>=b?a:Array(b-a.length+1).join("0")+a},c=[],d=a.substr(0,2),d=parseInt(d,16);c[0]=new String(Math.floor(d/40));c[1]=new String(d%40);var e=a.substr(2);a=[];for(d=0;d<e.length/2;d++)a.push(parseInt(e.substr(2*d,2),16));for(var e=[],f="",d=0;d<a.length;d++)a[d]&128?f+=b((a[d]&127).toString(2),7):(f+=b((a[d]&127).toString(2),7),e.push(new String(parseInt(f,2))),f="");b=c.join(".");0<e.length&&(b=b+"."+e.join("."));return b};
+ASN1HEX.dump=function(a,b,c,d){var e=function(a,b){return a.length<=2*b?a:a.substr(0,b)+"..(total "+a.length/2+"bytes).."+a.substr(a.length-b,b)};void 0===b&&(b={ommit_long_octet:32});void 0===c&&(c=0);void 0===d&&(d="");var f=b.ommit_long_octet;if("01"==a.substr(c,2))return a=ASN1HEX.getHexOfV_AtObj(a,c),"00"==a?d+"BOOLEAN FALSE\n":d+"BOOLEAN TRUE\n";if("02"==a.substr(c,2))return a=ASN1HEX.getHexOfV_AtObj(a,c),d+"INTEGER "+e(a,f)+"\n";if("03"==a.substr(c,2))return a=ASN1HEX.getHexOfV_AtObj(a,c),
+d+"BITSTRING "+e(a,f)+"\n";if("04"==a.substr(c,2))return a=ASN1HEX.getHexOfV_AtObj(a,c),ASN1HEX.isASN1HEX(a)?e=d+"OCTETSTRING, encapsulates\n"+ASN1HEX.dump(a,b,0,d+"  "):d+"OCTETSTRING "+e(a,f)+"\n";if("05"==a.substr(c,2))return d+"NULL\n";if("06"==a.substr(c,2)){a=ASN1HEX.getHexOfV_AtObj(a,c);var g=KJUR.asn1.ASN1Util.oidHexToInt(a),f=KJUR.asn1.x509.OID.oid2name(g);a=g.replace(/\./g," ");return""!=f?d+"ObjectIdentifier "+f+" ("+a+")\n":d+"ObjectIdentifier ("+a+")\n"}if("0c"==a.substr(c,2))return d+
+"UTF8String '"+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"'\n";if("13"==a.substr(c,2))return d+"PrintableString '"+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"'\n";if("14"==a.substr(c,2))return d+"TeletexString '"+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"'\n";if("16"==a.substr(c,2))return d+"IA5String '"+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"'\n";if("17"==a.substr(c,2))return d+"UTCTime "+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"\n";if("18"==a.substr(c,2))return d+"GeneralizedTime "+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,
+c))+"\n";if("30"==a.substr(c,2)){if("3000"==a.substr(c,4))return d+"SEQUENCE {}\n";e=d+"SEQUENCE\n";c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c);f=b;2!=c.length&&3!=c.length||"06"!=a.substr(c[0],2)||"04"!=a.substr(c[c.length-1],2)||(f=ASN1HEX.getHexOfV_AtObj(a,c[0]),g=KJUR.asn1.ASN1Util.oidHexToInt(f),f=KJUR.asn1.x509.OID.oid2name(g),b=JSON.parse(JSON.stringify(b)),b.x509ExtName=f,f=b);for(g=0;g<c.length;g++)e+=ASN1HEX.dump(a,f,c[g],d+"  ");return e}if("31"==a.substr(c,2)){e=d+"SET\n";c=ASN1HEX.getPosArrayOfChildren_AtObj(a,
+c);for(g=0;g<c.length;g++)e+=ASN1HEX.dump(a,b,c[g],d+"  ");return e}f=parseInt(a.substr(c,2),16);if(0!=(f&128)){e=f&31;if(0!=(f&32))for(e=d+"["+e+"]\n",c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c),g=0;g<c.length;g++)e+=ASN1HEX.dump(a,b,c[g],d+"  ");else a=ASN1HEX.getHexOfV_AtObj(a,c),"68747470"==a.substr(0,8)&&(a=hextoutf8(a)),"subjectAltName"===b.x509ExtName&&2==e&&(a=hextoutf8(a)),e=d+"["+e+"] "+a+"\n";return e}return d+"UNKNOWN("+a.substr(c,2)+") "+ASN1HEX.getHexOfV_AtObj(a,c)+"\n"};
+ASN1HEX.isASN1HEX=function(a){if(1==a.length%2)return!1;var b=ASN1HEX.getIntOfL_AtObj(a,0),c=a.substr(0,2),d=ASN1HEX.getHexOfL_AtObj(a,0);return a.length-c.length-d.length==2*b?!0:!1};exports.ASN1HEX=ASN1HEX;module.exports=exports;b64tohex=require("./base64.js").b64tohex;RSAKey=require("./rsa.js").RSAKey;ASN1HEX=require("./asn1hex-1.1.js").ASN1HEX;
+function X509(){this.hex=this.subjectPublicKeyRSA_hE=this.subjectPublicKeyRSA_hN=this.subjectPublicKeyRSA=null;this.getSerialNumberHex=function(){return ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,1])};this.getIssuerHex=function(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3])};this.getIssuerString=function(){return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3]))};this.getSubjectHex=function(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5])};this.getSubjectString=
+function(){return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5]))};this.getNotBefore=function(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,0]),a=a.replace(/(..)/g,"%$1");return a=decodeURIComponent(a)};this.getNotAfter=function(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,1]),a=a.replace(/(..)/g,"%$1");return a=decodeURIComponent(a)};this.readCertPEM=function(a){a=X509.pemToHex(a);var b=X509.getPublicKeyHexArrayFromCertHex(a),c=new RSAKey;c.setPublic(b[0],
+b[1]);this.subjectPublicKeyRSA=c;this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a};this.readCertPEMWithoutRSAInit=function(a){a=X509.pemToHex(a);var b=X509.getPublicKeyHexArrayFromCertHex(a);this.subjectPublicKeyRSA.setPublic(b[0],b[1]);this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a}}X509.pemToBase64=function(a){a=a.replace("-----BEGIN CERTIFICATE-----","");a=a.replace("-----END CERTIFICATE-----","");return a=a.replace(/[ \n]+/g,"")};
+X509.pemToHex=function(a){a=X509.pemToBase64(a);return b64tohex(a)};X509.getSubjectPublicKeyPosFromCertHex=function(a){var b=X509.getSubjectPublicKeyInfoPosFromCertHex(a);if(-1==b)return-1;b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);if(2!=b.length)return-1;b=b[1];if("03"!=a.substring(b,b+2))return-1;b=ASN1HEX.getStartPosOfV_AtObj(a,b);return"00"!=a.substring(b,b+2)?-1:b+2};
+X509.getSubjectPublicKeyInfoPosFromCertHex=function(a){var b=ASN1HEX.getStartPosOfV_AtObj(a,0),b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);return 1>b.length?-1:"a003020102"==a.substring(b[0],b[0]+10)?6>b.length?-1:b[6]:5>b.length?-1:b[5]};X509.getPublicKeyHexArrayFromCertHex=function(a){var b=X509.getSubjectPublicKeyPosFromCertHex(a),c=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);if(2!=c.length)return[];b=ASN1HEX.getHexOfV_AtObj(a,c[0]);a=ASN1HEX.getHexOfV_AtObj(a,c[1]);return null!=b&&null!=a?[b,a]:[]};
+X509.getHexTbsCertificateFromCert=function(a){return ASN1HEX.getStartPosOfV_AtObj(a,0)};X509.getPublicKeyHexArrayFromCertPEM=function(a){a=X509.pemToHex(a);return X509.getPublicKeyHexArrayFromCertHex(a)};X509.hex2dn=function(a){for(var b="",c=ASN1HEX.getPosArrayOfChildren_AtObj(a,0),d=0;d<c.length;d++)var e=ASN1HEX.getHexOfTLV_AtObj(a,c[d]),b=b+"/"+X509.hex2rdn(e);return b};
+X509.hex2rdn=function(a){var b=ASN1HEX.getDecendantHexTLVByNthList(a,0,[0,0]),c=ASN1HEX.getDecendantHexVByNthList(a,0,[0,1]);a="";try{a=X509.DN_ATTRHEX[b]}catch(d){a=b}c=c.replace(/(..)/g,"%$1");b=decodeURIComponent(c);return a+"="+b};X509.DN_ATTRHEX={"0603550406":"C","060355040a":"O","060355040b":"OU","0603550403":"CN","0603550405":"SN","0603550408":"ST","0603550407":"L"};
+X509.getPublicKeyFromCertPEM=function(a){var b=X509.getPublicKeyInfoPropOfCertPEM(a);if("2a864886f70d010101"==b.algoid){var c=KEYUTIL.parsePublicRawRSAKeyHex(b.keyhex);a=new RSAKey;a.setPublic(c.n,c.e);return a}if("2a8648ce3d0201"==b.algoid)return a=new KJUR.crypto.ECDSA({curve:KJUR.crypto.OID.oidhex2name[b.algparam],info:b.keyhex}),a.setPublicKeyHex(b.keyhex),a;if("2a8648ce380401"==b.algoid){var c=ASN1HEX.getVbyList(b.algparam,0,[0],"02"),d=ASN1HEX.getVbyList(b.algparam,0,[1],"02"),e=ASN1HEX.getVbyList(b.algparam,
+0,[2],"02"),b=ASN1HEX.getHexOfV_AtObj(b.keyhex,0),b=b.substr(2);a=new KJUR.crypto.DSA;a.setPublic(new BigInteger(c,16),new BigInteger(d,16),new BigInteger(e,16),new BigInteger(b,16));return a}throw"unsupported key";};
+X509.getPublicKeyInfoPropOfCertPEM=function(a){var b={algparam:null};a=X509.pemToHex(a);var c=ASN1HEX.getPosArrayOfChildren_AtObj(a,0);if(3!=c.length)throw"malformed X.509 certificate PEM (code:001)";if("30"!=a.substr(c[0],2))throw"malformed X.509 certificate PEM (code:002)";c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c[0]);if(7>c.length)throw"malformed X.509 certificate PEM (code:003)";c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c[6]);if(2!=c.length)throw"malformed X.509 certificate PEM (code:004)";var d=
+ASN1HEX.getPosArrayOfChildren_AtObj(a,c[0]);if(2!=d.length)throw"malformed X.509 certificate PEM (code:005)";b.algoid=ASN1HEX.getHexOfV_AtObj(a,d[0]);"06"==a.substr(d[1],2)?b.algparam=ASN1HEX.getHexOfV_AtObj(a,d[1]):"30"==a.substr(d[1],2)&&(b.algparam=ASN1HEX.getHexOfTLV_AtObj(a,d[1]));if("03"!=a.substr(c[1],2))throw"malformed X.509 certificate PEM (code:006)";a=ASN1HEX.getHexOfV_AtObj(a,c[1]);b.keyhex=a.substr(2);return b};
+X509.getPublicKeyInfoPosOfCertHEX=function(a){var b=ASN1HEX.getPosArrayOfChildren_AtObj(a,0);if(3!=b.length)throw"malformed X.509 certificate PEM (code:001)";if("30"!=a.substr(b[0],2))throw"malformed X.509 certificate PEM (code:002)";a=ASN1HEX.getPosArrayOfChildren_AtObj(a,b[0]);if(7>a.length)throw"malformed X.509 certificate PEM (code:003)";return a[6]};
+X509.getV3ExtInfoListOfCertHex=function(a){var b=ASN1HEX.getPosArrayOfChildren_AtObj(a,0);if(3!=b.length)throw"malformed X.509 certificate PEM (code:001)";if("30"!=a.substr(b[0],2))throw"malformed X.509 certificate PEM (code:002)";b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b[0]);if(8>b.length)throw"malformed X.509 certificate PEM (code:003)";if("a3"!=a.substr(b[7],2))throw"malformed X.509 certificate PEM (code:004)";b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b[7]);if(1!=b.length)throw"malformed X.509 certificate PEM (code:005)";
+if("30"!=a.substr(b[0],2))throw"malformed X.509 certificate PEM (code:006)";for(var b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b[0]),c=b.length,d=Array(c),e=0;e<c;e++)d[e]=X509.getV3ExtItemInfo_AtObj(a,b[e]);return d};
+X509.getV3ExtItemInfo_AtObj=function(a,b){var c={};c.posTLV=b;var d=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);if(2!=d.length&&3!=d.length)throw"malformed X.509v3 Ext (code:001)";if("06"!=a.substr(d[0],2))throw"malformed X.509v3 Ext (code:002)";var e=ASN1HEX.getHexOfV_AtObj(a,d[0]);c.oid=ASN1HEX.hextooidstr(e);c.critical=!1;3==d.length&&(c.critical=!0);d=d[d.length-1];if("04"!=a.substr(d,2))throw"malformed X.509v3 Ext (code:003)";c.posV=ASN1HEX.getStartPosOfV_AtObj(a,d);return c};
+X509.getHexOfTLV_V3ExtValue=function(a,b){var c=X509.getPosOfTLV_V3ExtValue(a,b);return-1==c?"":ASN1HEX.getHexOfTLV_AtObj(a,c)};X509.getHexOfV_V3ExtValue=function(a,b){var c=X509.getPosOfTLV_V3ExtValue(a,b);return-1==c?"":ASN1HEX.getHexOfV_AtObj(a,c)};X509.getPosOfTLV_V3ExtValue=function(a,b){var c=b;b.match(/^[0-9.]+$/)||(c=KJUR.asn1.x509.OID.name2oid(b));if(""==c)return-1;for(var d=X509.getV3ExtInfoListOfCertHex(a),e=0;e<d.length;e++){var f=d[e];if(f.oid==c)return f.posV}return-1};
+X509.KEYUSAGE_NAME="digitalSignature nonRepudiation keyEncipherment dataEncipherment keyAgreement keyCertSign cRLSign encipherOnly decipherOnly".split(" ");X509.getExtKeyUsageBin=function(a){var b=X509.getHexOfV_V3ExtValue(a,"keyUsage");if(""==b)return"";if(0!=b.length%2||2>=b.length)throw"malformed key usage value";a=parseInt(b.substr(0,2));b=parseInt(b.substr(2),16).toString(2);return b.substr(0,b.length-a)};
+X509.getExtKeyUsageString=function(a){a=X509.getExtKeyUsageBin(a);for(var b=[],c=0;c<a.length;c++)"1"==a.substr(c,1)&&b.push(X509.KEYUSAGE_NAME[c]);return b.join(",")};
+X509.getExtAIAInfo=function(a){var b={ocsp:[],caissuer:[]},c=X509.getPosOfTLV_V3ExtValue(a,"authorityInfoAccess");if(-1==c)return null;if("30"!=a.substr(c,2))throw"malformed AIA Extn Value";for(var c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c),d=0;d<c.length;d++){var e=ASN1HEX.getPosArrayOfChildren_AtObj(a,c[d]);if(2!=e.length)throw"malformed AccessDescription of AIA Extn";var f=e[0],e=e[1];"2b06010505073001"==ASN1HEX.getHexOfV_AtObj(a,f)&&"86"==a.substr(e,2)&&b.ocsp.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(a,
+e)));"2b06010505073002"==ASN1HEX.getHexOfV_AtObj(a,f)&&"86"==a.substr(e,2)&&b.caissuer.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(a,e)))}return b};exports.X509=X509;module.exports=exports;var dbits,canary=0xdeadbeefcafe,j_lm=15715070==(canary&16777215),BigInteger=function(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))};function nbi(){return new BigInteger(null)}
+function am1(a,b,c,d,e,f){for(;0<=--f;){var g=b*this[a++]+c[d]+e;e=Math.floor(g/67108864);c[d++]=g&67108863}return e}function am2(a,b,c,d,e,f){var g=b&32767;for(b>>=15;0<=--f;){var h=this[a]&32767,k=this[a++]>>15,l=b*h+k*g,h=g*h+((l&32767)<<15)+c[d]+(e&1073741823);e=(h>>>30)+(l>>>15)+b*k+(e>>>30);c[d++]=h&1073741823}return e}
+function am3(a,b,c,d,e,f){var g=b&16383;for(b>>=14;0<=--f;){var h=this[a]&16383,k=this[a++]>>14,l=b*h+k*g,h=g*h+((l&16383)<<14)+c[d]+e;e=(h>>28)+(l>>14)+b*k;c[d++]=h&268435455}return e}j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28);BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;
 var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz",BI_RC=[],rr,vv;rr=48;for(vv=0;9>=vv;++vv)BI_RC[rr++]=vv;rr=97;for(vv=10;36>vv;++vv)BI_RC[rr++]=vv;rr=65;for(vv=10;36>vv;++vv)BI_RC[rr++]=vv;function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return null==c?-1:c}
-function bnpCopyTo(a){for(var b=this.t-1;0<=b;--b)a[b]=this[b];a.t=this.t;a.s=this.s}function bnpFromInt(a){this.t=1;this.s=0>a?-1:0;0<a?this[0]=a:-1>a?this[0]=a+DV:this.t=0}function nbv(a){var b=nbi();b.fromInt(a);return b}
+function bnpCopyTo(a){for(var b=this.t-1;0<=b;--b)a[b]=this[b];a.t=this.t;a.s=this.s}function bnpFromInt(a){this.t=1;this.s=0>a?-1:0;0<a?this[0]=a:-1>a?this[0]=a+this.DV:this.t=0}function nbv(a){var b=nbi();b.fromInt(a);return b}
 function bnpFromString(a,b){var c;if(16==b)c=4;else if(8==b)c=3;else if(256==b)c=8;else if(2==b)c=1;else if(32==b)c=5;else if(4==b)c=2;else{this.fromRadix(a,b);return}this.s=this.t=0;for(var d=a.length,e=!1,f=0;0<=--d;){var g=8==c?a[d]&255:intAt(a,d);0>g?"-"==a.charAt(d)&&(e=!0):(e=!1,0==f?this[this.t++]=g:f+c>this.DB?(this[this.t-1]|=(g&(1<<this.DB-f)-1)<<f,this[this.t++]=g>>this.DB-f):this[this.t-1]|=g<<f,f+=c,f>=this.DB&&(f-=this.DB))}8==c&&0!=(a[0]&128)&&(this.s=-1,0<f&&(this[this.t-1]|=(1<<this.DB-
 f)-1<<f));this.clamp();e&&BigInteger.ZERO.subTo(this,this)}function bnpClamp(){for(var a=this.s&this.DM;0<this.t&&this[this.t-1]==a;)--this.t}
-function bnToString(a){if(0>this.s)return"-"+this.negate().toString(a);if(16==a)a=4;else if(8==a)a=3;else if(2==a)a=1;else if(32==a)a=5;else if(4==a)a=2;else return this.toRadix(a);var b=(1<<a)-1,c,d=!1,e="",f=this.t,g=this.DB-f*this.DB%a;if(0<f--){if(g<this.DB&&0<(c=this[f]>>g))d=!0,e=int2char(c);for(;0<=f;)g<a?(c=(this[f]&(1<<g)-1)<<a-g,c|=this[--f]>>(g+=this.DB-a)):(c=this[f]>>(g-=a)&b,0>=g&&(g+=this.DB,--f)),0<c&&(d=!0),d&&(e+=int2char(c))}return d?e:"0"}
-function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return 0>this.s?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t,b=c-a.t;if(0!=b)return b;for(;0<=--c;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b=1,c;if(0!=(c=a>>>16))a=c,b+=16;if(0!=(c=a>>8))a=c,b+=8;if(0!=(c=a>>4))a=c,b+=4;if(0!=(c=a>>2))a=c,b+=2;0!=a>>1&&(b+=1);return b}
+function bnToString(a){if(0>this.s)return"-"+this.negate().toString(a);if(16==a)a=4;else if(8==a)a=3;else if(2==a)a=1;else if(32==a)a=5;else if(4==a)a=2;else return this.toRadix(a);var b=(1<<a)-1,c,d=!1,e="",f=this.t,g=this.DB-f*this.DB%a;if(0<f--)for(g<this.DB&&0<(c=this[f]>>g)&&(d=!0,e=int2char(c));0<=f;)g<a?(c=(this[f]&(1<<g)-1)<<a-g,c|=this[--f]>>(g+=this.DB-a)):(c=this[f]>>(g-=a)&b,0>=g&&(g+=this.DB,--f)),0<c&&(d=!0),d&&(e+=int2char(c));return d?e:"0"}
+function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return 0>this.s?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t,b=c-a.t;if(0!=b)return 0>this.s?-b:b;for(;0<=--c;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b=1,c;0!=(c=a>>>16)&&(a=c,b+=16);0!=(c=a>>8)&&(a=c,b+=8);0!=(c=a>>4)&&(a=c,b+=4);0!=(c=a>>2)&&(a=c,b+=2);0!=a>>1&&(b+=1);return b}
 function bnBitLength(){return 0>=this.t?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;0<=c;--c)b[c+a]=this[c];for(c=a-1;0<=c;--c)b[c]=0;b.t=this.t+a;b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c<this.t;++c)b[c-a]=this[c];b.t=Math.max(this.t-a,0);b.s=this.s}
 function bnpLShiftTo(a,b){var c=a%this.DB,d=this.DB-c,e=(1<<d)-1,f=Math.floor(a/this.DB),g=this.s<<c&this.DM,h;for(h=this.t-1;0<=h;--h)b[h+f+1]=this[h]>>d|g,g=(this[h]&e)<<c;for(h=f-1;0<=h;--h)b[h]=0;b[f]=g;b.t=this.t+f+1;b.s=this.s;b.clamp()}
 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;var 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),l=this.FV/j,j=(1<<this.F1)/j,n=1<<this.F2,m=c.t,p=m-d,k=null==b?nbi():b;f.dlShiftTo(p,k);0<=c.compareTo(k)&&(c[c.t++]=1,c.subTo(k,c));BigInteger.ONE.dlShiftTo(d,
-k);for(k.subTo(f,f);f.t<d;)f[f.t++]=0;for(;0<=--p;){var q=c[--m]==e?this.DM:Math.floor(c[m]*l+(c[m-1]+n)*j);if((c[m]+=f.am(0,q,c,p,0,d))<q){f.dlShiftTo(p,k);for(c.subTo(k,c);c[m]<--q;)c.subTo(k,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 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);(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;var 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 k=e*(1<<this.F1)+(1<d?f[d-2]>>this.F2:0),l=this.FV/k,k=(1<<this.F1)/k,m=1<<this.F2,q=c.t,p=q-d,s=null==b?nbi():b;f.dlShiftTo(p,s);0<=c.compareTo(s)&&(c[c.t++]=1,c.subTo(s,c));BigInteger.ONE.dlShiftTo(d,
+s);for(s.subTo(f,f);f.t<d;)f[f.t++]=0;for(;0<=--p;){var w=c[--q]==e?this.DM:Math.floor(c[q]*l+(c[q-1]+m)*k);if((c[q]+=f.am(0,w,c,p,0,d))<w)for(f.dlShiftTo(p,s),c.subTo(s,c);c[q]<--w;)c.subTo(s,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}
@@ -228,56 +169,952 @@
 BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;
 BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnClone(){var a=nbi();this.copyTo(a);return a}function bnIntValue(){if(0>this.s){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnByteValue(){return 0==this.t?this.s:this[0]<<24>>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}
 function bnSigNum(){return 0>this.s?-1:0>=this.t||1==this.t&&0>=this[0]?0:1}function bnpToRadix(a){null==a&&(a=10);if(0==this.signum()||2>a||36<a)return"0";var b=this.chunkSize(a),b=Math.pow(a,b),c=nbv(b),d=nbi(),e=nbi(),f="";for(this.divRemTo(c,d,e);0<d.signum();)f=(b+e.intValue()).toString(a).substr(1)+f,d.divRemTo(c,d,e);return e.intValue().toString(a)+f}
-function bnpFromRadix(a,b){this.fromInt(0);null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,g=0,h=0;h<a.length;++h){var j=intAt(a,h);0>j?"-"==a.charAt(h)&&0==this.signum()&&(e=!0):(g=b*g+j,++f>=c&&(this.dMultiply(d),this.dAddOffset(g,0),g=f=0))}0<f&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(g,0));e&&BigInteger.ZERO.subTo(this,this)}
-function bnpFromNumber(a,b,c){if("number"==typeof b)if(2>a)this.fromInt(1);else{this.fromNumber(a,c);this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);for(this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this)}else{c=[];var d=a&7;c.length=(a>>3)+1;b.nextBytes(c);c[0]=0<d?c[0]&(1<<d)-1:0;this.fromString(c,256)}}
-function bnToByteArray(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,d,e=0;if(0<a--){if(c<this.DB&&(d=this[a]>>c)!=(this.s&this.DM)>>c)b[e++]=d|this.s<<this.DB-c;for(;0<=a;)if(8>c?(d=(this[a]&(1<<c)-1)<<8-c,d|=this[--a]>>(c+=this.DB-8)):(d=this[a]>>(c-=8)&255,0>=c&&(c+=this.DB,--a)),0!=(d&128)&&(d|=-256),0==e&&(this.s&128)!=(d&128)&&++e,0<e||d!=this.s)b[e++]=d}return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return 0>this.compareTo(a)?this:a}
+function bnpFromRadix(a,b){this.fromInt(0);null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,g=0,h=0;h<a.length;++h){var k=intAt(a,h);0>k?"-"==a.charAt(h)&&0==this.signum()&&(e=!0):(g=b*g+k,++f>=c&&(this.dMultiply(d),this.dAddOffset(g,0),g=f=0))}0<f&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(g,0));e&&BigInteger.ZERO.subTo(this,this)}
+function bnpFromNumber(a,b,c){if("number"==typeof b)if(2>a)this.fromInt(1);else for(this.fromNumber(a,c),this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this);else{c=[];var d=a&7;c.length=(a>>3)+1;b.nextBytes(c);c[0]=0<d?c[0]&(1<<d)-1:0;this.fromString(c,256)}}
+function bnToByteArray(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,d,e=0;if(0<a--)for(c<this.DB&&(d=this[a]>>c)!=(this.s&this.DM)>>c&&(b[e++]=d|this.s<<this.DB-c);0<=a;)if(8>c?(d=(this[a]&(1<<c)-1)<<8-c,d|=this[--a]>>(c+=this.DB-8)):(d=this[a]>>(c-=8)&255,0>=c&&(c+=this.DB,--a)),0!=(d&128)&&(d|=-256),0==e&&(this.s&128)!=(d&128)&&++e,0<e||d!=this.s)b[e++]=d;return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return 0>this.compareTo(a)?this:a}
 function bnMax(a){return 0<this.compareTo(a)?this:a}function bnpBitwiseTo(a,b,c){var d,e,f=Math.min(a.t,this.t);for(d=0;d<f;++d)c[d]=b(this[d],a[d]);if(a.t<this.t){e=a.s&this.DM;for(d=f;d<this.t;++d)c[d]=b(this[d],e);c.t=this.t}else{e=this.s&this.DM;for(d=f;d<a.t;++d)c[d]=b(e,a[d]);c.t=a.t}c.s=b(this.s,a.s);c.clamp()}function op_and(a,b){return a&b}function bnAnd(a){var b=nbi();this.bitwiseTo(a,op_and,b);return b}function op_or(a,b){return a|b}
 function bnOr(a){var b=nbi();this.bitwiseTo(a,op_or,b);return b}function op_xor(a,b){return a^b}function bnXor(a){var b=nbi();this.bitwiseTo(a,op_xor,b);return b}function op_andnot(a,b){return a&~b}function bnAndNot(a){var b=nbi();this.bitwiseTo(a,op_andnot,b);return b}function bnNot(){for(var a=nbi(),b=0;b<this.t;++b)a[b]=this.DM&~this[b];a.t=this.t;a.s=~this.s;return a}function bnShiftLeft(a){var b=nbi();0>a?this.rShiftTo(-a,b):this.lShiftTo(a,b);return b}
 function bnShiftRight(a){var b=nbi();0>a?this.lShiftTo(-a,b):this.rShiftTo(a,b);return b}function lbit(a){if(0==a)return-1;var b=0;0==(a&65535)&&(a>>=16,b+=16);0==(a&255)&&(a>>=8,b+=8);0==(a&15)&&(a>>=4,b+=4);0==(a&3)&&(a>>=2,b+=2);0==(a&1)&&++b;return b}function bnGetLowestSetBit(){for(var a=0;a<this.t;++a)if(0!=this[a])return a*this.DB+lbit(this[a]);return 0>this.s?this.t*this.DB:-1}function cbit(a){for(var b=0;0!=a;)a&=a-1,++b;return b}
 function bnBitCount(){for(var a=0,b=this.s&this.DM,c=0;c<this.t;++c)a+=cbit(this[c]^b);return a}function bnTestBit(a){var b=Math.floor(a/this.DB);return b>=this.t?0!=this.s:0!=(this[b]&1<<a%this.DB)}function bnpChangeBit(a,b){var c=BigInteger.ONE.shiftLeft(a);this.bitwiseTo(c,b,c);return c}function bnSetBit(a){return this.changeBit(a,op_or)}function bnClearBit(a){return this.changeBit(a,op_andnot)}function bnFlipBit(a){return this.changeBit(a,op_xor)}
 function bnpAddTo(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;0<d?b[c++]=d:-1>d&&(b[c++]=this.DV+d);b.t=c;b.clamp()}function bnAdd(a){var b=nbi();this.addTo(a,b);return b}function bnSubtract(a){var b=nbi();this.subTo(a,b);return b}
-function bnMultiply(a){var b=nbi();this.multiplyTo(a,b);return b}function bnDivide(a){var b=nbi();this.divRemTo(a,b,null);return b}function bnRemainder(a){var b=nbi();this.divRemTo(a,null,b);return b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();this.divRemTo(a,b,c);return[b,c]}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()}
+function bnMultiply(a){var b=nbi();this.multiplyTo(a,b);return b}function bnSquare(){var a=nbi();this.squareTo(a);return a}function bnDivide(a){var b=nbi();this.divRemTo(a,b,null);return b}function bnRemainder(a){var b=nbi();this.divRemTo(a,null,b);return b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();this.divRemTo(a,b,c);return[b,c]}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()}
 function bnpDAddOffset(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}NullExp.prototype.convert=nNop;NullExp.prototype.revert=nNop;NullExp.prototype.mulTo=nMulTo;NullExp.prototype.sqrTo=nSqrTo;function bnPow(a){return this.exp(a,new NullExp)}
 function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);c.s=0;for(c.t=d;0<d;)c[--d]=0;var e;for(e=c.t-this.t;d<e;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);d<e;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function bnpMultiplyUpperTo(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;0<=--d;)c[d]=0;for(d=Math.max(b-this.t,0);d<a.t;++d)c[this.t+d-b]=this.am(b-d,a[d],c,0,0,this.t+d-b);c.clamp();c.drShiftTo(1,c)}
 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,l=(1<<d)-1;g[1]=f.convert(this);if(1<d){c=nbi();for(f.sqrTo(g[1],c);h<=l;)g[h]=nbi(),f.mulTo(c,g[h-2],g[h]),h+=2}for(var n=a.t-1,m,p=!0,k=nbi(),c=nbits(a[n])-1;0<=n;){c>=j?m=a[n]>>c-j&l:(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,k),f.sqrTo(k,e),h-=2;0<h?f.sqrTo(e,k):(h=e,e=k,k=h);f.mulTo(k,g[m],e)}for(;0<=n&&0==(a[n]&1<<c);)f.sqrTo(e,k),h=e,e=k,k=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,k=d-1,l=(1<<d)-1;g[1]=f.convert(this);if(1<d)for(c=nbi(),f.sqrTo(g[1],c);h<=l;)g[h]=nbi(),f.mulTo(c,g[h-2],g[h]),h+=2;for(var m=a.t-1,q,p=!0,s=nbi(),c=nbits(a[m])-1;0<=m;){c>=k?q=a[m]>>c-k&l:(q=(a[m]&(1<<c+1)-1)<<k-c,0<m&&(q|=a[m-1]>>this.DB+c-k));for(h=d;0==(q&1);)q>>=1,--h;0>(c-=h)&&(c+=this.DB,--m);if(p)g[q].copyTo(e),
+p=!1;else{for(;1<h;)f.sqrTo(e,s),f.sqrTo(s,e),h-=2;0<h?f.sqrTo(e,s):(h=e,e=s,s=h);f.mulTo(s,g[q],e)}for(;0<=m&&0==(a[m]&1<<c);)f.sqrTo(e,s),h=e,e=s,s=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,
-h)}0<=c.compareTo(d)?(c.subTo(d,c),b&&e.subTo(g,e),f.subTo(h,f)):(d.subTo(c,d),b&&g.subTo(e,g),h.subTo(f,h))}if(0!=d.compareTo(BigInteger.ONE))return BigInteger.ZERO;if(0<=h.compareTo(a))return h.subtract(a);if(0>h.signum())h.addTo(a,h);else return h;return 0>h.signum()?h.add(a):h}
-var 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],lplim=67108864/lowprimes[lowprimes.length-1];
+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),b?(e.isEven()&&f.isEven()||(e.addTo(this,e),f.subTo(a,f)),e.rShiftTo(1,e)):f.isEven()||f.subTo(a,f),f.rShiftTo(1,f);for(;d.isEven();)d.rShiftTo(1,d),b?(g.isEven()&&h.isEven()||(g.addTo(this,g),h.subTo(a,h)),g.rShiftTo(1,g)):h.isEven()||h.subTo(a,h),h.rShiftTo(1,h);0<=c.compareTo(d)?
+(c.subTo(d,c),b&&e.subTo(g,e),f.subTo(h,f)):(d.subTo(c,d),b&&g.subTo(e,g),h.subTo(f,h))}if(0!=d.compareTo(BigInteger.ONE))return BigInteger.ZERO;if(0<=h.compareTo(a))return h.subtract(a);if(0>h.signum())h.addTo(a,h);else return h;return 0>h.signum()?h.add(a):h}
+var 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,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,
+733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],lplim=67108864/lowprimes[lowprimes.length-1];
 function bnIsProbablePrime(a){var b,c=this.abs();if(1==c.t&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;b<lowprimes.length;++b)if(c[0]==lowprimes[b])return!0;return!1}if(c.isEven())return!1;for(b=1;b<lowprimes.length;){for(var d=lowprimes[b],e=b+1;e<lowprimes.length&&d<lplim;)d*=lowprimes[e++];for(d=c.modInt(d);b<e;)if(0==d%lowprimes[b++])return!1}return c.millerRabin(a)}
-function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(0>=c)return!1;var d=b.shiftRight(c);a=a+1>>1;a>lowprimes.length&&(a=lowprimes.length);for(var e=nbi(),f=0;f<a;++f){e.fromInt(lowprimes[f]);var g=e.modPow(d,this);if(0!=g.compareTo(BigInteger.ONE)&&0!=g.compareTo(b)){for(var h=1;h++<c&&0!=g.compareTo(b);)if(g=g.modPowInt(2,this),0==g.compareTo(BigInteger.ONE))return!1;if(0!=g.compareTo(b))return!1}}return!0}BigInteger.prototype.chunkSize=bnpChunkSize;
-BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.fromNumber=bnpFromNumber;BigInteger.prototype.bitwiseTo=bnpBitwiseTo;BigInteger.prototype.changeBit=bnpChangeBit;BigInteger.prototype.addTo=bnpAddTo;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo;BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo;BigInteger.prototype.modInt=bnpModInt;
-BigInteger.prototype.millerRabin=bnpMillerRabin;BigInteger.prototype.clone=bnClone;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.byteValue=bnByteValue;BigInteger.prototype.shortValue=bnShortValue;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.toByteArray=bnToByteArray;BigInteger.prototype.equals=bnEquals;BigInteger.prototype.min=bnMin;BigInteger.prototype.max=bnMax;BigInteger.prototype.and=bnAnd;BigInteger.prototype.or=bnOr;BigInteger.prototype.xor=bnXor;
-BigInteger.prototype.andNot=bnAndNot;BigInteger.prototype.not=bnNot;BigInteger.prototype.shiftLeft=bnShiftLeft;BigInteger.prototype.shiftRight=bnShiftRight;BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit;BigInteger.prototype.bitCount=bnBitCount;BigInteger.prototype.testBit=bnTestBit;BigInteger.prototype.setBit=bnSetBit;BigInteger.prototype.clearBit=bnClearBit;BigInteger.prototype.flipBit=bnFlipBit;BigInteger.prototype.add=bnAdd;BigInteger.prototype.subtract=bnSubtract;
-BigInteger.prototype.multiply=bnMultiply;BigInteger.prototype.divide=bnDivide;BigInteger.prototype.remainder=bnRemainder;BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder;BigInteger.prototype.modPow=bnModPow;BigInteger.prototype.modInverse=bnModInverse;BigInteger.prototype.pow=bnPow;BigInteger.prototype.gcd=bnGCD;BigInteger.prototype.isProbablePrime=bnIsProbablePrime;
-var LOG=0,NDN=function NDN(b){if(!NDN.supported)throw Error("The necessary JavaScript support is not available on this platform.");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:null;this.port=b.port||9696;this.readyStatus=NDN.UNOPEN;this.verify=void 0!==b.verify?b.verify:!0;this.onopen=b.onopen||function(){3<LOG&&console.log("NDN connection established.")};
-this.onclose=b.onclose||function(){3<LOG&&console.log("NDN connection closed.")};this.ndndid=null};NDN.UNOPEN=0;NDN.OPENED=1;NDN.CLOSED=2;NDN.getSupported=function(){try{(new Uint8Array(1)).subarray(0,1)}catch(a){return console.log("NDN not available: Uint8Array not supported. "+a),!1}return!0};NDN.supported=NDN.getSupported();NDN.ndndIdFetcher=new Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/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.rsaKey=b;this.timeStamp=c};NDN.addKeyEntry=function(a){null==NDN.getKeyByName(a.keyName)&&NDN.KeyStore.push(a)};NDN.getKeyByName=function(a){for(var b=null,c=0;c<NDN.KeyStore.length;c++)if(NDN.KeyStore[c].keyName.contentName.match(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;this.timerID=-1};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.CSTable=[];var CSEntry=function(a,b){this.name=a;this.closure=b};
-function getEntryForRegisteredPrefix(a){for(var b=0;b<NDN.CSTable.length;b++)if(null!=NDN.CSTable[b].name.match(a))return NDN.CSTable[b];return null}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){var d=new Interest(a);null!=c?(d.minSuffixComponents=c.minSuffixComponents,d.maxSuffixComponents=c.maxSuffixComponents,d.publisherPublicKeyDigest=c.publisherPublicKeyDigest,d.exclude=c.exclude,d.childSelector=c.childSelector,d.answerOriginKind=c.answerOriginKind,d.scope=c.scope,d.interestLifetime=c.interestLifetime):d.interestLifetime=4E3;if(null==this.host||null==this.port)if(null==this.getHostAndPort)console.log("ERROR: host OR port NOT SET");else{var e=
-this;this.connectAndExecute(function(){e.reconnectAndExpressInterest(d,b)})}else this.reconnectAndExpressInterest(d,b)};NDN.prototype.reconnectAndExpressInterest=function(a,b){if(this.transport.connectedHost!=this.host||this.transport.connectedPort!=this.port){var c=this;this.transport.connect(c,function(){c.expressInterestHelper(a,b)})}else this.expressInterestHelper(a,b)};
-NDN.prototype.expressInterestHelper=function(a,b){var c=encodeToBinaryInterest(a),d=this;if(null!=b){var e=new PITEntry(a,b);NDN.PITTable.push(e);b.pitEntry=e;var f=a.interestLifetime||4E3,g=function(){3<LOG&&console.log("Interest time out: "+a.name.to_uri());var h=NDN.PITTable.indexOf(e);0<=h&&NDN.PITTable.splice(h,1);b.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,new UpcallInfo(d,a,0,null))==Closure.RESULT_REEXPRESS&&(3<LOG&&console.log("Re-express interest: "+a.name.to_uri()),e.timerID=setTimeout(g,
-f),NDN.PITTable.push(e),d.transport.send(c))};e.timerID=setTimeout(g,f)}this.transport.send(c)};
-NDN.prototype.registerPrefix=function(a,b,c){var d=this,e=function(){if(null==d.ndndid){var e=new Interest(NDN.ndndIdFetcher);e.interestLifetime=4E3;3<LOG&&console.log("Expressing interest for ndndid from ndnd.");d.reconnectAndExpressInterest(e,new NDN.FetchNdndidClosure(d,a,b,c))}else d.registerPrefixHelper(a,b,c)};null==this.host||null==this.port?null==this.getHostAndPort?console.log("ERROR: host OR port NOT SET"):this.connectAndExecute(e):e()};
-NDN.FetchNdndidClosure=function(a,b,c,d){Closure.call(this);this.ndn=a;this.name=b;this.callerClosure=c;this.flag=d};
-NDN.FetchNdndidClosure.prototype.upcall=function(a,b){if(a==Closure.UPCALL_INTEREST_TIMED_OUT)return console.log("Timeout while requesting the ndndid.  Cannot registerPrefix for "+this.name.to_uri()+" ."),Closure.RESULT_OK;if(!(a==Closure.UPCALL_CONTENT||a==Closure.UPCALL_CONTENT_UNVERIFIED))return Closure.RESULT_ERR;var c=b.contentObject;!c.signedInfo||!c.signedInfo.publisher||!c.signedInfo.publisher.publisherPublicKeyDigest?console.log("ContentObject doesn't have a publisherPublicKeyDigest. Cannot set ndndid and registerPrefix for "+
-this.name.to_uri()+" ."):(3<LOG&&console.log("Got ndndid from ndnd."),this.ndn.ndndid=c.signedInfo.publisher.publisherPublicKeyDigest,3<LOG&&console.log(this.ndn.ndndid),this.ndn.registerPrefixHelper(this.name,this.callerClosure,this.flag));return Closure.RESULT_OK};
-NDN.prototype.registerPrefixHelper=function(a,b){var c=new ForwardingEntry("selfreg",a,null,null,3,2147483647),c=encodeForwardingEntry(c),d=new SignedInfo;d.setFields();c=new ContentObject(new Name,d,c,new Signature);c.sign();c=encodeToBinaryContentObject(c);c=new Name(["ndnx",this.ndndid,"selfreg",c]);c=new Interest(c);c.scope=1;3<LOG&&console.log("Send Interest registration packet.");d=new CSEntry(a.getName(),b);NDN.CSTable.push(d);this.transport.send(encodeToBinaryInterest(c))};
-NDN.prototype.onReceivedElement=function(a){3<LOG&&console.log("Complete element received. Length "+a.length+". Start decoding.");var b=new BinaryXMLDecoder(a);if(b.peekStartElement(NDNProtocolDTags.Interest))3<LOG&&console.log("Interest packet received."),a=new Interest,a.from_ndnb(b),3<LOG&&console.log(a),b=escape(a.name.getName()),3<LOG&&console.log(b),b=getEntryForRegisteredPrefix(b),null!=b&&(a=new UpcallInfo(this,a,0,null),b.closure.upcall(Closure.UPCALL_INTEREST,a)==Closure.RESULT_INTEREST_CONSUMED&&
-null!=a.contentObject&&this.transport.send(encodeToBinaryContentObject(a.contentObject)));else if(b.peekStartElement(NDNProtocolDTags.ContentObject)){if(3<LOG&&console.log("ContentObject packet received."),a=new ContentObject,a.from_ndnb(b),b=NDN.getEntryForExpressedInterest(a.name),null!=b){clearTimeout(b.timerID);var c=NDN.PITTable.indexOf(b);0<=c&&NDN.PITTable.splice(c,1);c=b.closure;if(!1==this.verify)c.upcall(Closure.UPCALL_CONTENT_UNVERIFIED,new UpcallInfo(this,b.interest,0,a));else{var d=function(a,
-b,c,d,e){this.contentObject=a;this.closure=b;this.keyName=c;this.sigHex=d;this.witness=e;Closure.call(this)},e=this;d.prototype.upcall=function(a,b){if(a==Closure.UPCALL_INTEREST_TIMED_OUT)console.log("In KeyFetchClosure.upcall: interest time out."),console.log(this.keyName.contentName.getName());else if(a==Closure.UPCALL_CONTENT){var c=decodeSubjectPublicKeyInfo(b.contentObject.content),d=!0==c.verifyByteArray(this.contentObject.rawSignatureData,this.witness,this.sigHex)?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD;
-this.closure.upcall(d,new UpcallInfo(e,null,0,this.contentObject));c=new KeyStoreEntry(h.keyName,c,(new Date).getTime());NDN.addKeyEntry(c)}else a==Closure.UPCALL_CONTENT_BAD&&console.log("In KeyFetchClosure.upcall: signature verification failed")};if(a.signedInfo&&a.signedInfo.locator&&a.signature){3<LOG&&console.log("Key verification...");var f=DataUtils.toHex(a.signature.signature).toLowerCase(),g=null;null!=a.signature.Witness&&(g=new Witness,g.decode(a.signature.Witness));var h=a.signedInfo.locator;
-if(h.type==KeyLocatorType.KEYNAME)if(3<LOG&&console.log("KeyLocator contains KEYNAME"),h.keyName.contentName.match(a.name))3<LOG&&console.log("Content is key itself"),d=decodeSubjectPublicKeyInfo(a.content),f=d.verifyByteArray(a.rawSignatureData,g,f),f=!0==f?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD,c.upcall(f,new UpcallInfo(this,b.interest,0,a));else{var j=NDN.getKeyByName(h.keyName);j?(3<LOG&&console.log("Local key cache hit"),d=j.rsaKey,f=d.verifyByteArray(a.rawSignatureData,g,f),f=!0==
-f?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD,c.upcall(f,new UpcallInfo(this,b.interest,0,a))):(3<LOG&&console.log("Fetch key according to keylocator"),a=new d(a,c,h.keyName,f,g),this.expressInterest(h.keyName.contentName.getPrefix(4),a))}else h.type==KeyLocatorType.KEY?(3<LOG&&console.log("Keylocator contains KEY"),d=decodeSubjectPublicKeyInfo(a.signedInfo.locator.publicKey),f=d.verifyByteArray(a.rawSignatureData,g,f),f=!0==f?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD,c.upcall(Closure.UPCALL_CONTENT,
-new UpcallInfo(this,b.interest,0,a))):(a=h.certificate,console.log("KeyLocator contains CERT"),console.log(a))}}}}else console.log("Incoming packet is not Interest or ContentObject. Discard now.")};
-NDN.prototype.connectAndExecute=function(a){var b=this.getHostAndPort();if(null==b)console.log("ERROR: No more hosts from getHostAndPort"),this.host=null;else if(b.host==this.host&&b.port==this.port)console.log("ERROR: The host returned by getHostAndPort is not alive: "+this.host+":"+this.port);else{this.host=b.host;this.port=b.port;3<LOG&&console.log("Connect: trying host from getHostAndPort: "+this.host);b=new Interest(new Name("/"));b.interestLifetime=4E3;var c=this,d=setTimeout(function(){3<LOG&&
-console.log("Connect: timeout waiting for host "+c.host);c.connectAndExecute(a)},3E3);this.reconnectAndExpressInterest(b,new NDN.ConnectClosure(this,a,d))}};NDN.ConnectClosure=function(a,b,c){Closure.call(this);this.ndn=a;this.onConnected=b;this.timerID=c};NDN.ConnectClosure.prototype.upcall=function(a){if(!(a==Closure.UPCALL_CONTENT||a==Closure.UPCALL_CONTENT_UNVERIFIED))return Closure.RESULT_ERR;clearTimeout(this.timerID);this.ndn.readyStatus=NDN.OPENED;this.ndn.onopen();this.onConnected();return Closure.RESULT_OK};
-var BinaryXmlElementReader=function(a){this.elementListener=a;this.dataParts=[];this.structureDecoder=new BinaryXMLStructureDecoder};
-BinaryXmlElementReader.prototype.onReceivedData=function(a){for(;;)if(this.structureDecoder.seek(0),this.structureDecoder.findElementEnd(a)){this.dataParts.push(a.subarray(0,this.structureDecoder.offset));var b=DataUtils.concatArrays(this.dataParts);this.dataParts=[];try{this.elementListener.onReceivedElement(b)}catch(c){console.log("BinaryXmlElementReader: ignoring exception from onReceivedElement: "+c)}a=a.subarray(this.structureDecoder.offset,a.length);this.structureDecoder=new BinaryXMLStructureDecoder;
-if(0==a.length)break}else{this.dataParts.push(a);3<LOG&&console.log("Incomplete packet received. Length "+a.length+". Wait for more input.");break}};
+function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(0>=c)return!1;var d=b.shiftRight(c);a=a+1>>1;a>lowprimes.length&&(a=lowprimes.length);for(var e=nbi(),f=0;f<a;++f){e.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);var g=e.modPow(d,this);if(0!=g.compareTo(BigInteger.ONE)&&0!=g.compareTo(b)){for(var h=1;h++<c&&0!=g.compareTo(b);)if(g=g.modPowInt(2,this),0==g.compareTo(BigInteger.ONE))return!1;if(0!=g.compareTo(b))return!1}}return!0}
+BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.fromNumber=bnpFromNumber;BigInteger.prototype.bitwiseTo=bnpBitwiseTo;BigInteger.prototype.changeBit=bnpChangeBit;BigInteger.prototype.addTo=bnpAddTo;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo;BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo;
+BigInteger.prototype.modInt=bnpModInt;BigInteger.prototype.millerRabin=bnpMillerRabin;BigInteger.prototype.clone=bnClone;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.byteValue=bnByteValue;BigInteger.prototype.shortValue=bnShortValue;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.toByteArray=bnToByteArray;BigInteger.prototype.equals=bnEquals;BigInteger.prototype.min=bnMin;BigInteger.prototype.max=bnMax;BigInteger.prototype.and=bnAnd;BigInteger.prototype.or=bnOr;
+BigInteger.prototype.xor=bnXor;BigInteger.prototype.andNot=bnAndNot;BigInteger.prototype.not=bnNot;BigInteger.prototype.shiftLeft=bnShiftLeft;BigInteger.prototype.shiftRight=bnShiftRight;BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit;BigInteger.prototype.bitCount=bnBitCount;BigInteger.prototype.testBit=bnTestBit;BigInteger.prototype.setBit=bnSetBit;BigInteger.prototype.clearBit=bnClearBit;BigInteger.prototype.flipBit=bnFlipBit;BigInteger.prototype.add=bnAdd;BigInteger.prototype.subtract=bnSubtract;
+BigInteger.prototype.multiply=bnMultiply;BigInteger.prototype.divide=bnDivide;BigInteger.prototype.remainder=bnRemainder;BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder;BigInteger.prototype.modPow=bnModPow;BigInteger.prototype.modInverse=bnModInverse;BigInteger.prototype.pow=bnPow;BigInteger.prototype.gcd=bnGCD;BigInteger.prototype.isProbablePrime=bnIsProbablePrime;BigInteger.prototype.square=bnSquare;exports.BigInteger=BigInteger;module.exports=exports;
+var ASN1HEX=require("../contrib/securityLib/asn1hex-1.1.js").ASN1HEX,KJUR=require("../contrib/securityLib/crypto-1.0.js").KJUR,RSAKey=require("../contrib/securityLib/rsasign-1.2.js").RSAKey,b64tohex=require("../contrib/securityLib/base64.js").b64tohex,exports=ndn=ndn||{};
+exports.createHash=function(a){if("sha256"!=a)throw Error("createHash: unsupported algorithm.");a={};a.md=new KJUR.crypto.MessageDigest({alg:"sha256",prov:"cryptojs"});a.update=function(a){this.md.updateHex(a.toString("hex"))};a.digest=function(a){var c=this.md.digest();return"hex"==a?c:"base64"==a?(new Buffer(c,"hex")).toString("base64"):new Buffer(c,"hex")};return a};
+exports.createHmac=function(a,b){if("sha256"!==a)throw Error("createHmac: unsupported algorithm.");var c={};c.md=new KJUR.crypto.Mac({alg:"HmacSHA256",pass:{hex:b.toString("hex")}});c.update=function(a){this.md.updateHex(a.toString("hex"))};c.digest=function(a){var b=this.md.doFinal();return"hex"==a?b:"base64"==a?(new Buffer(b,"hex")).toString("base64"):new Buffer(b,"hex")};return c};
+exports.createSign=function(a){if("RSA-SHA256"!=a)throw Error("createSign: unsupported algorithm.");return{arr:[],update:function(a){this.arr.push(a)},sign:function(a){var c=new RSAKey;c.readPrivateKeyFromPEMString(a);a=new KJUR.crypto.Signature({alg:"SHA256withRSA",prov:"cryptojs/jsrsa"});a.initSign(c);for(c=0;c<this.arr.length;++c)a.updateHex(this.arr[c].toString("hex"));return new Buffer(a.sign(),"hex")}}};
+exports.createVerify=function(a){if("RSA-SHA256"!=a)throw Error("createSign: unsupported algorithm.");return{arr:[],update:function(a){this.arr.push(a)},verify:function(a,c){for(var d=a.split("\n"),e="",f=1;f<d.length-1;f++)e+=d[f];d=(new Buffer(e,"base64")).toString("hex");e=ASN1HEX.getPosArrayOfChildren_AtObj(d,0);2!=e.length?e=-1:(e=e[1],"03"!=d.substring(e,e+2)?e=-1:(e=ASN1HEX.getStartPosOfV_AtObj(d,e),e="00"!=d.substring(e,e+2)?-1:e+2));f=ASN1HEX.getPosArrayOfChildren_AtObj(d,e);2!=f.length?
+e=null:(e=ASN1HEX.getHexOfV_AtObj(d,f[0]),d=ASN1HEX.getHexOfV_AtObj(d,f[1]),f=new RSAKey,f.setPublic(e,d),e=f);d=new KJUR.crypto.Signature({alg:"SHA256withRSA",prov:"cryptojs/jsrsa"});d.initVerifyByPublicKey(e);for(e=0;e<this.arr.length;e++)d.updateHex(this.arr[e].toString("hex"));e=c.toString("hex");return d.verify(e)}}};exports.randomBytes=function(a){for(var b=new Buffer(a),c=0;c<a;++c)b[c]=Math.floor(256*Math.random());return b};
+exports.toByteArray=function(a){var b=[];b64tohex(a).replace(/(..)/g,function(a){b.push(parseInt(a,16))});return b};module.exports=exports;var lookup="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",base64js={};
+(function(a){function b(a){a=a.charCodeAt(0);if(a===d)return 62;if(a===e)return 63;if(a<f)return-1;if(a<f+10)return a-f+52;if(a<h+26)return a-h;if(a<g+26)return a-g+26}var c="undefined"!==typeof Uint8Array?Uint8Array:Array,d=43,e=47,f=48,g=97,h=65;a.toByteArray=function(a){function d(a){w[M++]=a}var e,f,g,h,w;if(0<a.length%4)throw Error("Invalid string. Length must be a multiple of 4");e=a.length;h="="===a.charAt(e-2)?2:"="===a.charAt(e-1)?1:0;w=new c(3*a.length/4-h);f=0<h?a.length-4:a.length;var M=
+0;for(e=0;e<f;e+=4)g=b(a.charAt(e))<<18|b(a.charAt(e+1))<<12|b(a.charAt(e+2))<<6|b(a.charAt(e+3)),d((g&16711680)>>16),d((g&65280)>>8),d(g&255);2===h?(g=b(a.charAt(e))<<2|b(a.charAt(e+1))>>4,d(g&255)):1===h&&(g=b(a.charAt(e))<<10|b(a.charAt(e+1))<<4|b(a.charAt(e+2))>>2,d(g>>8&255),d(g&255));return w};a.fromByteArray=function(a){var b,c=a.length%3,d="",e,f;b=0;for(f=a.length-c;b<f;b+=3)e=(a[b]<<16)+(a[b+1]<<8)+a[b+2],e=lookup.charAt(e>>18&63)+lookup.charAt(e>>12&63)+lookup.charAt(e>>6&63)+lookup.charAt(e&
+63),d+=e;switch(c){case 1:e=a[a.length-1];d+=lookup.charAt(e>>2);d+=lookup.charAt(e<<4&63);d+="==";break;case 2:e=(a[a.length-2]<<8)+a[a.length-1],d+=lookup.charAt(e>>10),d+=lookup.charAt(e>>4&63),d+=lookup.charAt(e<<2&63),d+="="}return d}})(base64js);
+var ieee={read:function(a,b,c,d,e){var f;f=8*e-d-1;var g=(1<<f)-1,h=g>>1,k=-7;e=c?e-1:0;var l=c?-1:1,m=a[b+e];e+=l;c=m&(1<<-k)-1;m>>=-k;for(k+=f;0<k;c=256*c+a[b+e],e+=l,k-=8);f=c&(1<<-k)-1;c>>=-k;for(k+=d;0<k;f=256*f+a[b+e],e+=l,k-=8);if(0===c)c=1-h;else{if(c===g)return f?NaN:Infinity*(m?-1:1);f+=Math.pow(2,d);c-=h}return(m?-1:1)*f*Math.pow(2,c-d)},write:function(a,b,c,d,e,f){var g,h=8*f-e-1,k=(1<<h)-1,l=k>>1,m=23===e?Math.pow(2,-24)-Math.pow(2,-77):0;f=d?0:f-1;var q=d?1:-1,p=0>b||0===b&&0>1/b?1:
+0;b=Math.abs(b);isNaN(b)||Infinity===b?(b=isNaN(b)?1:0,d=k):(d=Math.floor(Math.log(b)/Math.LN2),1>b*(g=Math.pow(2,-d))&&(d--,g*=2),b=1<=d+l?b+m/g:b+m*Math.pow(2,1-l),2<=b*g&&(d++,g/=2),d+l>=k?(b=0,d=k):1<=d+l?(b=(b*g-1)*Math.pow(2,e),d+=l):(b=b*Math.pow(2,l-1)*Math.pow(2,e),d=0));for(;8<=e;a[c+f]=b&255,f+=q,b/=256,e-=8);d=d<<e|b;for(h+=e;0<h;a[c+f]=d&255,f+=q,d/=256,h-=8);a[c+f-q]|=128*p}};exports.ieee=ieee;var base64=base64js,ieee754=require("./ieee754.js").ieee;exports.Buffer=Buffer;
+exports.SlowBuffer=Buffer;exports.INSPECT_MAX_BYTES=50;Buffer.poolSize=8192;Buffer._useTypedArrays=function(){try{var a=new ArrayBuffer(0),b=new Uint8Array(a);b.foo=function(){return 42};return 42===b.foo()&&"function"===typeof b.subarray}catch(c){return!1}}();
+function Buffer(a,b,c){if(!(this instanceof Buffer))return new Buffer(a,b,c);var d=typeof a;if("base64"===b&&"string"===d)for(a=Buffer.stringtrim(a);0!==a.length%4;)a+="=";var e;if("number"===d)e=Buffer.coerce(a);else if("string"===d)e=Buffer.byteLength(a,b);else if("object"===d)e=Buffer.coerce(a.length);else throw Error("First argument needs to be a number, array or string.");var f;Buffer._useTypedArrays?f=Buffer._augment(new Uint8Array(e)):(f=this,f.length=e,f._isBuffer=!0);if(Buffer._useTypedArrays&&
+"number"===typeof a.byteLength)f._set(a);else if(Buffer.isArrayish(a))if(Buffer.isBuffer(a))for(b=0;b<e;b++)f[b]=a.readUInt8(b);else for(b=0;b<e;b++)f[b]=(a[b]%256+256)%256;else if("string"===d)f.write(a,0,b);else if("number"===d&&!Buffer._useTypedArrays&&!c)for(b=0;b<e;b++)f[b]=0;return f}
+Buffer.isEncoding=function(a){switch(String(a).toLowerCase()){case "hex":case "utf8":case "utf-8":case "ascii":case "binary":case "base64":case "raw":case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":return!0;default:return!1}};Buffer.isBuffer=function(a){return!(null===a||void 0===a||!a._isBuffer)};
+Buffer.byteLength=function(a,b){var c;a=a.toString();switch(b||"utf8"){case "hex":c=a.length/2;break;case "utf8":case "utf-8":c=Buffer.utf8ToBytes(a).length;break;case "ascii":case "binary":case "raw":c=a.length;break;case "base64":c=Buffer.base64ToBytes(a).length;break;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":c=2*a.length;break;default:throw Error("Unknown encoding");}return c};
+Buffer.concat=function(a,b){Buffer.assert(Buffer.isArray(a),"Usage: Buffer.concat(list[, length])");if(0===a.length)return new Buffer(0);if(1===a.length)return a[0];var c;if(void 0===b)for(c=b=0;c<a.length;c++)b+=a[c].length;var d=new Buffer(b),e=0;for(c=0;c<a.length;c++){var f=a[c];f.copy(d,e);e+=f.length}return d};
+Buffer.compare=function(a,b){Buffer.assert(Buffer.isBuffer(a)&&Buffer.isBuffer(b),"Arguments must be Buffers");for(var c=a.length,d=b.length,e=0,f=Math.min(c,d);e<f&&a[e]===b[e];e++);e!==f&&(c=a[e],d=b[e]);return c<d?-1:d<c?1:0};
+Buffer.hexWrite=function(a,b,c,d){c=Number(c)||0;var e=a.length-c;d?(d=Number(d),d>e&&(d=e)):d=e;e=b.length;Buffer.assert(0===e%2,"Invalid hex string");d>e/2&&(d=e/2);for(e=0;e<d;e++){var f=parseInt(b.substr(2*e,2),16);Buffer.assert(!isNaN(f),"Invalid hex string");a[c+e]=f}return e};Buffer.utf8Write=function(a,b,c,d){return Buffer.blitBuffer(Buffer.utf8ToBytes(b),a,c,d)};Buffer.asciiWrite=function(a,b,c,d){return Buffer.blitBuffer(Buffer.asciiToBytes(b),a,c,d)};
+Buffer.binaryWrite=function(a,b,c,d){return Buffer.asciiWrite(a,b,c,d)};Buffer.base64Write=function(a,b,c,d){return Buffer.blitBuffer(Buffer.base64ToBytes(b),a,c,d)};Buffer.utf16leWrite=function(a,b,c,d){return Buffer.blitBuffer(Buffer.utf16leToBytes(b),a,c,d)};
+Buffer.prototype.write=function(a,b,c,d){if(isFinite(b))isFinite(c)||(d=c,c=void 0);else{var e=d;d=b;b=c;c=e}b=Number(b)||0;e=this.length-b;c?(c=Number(c),c>e&&(c=e)):c=e;d=String(d||"utf8").toLowerCase();switch(d){case "hex":a=Buffer.hexWrite(this,a,b,c);break;case "utf8":case "utf-8":a=Buffer.utf8Write(this,a,b,c);break;case "ascii":a=Buffer.asciiWrite(this,a,b,c);break;case "binary":a=Buffer.binaryWrite(this,a,b,c);break;case "base64":a=Buffer.base64Write(this,a,b,c);break;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":a=
+Buffer.utf16leWrite(this,a,b,c);break;default:throw Error("Unknown encoding");}return a};
+Buffer.prototype.toString=function(a,b,c){a=String(a||"utf8").toLowerCase();b=Number(b)||0;c=void 0===c?this.length:Number(c);if(c===b)return"";switch(a){case "hex":a=Buffer.hexSlice(this,b,c);break;case "utf8":case "utf-8":a=Buffer.utf8Slice(this,b,c);break;case "ascii":a=Buffer.asciiSlice(this,b,c);break;case "binary":a=Buffer.binarySlice(this,b,c);break;case "base64":a=Buffer.base64Slice(this,b,c);break;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":a=utf16leSlice(this,b,c);break;default:throw Error("Unknown encoding");
+}return a};Buffer.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};Buffer.prototype.equals=function(a){Buffer.assert(Buffer.isBuffer(a),"Argument must be a Buffer");return 0===Buffer.compare(this,a)};Buffer.prototype.compare=function(a){Buffer.assert(Buffer.isBuffer(a),"Argument must be a Buffer");return Buffer.compare(this,a)};
+Buffer.prototype.copy=function(a,b,c,d){c||(c=0);d||0===d||(d=this.length);b||(b=0);if(d!==c&&0!==a.length&&0!==this.length)if(Buffer.assert(d>=c,"sourceEnd < sourceStart"),Buffer.assert(0<=b&&b<a.length,"targetStart out of bounds"),Buffer.assert(0<=c&&c<this.length,"sourceStart out of bounds"),Buffer.assert(0<=d&&d<=this.length,"sourceEnd out of bounds"),d>this.length&&(d=this.length),a.length-b<d-c&&(d=a.length-b+c),d-=c,100>d||!Buffer._useTypedArrays)for(var e=0;e<d;e++)a[e+b]=this[e+c];else a._set(this.subarray(c,
+c+d),b)};Buffer.base64Slice=function(a,b,c){return 0===b&&c===a.length?base64.fromByteArray(a):base64.fromByteArray(a.slice(b,c))};Buffer.utf8Slice=function(a,b,c){var d="",e="";for(c=Math.min(a.length,c);b<c;b++)127>=a[b]?(d+=Buffer.decodeUtf8Char(e)+String.fromCharCode(a[b]),e=""):e+="%"+a[b].toString(16);return d+Buffer.decodeUtf8Char(e)};Buffer.asciiSlice=function(a,b,c){var d="";for(c=Math.min(a.length,c);b<c;b++)d+=String.fromCharCode(a[b]);return d};
+Buffer.binarySlice=function(a,b,c){return Buffer.asciiSlice(a,b,c)};Buffer.hexSlice=function(a,b,c){var d=a.length;if(!b||0>b)b=0;if(!c||0>c||c>d)c=d;for(d="";b<c;b++)d+=Buffer.toHex(a[b]);return d};function utf16leSlice(a,b,c){a=a.slice(b,c);b="";for(c=0;c<a.length;c+=2)b+=String.fromCharCode(a[c]+256*a[c+1]);return b}
+Buffer.prototype.slice=function(a,b){var c=this.length;a=Buffer.clamp(a,c,0);b=Buffer.clamp(b,c,c);if(Buffer._useTypedArrays)return Buffer._augment(this.subarray(a,b));for(var c=b-a,d=new Buffer(c,void 0,!0),e=0;e<c;e++)d[e]=this[e+a];return d};Buffer.prototype.get=function(a){console.log(".get() is deprecated. Access using array indexes instead.");return this.readUInt8(a)};
+Buffer.prototype.set=function(a,b){console.log(".set() is deprecated. Access using array indexes instead.");return this.writeUInt8(a,b)};Buffer.prototype.readUInt8=function(a,b){b||(Buffer.assert(void 0!==a&&null!==a,"missing offset"),Buffer.assert(a<this.length,"Trying to read beyond buffer length"));if(!(a>=this.length))return this[a]};
+Buffer.readUInt16=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b+1<a.length,"Trying to read beyond buffer length"));d=a.length;if(!(b>=d))return c?(c=a[b],b+1<d&&(c|=a[b+1]<<8)):(c=a[b]<<8,b+1<d&&(c|=a[b+1])),c};Buffer.prototype.readUInt16LE=function(a,b){return Buffer.readUInt16(this,a,!0,b)};Buffer.prototype.readUInt16BE=function(a,b){return Buffer.readUInt16(this,a,!1,b)};
+Buffer.readUInt32=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b+3<a.length,"Trying to read beyond buffer length"));d=a.length;if(!(b>=d)){var e;c?(b+2<d&&(e=a[b+2]<<16),b+1<d&&(e|=a[b+1]<<8),e|=a[b],b+3<d&&(e+=a[b+3]<<24>>>0)):(b+1<d&&(e=a[b+1]<<16),b+2<d&&(e|=a[b+2]<<8),b+3<d&&(e|=a[b+3]),e+=a[b]<<24>>>0);return e}};
+Buffer.prototype.readUInt32LE=function(a,b){return Buffer.readUInt32(this,a,!0,b)};Buffer.prototype.readUInt32BE=function(a,b){return Buffer.readUInt32(this,a,!1,b)};Buffer.prototype.readInt8=function(a,b){b||(Buffer.assert(void 0!==a&&null!==a,"missing offset"),Buffer.assert(a<this.length,"Trying to read beyond buffer length"));if(!(a>=this.length))return this[a]&128?-1*(255-this[a]+1):this[a]};
+Buffer.readInt16=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b+1<a.length,"Trying to read beyond buffer length"));if(!(b>=a.length))return a=Buffer.readUInt16(a,b,c,!0),a&32768?-1*(65535-a+1):a};Buffer.prototype.readInt16LE=function(a,b){return Buffer.readInt16(this,a,!0,b)};Buffer.prototype.readInt16BE=function(a,b){return Buffer.readInt16(this,a,!1,b)};
+Buffer.readInt32=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b+3<a.length,"Trying to read beyond buffer length"));if(!(b>=a.length))return a=Buffer.readUInt32(a,b,c,!0),a&2147483648?-1*(4294967295-a+1):a};Buffer.prototype.readInt32LE=function(a,b){return Buffer.readInt32(this,a,!0,b)};Buffer.prototype.readInt32BE=function(a,b){return Buffer.readInt32(this,a,!1,b)};
+Buffer.readFloat=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(b+3<a.length,"Trying to read beyond buffer length"));return ieee754.read(a,b,c,23,4)};Buffer.prototype.readFloatLE=function(a,b){return Buffer.readFloat(this,a,!0,b)};Buffer.prototype.readFloatBE=function(a,b){return Buffer.readFloat(this,a,!1,b)};
+Buffer.readDouble=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(b+7<a.length,"Trying to read beyond buffer length"));return ieee754.read(a,b,c,52,8)};Buffer.prototype.readDoubleLE=function(a,b){return Buffer.readDouble(this,a,!0,b)};Buffer.prototype.readDoubleBE=function(a,b){return Buffer.readDouble(this,a,!1,b)};
+Buffer.prototype.writeUInt8=function(a,b,c){c||(Buffer.assert(void 0!==a&&null!==a,"missing value"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b<this.length,"trying to write beyond buffer length"),Buffer.verifuint(a,255));if(!(b>=this.length))return this[b]=a,b+1};
+Buffer.writeUInt16=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+1<a.length,"trying to write beyond buffer length"),Buffer.verifuint(b,65535));var f=a.length;if(!(c>=f)){e=0;for(f=Math.min(f-c,2);e<f;e++)a[c+e]=(b&255<<8*(d?e:1-e))>>>8*(d?e:1-e);return c+2}};
+Buffer.prototype.writeUInt16LE=function(a,b,c){return Buffer.writeUInt16(this,a,b,!0,c)};Buffer.prototype.writeUInt16BE=function(a,b,c){return Buffer.writeUInt16(this,a,b,!1,c)};
+Buffer.writeUInt32=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+3<a.length,"trying to write beyond buffer length"),Buffer.verifuint(b,4294967295));var f=a.length;if(!(c>=f)){e=0;for(f=Math.min(f-c,4);e<f;e++)a[c+e]=b>>>8*(d?e:3-e)&255;return c+4}};Buffer.prototype.writeUInt32LE=function(a,b,c){return Buffer.writeUInt32(this,a,b,!0,c)};
+Buffer.prototype.writeUInt32BE=function(a,b,c){return Buffer.writeUInt32(this,a,b,!1,c)};Buffer.prototype.writeInt8=function(a,b,c){c||(Buffer.assert(void 0!==a&&null!==a,"missing value"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b<this.length,"Trying to write beyond buffer length"),Buffer.verifsint(a,127,-128));if(!(b>=this.length))return 0<=a?this.writeUInt8(a,b,c):this.writeUInt8(255+a+1,b,c),b+1};
+Buffer.writeInt16=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+1<a.length,"Trying to write beyond buffer length"),Buffer.verifsint(b,32767,-32768));if(!(c>=a.length))return 0<=b?Buffer.writeUInt16(a,b,c,d,e):Buffer.writeUInt16(a,65535+b+1,c,d,e),c+2};Buffer.prototype.writeInt16LE=function(a,b,c){return Buffer.writeInt16(this,a,b,!0,c)};
+Buffer.prototype.writeInt16BE=function(a,b,c){return Buffer.writeInt16(this,a,b,!1,c)};
+Buffer.writeInt32=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+3<a.length,"Trying to write beyond buffer length"),Buffer.verifsint(b,2147483647,-2147483648));if(!(c>=a.length))return 0<=b?Buffer.writeUInt32(a,b,c,d,e):Buffer.writeUInt32(a,4294967295+b+1,c,d,e),c+4};
+Buffer.prototype.writeInt32LE=function(a,b,c){return Buffer.writeInt32(this,a,b,!0,c)};Buffer.prototype.writeInt32BE=function(a,b,c){return Buffer.writeInt32(this,a,b,!1,c)};
+Buffer.writeFloat=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+3<a.length,"Trying to write beyond buffer length"),Buffer.verifIEEE754(b,3.4028234663852886E38,-3.4028234663852886E38));if(!(c>=a.length))return ieee754.write(a,b,c,d,23,4),c+4};Buffer.prototype.writeFloatLE=function(a,b,c){return Buffer.writeFloat(this,a,b,!0,c)};
+Buffer.prototype.writeFloatBE=function(a,b,c){return Buffer.writeFloat(this,a,b,!1,c)};Buffer.writeDouble=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+7<a.length,"Trying to write beyond buffer length"),Buffer.verifIEEE754(b,1.7976931348623157E308,-1.7976931348623157E308));if(!(c>=a.length))return ieee754.write(a,b,c,d,52,8),c+8};
+Buffer.prototype.writeDoubleLE=function(a,b,c){return Buffer.writeDouble(this,a,b,!0,c)};Buffer.prototype.writeDoubleBE=function(a,b,c){return Buffer.writeDouble(this,a,b,!1,c)};
+Buffer.prototype.fill=function(a,b,c){a||(a=0);b||(b=0);c||(c=this.length);Buffer.assert(c>=b,"end < start");if(c!==b&&0!==this.length){Buffer.assert(0<=b&&b<this.length,"start out of bounds");Buffer.assert(0<=c&&c<=this.length,"end out of bounds");if("number"===typeof a)for(;b<c;b++)this[b]=a;else{a=Buffer.utf8ToBytes(a.toString());for(var d=a.length;b<c;b++)this[b]=a[b%d]}return this}};
+Buffer.prototype.inspect=function(){for(var a=[],b=this.length,c=0;c<b;c++)if(a[c]=Buffer.toHex(this[c]),c===exports.INSPECT_MAX_BYTES){a[c+1]="...";break}return"<Buffer "+a.join(" ")+">"};Buffer.prototype.toArrayBuffer=function(){if("undefined"!==typeof Uint8Array){if(Buffer._useTypedArrays)return(new Buffer(this)).buffer;for(var a=new Uint8Array(this.length),b=0,c=a.length;b<c;b+=1)a[b]=this[b];return a.buffer}throw Error("Buffer.toArrayBuffer not supported in this browser");};var BP=Buffer.prototype;
+Buffer._augment=function(a){a._isBuffer=!0;a._get=a.get;a._set=a.set;a.get=BP.get;a.set=BP.set;a.write=BP.write;a.toString=BP.toString;a.toLocaleString=BP.toString;a.toJSON=BP.toJSON;a.equals=BP.equals;a.compare=BP.compare;a.copy=BP.copy;a.slice=BP.slice;a.readUInt8=BP.readUInt8;a.readUInt16LE=BP.readUInt16LE;a.readUInt16BE=BP.readUInt16BE;a.readUInt32LE=BP.readUInt32LE;a.readUInt32BE=BP.readUInt32BE;a.readInt8=BP.readInt8;a.readInt16LE=BP.readInt16LE;a.readInt16BE=BP.readInt16BE;a.readInt32LE=BP.readInt32LE;
+a.readInt32BE=BP.readInt32BE;a.readFloatLE=BP.readFloatLE;a.readFloatBE=BP.readFloatBE;a.readDoubleLE=BP.readDoubleLE;a.readDoubleBE=BP.readDoubleBE;a.writeUInt8=BP.writeUInt8;a.writeUInt16LE=BP.writeUInt16LE;a.writeUInt16BE=BP.writeUInt16BE;a.writeUInt32LE=BP.writeUInt32LE;a.writeUInt32BE=BP.writeUInt32BE;a.writeInt8=BP.writeInt8;a.writeInt16LE=BP.writeInt16LE;a.writeInt16BE=BP.writeInt16BE;a.writeInt32LE=BP.writeInt32LE;a.writeInt32BE=BP.writeInt32BE;a.writeFloatLE=BP.writeFloatLE;a.writeFloatBE=
+BP.writeFloatBE;a.writeDoubleLE=BP.writeDoubleLE;a.writeDoubleBE=BP.writeDoubleBE;a.fill=BP.fill;a.inspect=BP.inspect;a.toArrayBuffer=BP.toArrayBuffer;return a};Buffer.stringtrim=function(a){return a.trim?a.trim():a.replace(/^\s+|\s+$/g,"")};Buffer.clamp=function(a,b,c){if("number"!==typeof a)return c;a=~~a;if(a>=b)return b;if(0<=a)return a;a+=b;return 0<=a?a:0};Buffer.coerce=function(a){a=~~Math.ceil(+a);return 0>a?0:a};
+Buffer.isArray=function(a){return(Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)})(a)};Buffer.isArrayish=function(a){return Buffer.isArray(a)||Buffer.isBuffer(a)||a&&"object"===typeof a&&"number"===typeof a.length};Buffer.toHex=function(a){return 16>a?"0"+a.toString(16):a.toString(16)};
+Buffer.utf8ToBytes=function(a){for(var b=[],c=0;c<a.length;c++){var d=a.charCodeAt(c);if(127>=d)b.push(d);else{var e=c;55296<=d&&57343>=d&&c++;d=encodeURIComponent(a.slice(e,c+1)).substr(1).split("%");for(e=0;e<d.length;e++)b.push(parseInt(d[e],16))}}return b};Buffer.asciiToBytes=function(a){for(var b=[],c=0;c<a.length;c++)b.push(a.charCodeAt(c)&255);return b};Buffer.utf16leToBytes=function(a){for(var b,c,d=[],e=0;e<a.length;e++)b=a.charCodeAt(e),c=b>>8,b%=256,d.push(b),d.push(c);return d};
+Buffer.base64ToBytes=function(a){return base64.toByteArray(a)};Buffer.blitBuffer=function(a,b,c,d){for(var e=0;e<d&&!(e+c>=b.length||e>=a.length);e++)b[e+c]=a[e];return e};Buffer.decodeUtf8Char=function(a){try{return decodeURIComponent(a)}catch(b){return String.fromCharCode(65533)}};
+Buffer.verifuint=function(a,b){Buffer.assert("number"===typeof a,"cannot write a non-number as a number");Buffer.assert(0<=a,"specified a negative value for writing an unsigned value");Buffer.assert(a<=b,"value is larger than maximum value for type");Buffer.assert(Math.floor(a)===a,"value has a fractional component")};
+Buffer.verifsint=function(a,b,c){Buffer.assert("number"===typeof a,"cannot write a non-number as a number");Buffer.assert(a<=b,"value larger than maximum allowed value");Buffer.assert(a>=c,"value smaller than minimum allowed value");Buffer.assert(Math.floor(a)===a,"value has a fractional component")};Buffer.verifIEEE754=function(a,b,c){Buffer.assert("number"===typeof a,"cannot write a non-number as a number");Buffer.assert(a<=b,"value larger than maximum allowed value");Buffer.assert(a>=c,"value smaller than minimum allowed value")};
+Buffer.assert=function(a,b){if(!a)throw Error(b||"Failed assertion");};var Log=function(){};exports.Log=Log;Log.LOG=0;var printStackTrace=require("../../contrib/stacktrace/stacktrace.js").printStackTrace,NdnCommon={};exports.NdnCommon=NdnCommon;NdnCommon.MAX_NDN_PACKET_SIZE=8800;NdnCommon.getErrorWithStackTrace=function(a){return a+"\n"+printStackTrace({e:a}).join("\n")};
+NdnCommon.checkIndexedDb=function(a){try{var b=new Dexie("test-Dexie-support");b.version(1).stores({});b.open();setTimeout(function(){try{a(b.isOpen())}catch(c){a(!1)}},200)}catch(c){a(!1)}};var NdnCommon=require("./ndn-common.js").NdnCommon,ExponentialReExpress=function(a,b,c,d){d=d||{};this.face=a;this.callerOnData=b;this.callerOnTimeout=c;this.maxInterestLifetime=d.maxInterestLifetime||16E3};exports.ExponentialReExpress=ExponentialReExpress;
+ExponentialReExpress.makeOnTimeout=function(a,b,c,d){var e=new ExponentialReExpress(a,b,c,d);return function(a){e.onTimeout(a)}};
+ExponentialReExpress.prototype.onTimeout=function(a){var b=a.getInterestLifetimeMilliseconds();if(null==b){if(this.callerOnTimeout)try{this.callerOnTimeout(a)}catch(c){console.log("Error in onTimeout: "+NdnCommon.getErrorWithStackTrace(c))}}else if(b*=2,b>this.maxInterestLifetime){if(this.callerOnTimeout)try{this.callerOnTimeout(a)}catch(d){console.log("Error in onTimeout: "+NdnCommon.getErrorWithStackTrace(d))}}else{a=a.clone();a.setInterestLifetimeMilliseconds(b);var e=this;this.face.expressInterest(a,
+this.callerOnData,function(a){e.onTimeout(a)})}};var Blob=function Blob(b,c){null==c&&(c=!0);null==b?this.buffer=null:"object"===typeof b&&b instanceof Blob?this.buffer=b.buffer:"string"===typeof b?this.buffer=new Buffer(b,"utf8"):c?this.buffer=new Buffer(b):Buffer.isBuffer(b)?this.buffer=b:this.buffer=new Buffer(b);this.length=null!=this.buffer?this.buffer.length:0};exports.Blob=Blob;Blob.prototype.size=function(){return null!=this.buffer?this.buffer.length:0};Blob.prototype.buf=function(){return this.buffer};
+Blob.prototype.isNull=function(){return null==this.buffer};Blob.prototype.toHex=function(){return null==this.buffer?"":this.buffer.toString("hex")};Blob.prototype.toString=function(){return null==this.buffer?"":this.buffer.toString("utf8")};Blob.prototype.equals=function(a){if(this.isNull())return a.isNull();if(a.isNull()||this.buffer.length!=a.buffer.length)return!1;for(var b=0;b<this.buffer.length;++b)if(this.buffer[b]!=a.buffer[b])return!1;return!0};
+var Blob=require("./blob.js").Blob,SignedBlob=function SignedBlob(b,c,d){Blob.call(this,b);null==this.buffer?this.signedPortionEndOffset=this.signedPortionBeginOffset=0:"object"===typeof b&&b instanceof SignedBlob?(this.signedPortionBeginOffset=null==c?b.signedPortionBeginOffset:c,this.signedPortionEndOffset=null==d?b.signedPortionEndOffset:d):(this.signedPortionBeginOffset=c||0,this.signedPortionEndOffset=d||0);this.signedBuffer=null==this.buffer?null:this.buffer.slice(this.signedPortionBeginOffset,
+this.signedPortionEndOffset)};SignedBlob.prototype=new Blob;SignedBlob.prototype.name="SignedBlob";exports.SignedBlob=SignedBlob;SignedBlob.prototype.signedSize=function(){return null!=this.signedBuffer?this.signedBuffer.length:0};SignedBlob.prototype.signedBuf=function(){return this.signedBuffer};SignedBlob.prototype.getSignedPortionBeginOffset=function(){return this.signedPortionBeginOffset};SignedBlob.prototype.getSignedPortionEndOffset=function(){return this.signedPortionEndOffset};
+var DynamicBuffer=function(a){a||(a=16);this.array=new Buffer(a)};exports.DynamicBuffer=DynamicBuffer;DynamicBuffer.prototype.ensureLength=function(a){if(!(this.array.length>=a)){var b=2*this.array.length;a>b&&(b=a);a=new Buffer(b);this.array.copy(a);this.array=a}};DynamicBuffer.prototype.copy=function(a,b){this.ensureLength(a.length+b);Buffer.isBuffer(a)?a.copy(this.array,b):(new Buffer(a)).copy(this.array,b);return b+a.length};
+DynamicBuffer.prototype.ensureLengthFromBack=function(a){if(!(this.array.length>=a)){var b=2*this.array.length;a>b&&(b=a);a=new Buffer(b);this.array.copy(a,a.length-this.array.length);this.array=a}};DynamicBuffer.prototype.copyFromBack=function(a,b){this.ensureLengthFromBack(b);Buffer.isBuffer(a)?a.copy(this.array,this.array.length-b):(new Buffer(a)).copy(this.array,this.array.length-b)};DynamicBuffer.prototype.slice=function(a,b){return void 0==b?this.array.slice(a):this.array.slice(a,b)};
+var ChangeCounter=function(a){this.target=a;this.changeCount=null==a?0:a.getChangeCount()};exports.ChangeCounter=ChangeCounter;ChangeCounter.prototype.get=function(){return this.target};ChangeCounter.prototype.set=function(a){this.target=a;this.changeCount=null==a?0:a.getChangeCount()};ChangeCounter.prototype.checkChanged=function(){if(null==this.target)return!1;var a=this.target.getChangeCount();return this.changeCount!=a?(this.changeCount=a,!0):!1};
+var NdnCommon=require("./ndn-common.js").NdnCommon,SyncPromise=function(a,b){this.value=a;this.isRejected=b};exports.SyncPromise=SyncPromise;SyncPromise.prototype.then=function(a,b){if(this.isRejected)if(b)try{return b(this.value)}catch(c){return new SyncPromise(c,!0)}else return this;else if(a)try{return a(this.value)}catch(d){return new SyncPromise(d,!0)}else return this};SyncPromise.prototype["catch"]=function(a){return this.then(void 0,a)};
+SyncPromise.resolve=function(a){return new SyncPromise(a,!1)};SyncPromise.reject=function(a){return new SyncPromise(a,!0)};SyncPromise.getValue=function(a){if(a instanceof SyncPromise){if(a.isRejected)throw a.value;return a.value}throw Error("Cannot return immediately because promise is not a SyncPromise");};
+SyncPromise.complete=function(a,b,c){var d;c?d=b:(c=b,d=null);if(a)c.then(function(b){try{a(b)}catch(c){console.log("Error in onComplete: "+NdnCommon.getErrorWithStackTrace(c))}},function(a){if(d)try{d(a)}catch(b){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(b))}else{if(c instanceof SyncPromise)throw a;console.log("Uncaught exception from a Promise: "+NdnCommon.getErrorWithStackTrace(a))}});else return SyncPromise.getValue(c)};var DataUtils={};exports.DataUtils=DataUtils;
+DataUtils.keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";DataUtils.stringtoBase64=function(a){var b="",c,d,e="",f,g,h="",k=0;do c=a.charCodeAt(k++),d=a.charCodeAt(k++),e=a.charCodeAt(k++),f=c>>2,c=(c&3)<<4|d>>4,g=(d&15)<<2|e>>6,h=e&63,isNaN(d)?g=h=64:isNaN(e)&&(h=64),b=b+DataUtils.keyStr.charAt(f)+DataUtils.keyStr.charAt(c)+DataUtils.keyStr.charAt(g)+DataUtils.keyStr.charAt(h);while(k<a.length);return b};
+DataUtils.base64toString=function(a){var b="",c,d,e="",f,g="",h=0;/[^A-Za-z0-9\+\/\=]/g.exec(a)&&alert("There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\nExpect errors in decoding.");a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do c=DataUtils.keyStr.indexOf(a.charAt(h++)),d=DataUtils.keyStr.indexOf(a.charAt(h++)),f=DataUtils.keyStr.indexOf(a.charAt(h++)),g=DataUtils.keyStr.indexOf(a.charAt(h++)),c=c<<2|d>>4,d=(d&15)<<4|f>>2,e=(f&3)<<6|g,
+b+=String.fromCharCode(c),64!=f&&(b+=String.fromCharCode(d)),64!=g&&(b+=String.fromCharCode(e));while(h<a.length);return b};DataUtils.toHex=function(a){return a.toString("hex")};DataUtils.stringToHex=function(a){for(var b="",c=0;c<a.length;++c)var d=a.charCodeAt(c),b=b+((16>d?"0":"")+d.toString(16));return b};DataUtils.toString=function(a){return a.toString("binary")};DataUtils.toNumbers=function(a){return new Buffer(a,"hex")};
+DataUtils.hexToRawString=function(a){if("string"==typeof a){var b="";a.replace(/(..)/g,function(a){b+=String.fromCharCode(parseInt(a,16))});return b}};DataUtils.toNumbersFromString=function(a){return new Buffer(a,"binary")};DataUtils.toNumbersIfString=function(a){return"string"===typeof a?new Buffer(a,"binary"):a};DataUtils.stringToUtf8Array=function(a){return new Buffer(a,"utf8")};DataUtils.concatArrays=function(a){return Buffer.concat(a)};
+DataUtils.decodeUtf8=function(a){for(var b="",c=0,d=0,e=0;c<a.length;)if(d=a.charCodeAt(c),128>d)b+=String.fromCharCode(d),c++;else if(191<d&&224>d)e=a.charCodeAt(c+1),b+=String.fromCharCode((d&31)<<6|e&63),c+=2;else var e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b=b+String.fromCharCode((d&15)<<12|(e&63)<<6|f&63),c=c+3;return b};
+DataUtils.arraysEqual=function(a,b){if(!a.slice)throw Error("DataUtils.arraysEqual: a1 is not an array");if(!b.slice)throw Error("DataUtils.arraysEqual: a2 is not an array");if(a.length!=b.length)return!1;for(var c=0;c<a.length;++c)if(a[c]!=b[c])return!1;return!0};DataUtils.bigEndianToUnsignedInt=function(a){for(var b=0,c=0;c<a.length;++c)b*=256,b+=a[c];return b};
+DataUtils.nonNegativeIntToBigEndian=function(a){a=Math.round(a);if(0>=a)return new Buffer(0);for(var b=new Buffer(8),c=0;0!=a;)++c,b[8-c]=a&255,a=Math.floor(a/256);return b.slice(8-c,8)};DataUtils.shuffle=function(a){for(var b=a.length-1;1<=b;--b){var c=Math.floor(Math.random()*(b+1)),d=a[b];a[b]=a[c];a[c]=d}};DataUtils.privateKeyPemToDer=function(a){a=a.split("\n");for(var b="",c=1;c<a.length-1;c++)b+=a[c];return new Buffer(b,"base64")};
+function DecodingException(a){if(a)return a.__proto__=DecodingException.prototype,a}DecodingException.prototype=Error();DecodingException.prototype.name="DecodingException";exports.DecodingException=DecodingException;var Tlv=function(){};exports.Tlv=Tlv;Tlv.Interest=5;Tlv.Data=6;Tlv.Name=7;Tlv.ImplicitSha256DigestComponent=1;Tlv.NameComponent=8;Tlv.Selectors=9;Tlv.Nonce=10;Tlv.InterestLifetime=12;Tlv.MinSuffixComponents=13;Tlv.MaxSuffixComponents=14;Tlv.PublisherPublicKeyLocator=15;Tlv.Exclude=16;
+Tlv.ChildSelector=17;Tlv.MustBeFresh=18;Tlv.Any=19;Tlv.MetaInfo=20;Tlv.Content=21;Tlv.SignatureInfo=22;Tlv.SignatureValue=23;Tlv.ContentType=24;Tlv.FreshnessPeriod=25;Tlv.FinalBlockId=26;Tlv.SignatureType=27;Tlv.KeyLocator=28;Tlv.KeyLocatorDigest=29;Tlv.SelectedDelegation=32;Tlv.FaceInstance=128;Tlv.ForwardingEntry=129;Tlv.StatusResponse=130;Tlv.Action=131;Tlv.FaceID=132;Tlv.IPProto=133;Tlv.Host=134;Tlv.Port=135;Tlv.MulticastInterface=136;Tlv.MulticastTTL=137;Tlv.ForwardingFlags=138;
+Tlv.StatusCode=139;Tlv.StatusText=140;Tlv.SignatureType_DigestSha256=0;Tlv.SignatureType_SignatureSha256WithRsa=1;Tlv.SignatureType_SignatureSha256WithEcdsa=3;Tlv.SignatureType_SignatureHmacWithSha256=4;Tlv.ContentType_Default=0;Tlv.ContentType_Link=1;Tlv.ContentType_Key=2;Tlv.NfdCommand_ControlResponse=101;Tlv.NfdCommand_StatusCode=102;Tlv.NfdCommand_StatusText=103;Tlv.ControlParameters_ControlParameters=104;Tlv.ControlParameters_FaceId=105;Tlv.ControlParameters_Uri=114;
+Tlv.ControlParameters_LocalControlFeature=110;Tlv.ControlParameters_Origin=111;Tlv.ControlParameters_Cost=106;Tlv.ControlParameters_Flags=108;Tlv.ControlParameters_Strategy=107;Tlv.ControlParameters_ExpirationPeriod=109;Tlv.LpPacket_LpPacket=100;Tlv.LpPacket_Fragment=80;Tlv.LpPacket_Sequence=81;Tlv.LpPacket_FragIndex=82;Tlv.LpPacket_FragCount=83;Tlv.LpPacket_Nack=800;Tlv.LpPacket_NackReason=801;Tlv.LpPacket_NextHopFaceId=816;Tlv.LpPacket_IncomingFaceId=817;Tlv.LpPacket_CachePolicy=820;
+Tlv.LpPacket_CachePolicyType=821;Tlv.LpPacket_IGNORE_MIN=800;Tlv.LpPacket_IGNORE_MAX=959;Tlv.Link_Preference=30;Tlv.Link_Delegation=31;Tlv.Encrypt_EncryptedContent=130;Tlv.Encrypt_EncryptionAlgorithm=131;Tlv.Encrypt_EncryptedPayload=132;Tlv.Encrypt_InitialVector=133;Tlv.Encrypt_StartDate=134;Tlv.Encrypt_EndDate=135;Tlv.Encrypt_IntervalStartHour=136;Tlv.Encrypt_IntervalEndHour=137;Tlv.Encrypt_NRepeats=138;Tlv.Encrypt_RepeatUnit=139;Tlv.Encrypt_RepetitiveInterval=140;Tlv.Encrypt_WhiteIntervalList=141;
+Tlv.Encrypt_BlackIntervalList=142;Tlv.Encrypt_Schedule=143;Tlv.getHighBytes=function(a){return(a-a%4294967296)/4294967296};var DynamicBuffer=require("../../util/dynamic-buffer.js").DynamicBuffer,Tlv=require("./tlv.js").Tlv,TlvEncoder=function(a){this.output=new DynamicBuffer(a||16);this.length=0};exports.TlvEncoder=TlvEncoder;TlvEncoder.prototype.getLength=function(){return this.length};
+TlvEncoder.prototype.writeVarNumber=function(a){if(253>a)this.length+=1,this.output.ensureLengthFromBack(this.length),this.output.array[this.output.array.length-this.length]=a&255;else if(65535>=a){this.length+=3;this.output.ensureLengthFromBack(this.length);var b=this.output.array.length-this.length;this.output.array[b]=253;this.output.array[b+1]=a>>8&255;this.output.array[b+2]=a&255}else if(4294967295>=a)this.length+=5,this.output.ensureLengthFromBack(this.length),b=this.output.array.length-this.length,
+this.output.array[b]=254,this.output.array[b+1]=a>>24&255,this.output.array[b+2]=a>>16&255,this.output.array[b+3]=a>>8&255,this.output.array[b+4]=a&255;else{this.length+=9;this.output.ensureLengthFromBack(this.length);b=this.output.array.length-this.length;this.output.array[b]=255;var c=Tlv.getHighBytes(a);this.output.array[b+1]=c>>24&255;this.output.array[b+2]=c>>16&255;this.output.array[b+3]=c>>8&255;this.output.array[b+4]=c&255;this.output.array[b+5]=a>>24&255;this.output.array[b+6]=a>>16&255;
+this.output.array[b+7]=a>>8&255;this.output.array[b+8]=a&255}};TlvEncoder.prototype.writeTypeAndLength=function(a,b){this.writeVarNumber(b);this.writeVarNumber(a)};
+TlvEncoder.prototype.writeNonNegativeInteger=function(a){if(0>a)throw Error("TLV integer value may not be negative");a=Math.round(a);if(255>=a)this.length+=1,this.output.ensureLengthFromBack(this.length),this.output.array[this.output.array.length-this.length]=a&255;else if(65535>=a){this.length+=2;this.output.ensureLengthFromBack(this.length);var b=this.output.array.length-this.length;this.output.array[b]=a>>8&255;this.output.array[b+1]=a&255}else if(4294967295>=a)this.length+=4,this.output.ensureLengthFromBack(this.length),
+b=this.output.array.length-this.length,this.output.array[b]=a>>24&255,this.output.array[b+1]=a>>16&255,this.output.array[b+2]=a>>8&255,this.output.array[b+3]=a&255;else{this.length+=8;this.output.ensureLengthFromBack(this.length);var b=this.output.array.length-this.length,c=Tlv.getHighBytes(a);this.output.array[b]=c>>24&255;this.output.array[b+1]=c>>16&255;this.output.array[b+2]=c>>8&255;this.output.array[b+3]=c&255;this.output.array[b+4]=a>>24&255;this.output.array[b+5]=a>>16&255;this.output.array[b+
+6]=a>>8&255;this.output.array[b+7]=a&255}};TlvEncoder.prototype.writeNonNegativeIntegerTlv=function(a,b){var c=this.length;this.writeNonNegativeInteger(b);this.writeTypeAndLength(a,this.length-c)};TlvEncoder.prototype.writeOptionalNonNegativeIntegerTlv=function(a,b){null!=b&&0<=b&&this.writeNonNegativeIntegerTlv(a,b)};TlvEncoder.prototype.writeBuffer=function(a){null!=a&&(this.length+=a.length,this.output.copyFromBack(a,this.length))};
+TlvEncoder.prototype.writeBlobTlv=function(a,b){null==b?this.writeTypeAndLength(a,0):(this.writeBuffer(b),this.writeTypeAndLength(a,b.length))};TlvEncoder.prototype.writeOptionalBlobTlv=function(a,b){null!=b&&0<b.length&&this.writeBlobTlv(a,b)};TlvEncoder.prototype.getOutput=function(){return this.output.array.slice(this.output.array.length-this.length)};var DecodingException=require("../decoding-exception.js").DecodingException,TlvDecoder=function(a){this.input=a;this.offset=0};
+exports.TlvDecoder=TlvDecoder;TlvDecoder.prototype.readVarNumber=function(){var a=this.input[this.offset];this.offset+=1;return 253>a?a:this.readExtendedVarNumber(a)};
+TlvDecoder.prototype.readExtendedVarNumber=function(a){253==a?(a=(this.input[this.offset]<<8)+this.input[this.offset+1],this.offset+=2):254==a?(a=Math.abs(this.input[this.offset]<<24)+(this.input[this.offset+1]<<16)+(this.input[this.offset+2]<<8)+this.input[this.offset+3],this.offset+=4):(a=4294967296*(Math.abs(this.input[this.offset]<<24)+(this.input[this.offset+1]<<16)+(this.input[this.offset+2]<<8)+this.input[this.offset+3])+(this.input[this.offset+4]<<24)+(this.input[this.offset+5]<<16)+(this.input[this.offset+
+6]<<8)+this.input[this.offset+7],this.offset+=8);return a};TlvDecoder.prototype.readTypeAndLength=function(a){if(this.readVarNumber()!=a)throw new DecodingException(Error("Did not get the expected TLV type"));a=this.readVarNumber();if(this.offset+a>this.input.length)throw new DecodingException(Error("TLV length exceeds the buffer length"));return a};TlvDecoder.prototype.readNestedTlvsStart=function(a){return this.readTypeAndLength(a)+this.offset};
+TlvDecoder.prototype.finishNestedTlvs=function(a){if(this.offset!=a){for(;this.offset<a;){this.readVarNumber();var b=this.readVarNumber();this.offset+=b;if(this.offset>this.input.length)throw new DecodingException(Error("TLV length exceeds the buffer length"));}if(this.offset!=a)throw new DecodingException(Error("TLV length does not equal the total length of the nested TLVs"));}};
+TlvDecoder.prototype.peekType=function(a,b){if(this.offset>=b)return!1;var c=this.offset,d=this.readVarNumber();this.offset=c;return d==a};
+TlvDecoder.prototype.readNonNegativeInteger=function(a){var b;if(1==a)b=this.input[this.offset];else if(2==a)b=(this.input[this.offset]<<8)+this.input[this.offset+1];else if(4==a)b=Math.abs(this.input[this.offset]<<24)+(this.input[this.offset+1]<<16)+(this.input[this.offset+2]<<8)+this.input[this.offset+3];else if(8==a)b=4294967296*(Math.abs(this.input[this.offset]<<24)+(this.input[this.offset+1]<<16)+(this.input[this.offset+2]<<8)+this.input[this.offset+3])+Math.abs(this.input[this.offset+4]<<24)+
+(this.input[this.offset+5]<<16)+(this.input[this.offset+6]<<8)+this.input[this.offset+7];else throw new DecodingException(Error("Invalid length for a TLV nonNegativeInteger"));this.offset+=a;return b};TlvDecoder.prototype.readNonNegativeIntegerTlv=function(a){a=this.readTypeAndLength(a);return this.readNonNegativeInteger(a)};TlvDecoder.prototype.readOptionalNonNegativeIntegerTlv=function(a,b){return this.peekType(a,b)?this.readNonNegativeIntegerTlv(a):null};
+TlvDecoder.prototype.readBlobTlv=function(a){a=this.readTypeAndLength(a);var b=this.input.slice(this.offset,this.offset+a);this.offset+=a;return b};TlvDecoder.prototype.readOptionalBlobTlv=function(a,b){return this.peekType(a,b)?this.readBlobTlv(a):null};TlvDecoder.prototype.readBooleanTlv=function(a,b){if(this.peekType(a,b)){var c=this.readTypeAndLength(a);this.offset+=c;return!0}return!1};TlvDecoder.prototype.getOffset=function(){return this.offset};
+TlvDecoder.prototype.seek=function(a){this.offset=a};TlvDecoder.prototype.getSlice=function(a,b){return this.input.slice(a,b)};var TlvDecoder=require("./tlv-decoder.js").TlvDecoder,TlvStructureDecoder=function TlvStructureDecoder(){this.gotElementEnd_=!1;this.offset_=0;this.state_=TlvStructureDecoder.READ_TYPE;this.headerLength_=0;this.useHeaderBuffer_=!1;this.headerBuffer_=new Buffer(8);this.nBytesToRead_=0};exports.TlvStructureDecoder=TlvStructureDecoder;TlvStructureDecoder.READ_TYPE=0;
+TlvStructureDecoder.READ_TYPE_BYTES=1;TlvStructureDecoder.READ_LENGTH=2;TlvStructureDecoder.READ_LENGTH_BYTES=3;TlvStructureDecoder.READ_VALUE_BYTES=4;
+TlvStructureDecoder.prototype.findElementEnd=function(a){if(this.gotElementEnd_)return!0;for(var b=new TlvDecoder(a);;){if(this.offset_>=a.length)return!1;if(this.state_==TlvStructureDecoder.READ_TYPE){var c=a[this.offset_];this.offset_+=1;253>c?this.state_=TlvStructureDecoder.READ_LENGTH:(this.nBytesToRead_=253==c?2:254==c?4:8,this.state_=TlvStructureDecoder.READ_TYPE_BYTES)}else if(this.state_==TlvStructureDecoder.READ_TYPE_BYTES){c=a.length-this.offset_;if(c<this.nBytesToRead_)return this.offset_+=
+c,this.nBytesToRead_-=c,!1;this.offset_+=this.nBytesToRead_;this.state_=TlvStructureDecoder.READ_LENGTH}else if(this.state_==TlvStructureDecoder.READ_LENGTH)if(c=a[this.offset_],this.offset_+=1,253>c){this.nBytesToRead_=c;if(0==this.nBytesToRead_)return this.gotElementEnd_=!0;this.state_=TlvStructureDecoder.READ_VALUE_BYTES}else this.nBytesToRead_=253==c?2:254==c?4:8,this.firstOctet_=c,this.state_=TlvStructureDecoder.READ_LENGTH_BYTES;else if(this.state_==TlvStructureDecoder.READ_LENGTH_BYTES){c=
+a.length-this.offset_;if(!this.useHeaderBuffer_&&c>=this.nBytesToRead_)b.seek(this.offset_),this.nBytesToRead_=b.readExtendedVarNumber(this.firstOctet_),this.offset_=b.getOffset();else{this.useHeaderBuffer_=!0;var d=this.nBytesToRead_-this.headerLength_;if(d>c){if(this.headerLength_+c>this.headerBuffer_.length)throw Error("Cannot store more header bytes than the size of headerBuffer");a.slice(this.offset_,this.offset_+c).copy(this.headerBuffer_,this.headerLength_);this.offset_+=c;this.headerLength_+=
+c;return!1}if(this.headerLength_+d>this.headerBuffer_.length)throw Error("Cannot store more header bytes than the size of headerBuffer");a.slice(this.offset_,this.offset_+d).copy(this.headerBuffer_,this.headerLength_);this.offset_+=d;this.nBytesToRead_=(new TlvDecoder(this.headerBuffer_)).readExtendedVarNumber(this.firstOctet_)}if(0==this.nBytesToRead_)return this.gotElementEnd_=!0;this.state_=TlvStructureDecoder.READ_VALUE_BYTES}else{if(this.state_==TlvStructureDecoder.READ_VALUE_BYTES){c=a.length-
+this.offset_;if(c<this.nBytesToRead_)return this.offset_+=c,this.nBytesToRead_-=c,!1;this.offset_+=this.nBytesToRead_;return this.gotElementEnd_=!0}throw Error("findElementEnd: unrecognized state");}}};TlvStructureDecoder.prototype.getOffset=function(){return this.offset_};TlvStructureDecoder.prototype.seek=function(a){this.offset_=a};
+var TlvEncoder=require("./tlv/tlv-encoder.js").TlvEncoder,TlvDecoder=require("./tlv/tlv-decoder.js").TlvDecoder,Blob=require("../util/blob.js").Blob,Name=require("../name.js").Name,ProtobufTlv=function(){};exports.ProtobufTlv=ProtobufTlv;ProtobufTlv._Field=null;ProtobufTlv.establishField=function(){if(null===ProtobufTlv._Field)try{ProtobufTlv._Field=dcodeIO.ProtoBuf.Reflect.Message.Field}catch(a){ProtobufTlv._Field=require("protobufjs").Reflect.Message.Field}};
+ProtobufTlv.encode=function(a,b){ProtobufTlv.establishField();a.encodeAB();var c=new TlvEncoder;ProtobufTlv._encodeMessageValue(a,b,c);return new Blob(c.getOutput(),!1)};ProtobufTlv.decode=function(a,b,c){ProtobufTlv.establishField();c="object"===typeof c&&c instanceof Blob?c.buf():c;var d=new TlvDecoder(c);ProtobufTlv._decodeMessageValue(a,b,d,c.length)};
+ProtobufTlv._encodeMessageValue=function(a,b,c){b=b.getChildren(ProtobufTlv._Field);for(var d=b.length-1;0<=d;--d){var e=b[d],f=e.id,g;if(e.repeated)g=a[e.name];else if(null!=a[e.name])g=[a[e.name]];else continue;for(var h=g.length-1;0<=h;--h){var k=g[h];if("message"==e.type.name){var l=c.getLength();ProtobufTlv._encodeMessageValue(k,e.resolvedType,c);c.writeTypeAndLength(f,c.getLength()-l)}else if("uint32"==e.type.name||"uint64"==e.type.name)c.writeNonNegativeIntegerTlv(f,k);else if("enum"==e.type.name){if(0>
+k)throw Error("ProtobufTlv::encode: ENUM value may not be negative");c.writeNonNegativeIntegerTlv(f,k)}else if("bytes"==e.type.name)l=k.toBuffer(),void 0==l.length&&(l=new Uint8Array(k.toArrayBuffer())),c.writeBlobTlv(f,l);else if("string"==e.type.name)c.writeBlobTlv(f,(new Blob(k,!1)).buf());else if("bool"==e.type.name)k&&c.writeTypeAndLength(f,0);else if("double"==e.type.name)l=new Buffer(8),l.writeDoubleLE(k,0),c.writeBlobTlv(f,l);else throw Error("ProtobufTlv::encode: Unknown field type");}}};
+ProtobufTlv._decodeMessageValue=function(a,b,c,d){b=b.getChildren(ProtobufTlv._Field);for(var e=0;e<b.length;++e){var f=b[e],g=f.id;if(f.required||c.peekType(g,d))if(f.repeated)for(;c.peekType(g,d);)if("message"==f.type.name){var h=c.readNestedTlvsStart(g),k=new (f.resolvedType.build());a.add(f.name,k);ProtobufTlv._decodeMessageValue(k,f.resolvedType,c,h);c.finishNestedTlvs(h)}else a.add(f.name,ProtobufTlv._decodeFieldValue(f,g,c,d));else"message"==f.type.name?(h=c.readNestedTlvsStart(g),k=new (f.resolvedType.build()),
+a.set(f.name,k),ProtobufTlv._decodeMessageValue(k,f.resolvedType,c,h),c.finishNestedTlvs(h)):a.set(f.name,ProtobufTlv._decodeFieldValue(f,g,c,d))}};
+ProtobufTlv._decodeFieldValue=function(a,b,c,d){if("uint32"==a.type.name||"uint64"==a.type.name||"enum"==a.type.name)return c.readNonNegativeIntegerTlv(b);if("bytes"==a.type.name)return c.readBlobTlv(b);if("string"==a.type.name)return c.readBlobTlv(b).toString();if("bool"==a.type.name)return c.readBooleanTlv(b,d);if("double"==a.type.name)return c.readBlobTlv(b).readDoubleLE(0);throw Error("ProtobufTlv.decode: Unknown field type");};
+ProtobufTlv.toName=function(a){for(var b=new Name,c=0;c<a.length;++c)b.append(new Blob(new Buffer(a[c].toBinary(),"binary")),!1);return b};var OID=function(a){if("string"===typeof a){a=a.split(".");this.oid=[];for(var b=0;b<a.length;++b)this.oid.push(parseInt(a[b]))}else this.oid=a.slice(0,a.length)};exports.OID=OID;OID.prototype.getIntegerList=function(){return this.oid};OID.prototype.setIntegerList=function(a){this.oid=a.slice(0,a.length)};
+OID.prototype.toString=function(){for(var a="",b=0;b<this.oid.length;++b)0!==b&&(a+="."),a+=this.oid[b];return a};OID.prototype.equals=function(a){if(!(a instanceof OID)||this.oid.length!==a.oid.length)return!1;for(var b=0;b<this.oid.length;++b)if(this.oid[b]!=a.oid[b])return!1;return!0};var WireFormat=function(){};exports.WireFormat=WireFormat;WireFormat.prototype.encodeName=function(a){throw Error("encodeName is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeName=function(a,b,c){throw Error("decodeName is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeInterest=function(a){throw Error("encodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.decodeInterest=function(a,b,c){throw Error("decodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.encodeData=function(a){throw Error("encodeData is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.decodeData=function(a,b,c){throw Error("decodeData is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeControlParameters=function(a){throw Error("encodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeControlParameters=function(a,b,c){throw Error("decodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeControlResponse=function(a){throw Error("encodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeControlResponse=function(a,b,c){throw Error("decodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeSignatureInfo=function(a){throw Error("encodeSignatureInfo is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeSignatureInfoAndValue=function(a,b,c){throw Error("decodeSignatureInfoAndValue is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeSignatureValue=function(a){throw Error("encodeSignatureValue is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeLpPacket=function(a,b,c){throw Error("decodeLpPacket is unimplemented in the base WireFormat class. You should use a derived class.");};WireFormat.prototype.encodeDelegationSet=function(a){throw Error("encodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");};
+WireFormat.prototype.decodeDelegationSet=function(a,b,c){throw Error("decodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");};WireFormat.prototype.encodeEncryptedContent=function(a){throw Error("encodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");};
+WireFormat.prototype.decodeEncryptedContent=function(a,b,c){throw Error("decodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");};WireFormat.setDefaultWireFormat=function(a){WireFormat.defaultWireFormat=a};WireFormat.getDefaultWireFormat=function(){return WireFormat.defaultWireFormat};
+var TlvWireFormat=require("./tlv-wire-format.js").TlvWireFormat,DataUtils=require("./data-utils.js").DataUtils,Tlv=require("./tlv/tlv.js").Tlv,TlvStructureDecoder=require("./tlv/tlv-structure-decoder.js").TlvStructureDecoder,DecodingException=require("./decoding-exception.js").DecodingException,NdnCommon=require("../util/ndn-common.js").NdnCommon,LOG=require("../log.js").Log.LOG,ElementReader=function(a){this.elementListener_=a;this.dataParts_=[];this.tlvStructureDecoder_=new TlvStructureDecoder};
+exports.ElementReader=ElementReader;
+ElementReader.prototype.onReceivedData=function(a){for(;;){var b,c;try{if(0===this.dataParts_.length&&0>=a.length)break;this.tlvStructureDecoder_.seek(0);b=this.tlvStructureDecoder_.findElementEnd(a);c=this.tlvStructureDecoder_.getOffset()}catch(d){throw this.dataParts_=[],this.tlvStructureDecoder_=new TlvStructureDecoder,d;}if(b){var e;0===this.dataParts_.length?e=a.slice(0,c):(this.dataParts_.push(a.slice(0,c)),e=DataUtils.concatArrays(this.dataParts_),this.dataParts_=[]);a=a.slice(c,a.length);
+this.tlvStructureDecoder_=new TlvStructureDecoder;this.elementListener_.onReceivedElement(e);if(0==a.length)break}else{b=a.length;for(c=0;c<this.dataParts_.length;++c)b+=this.dataParts_[c].length;if(b>NdnCommon.MAX_NDN_PACKET_SIZE)throw this.dataParts_=[],this.tlvStructureDecoder_=new TlvStructureDecoder,new DecodingException(Error("The incoming packet exceeds the maximum limit Face.getMaxNdnPacketSize()"));this.dataParts_.push(new Buffer(a));3<LOG&&console.log("Incomplete packet received. Length "+
+a.length+". Wait for more input.");break}}};function DerDecodingException(a){if(a)return a.__proto__=DerDecodingException.prototype,a}DerDecodingException.prototype=Error();DerDecodingException.prototype.name="DerDecodingException";exports.DerDecodingException=DerDecodingException;function DerEncodingException(a){if(a)return a.__proto__=DerEncodingException.prototype,a}DerEncodingException.prototype=Error();DerEncodingException.prototype.name="DerEncodingException";exports.DerEncodingException=DerEncodingException;
+var DerNodeType=function(){};exports.DerNodeType=DerNodeType;DerNodeType.Eoc=0;DerNodeType.Boolean=1;DerNodeType.Integer=2;DerNodeType.BitString=3;DerNodeType.OctetString=4;DerNodeType.Null=5;DerNodeType.ObjectIdentifier=6;DerNodeType.ObjectDescriptor=7;DerNodeType.External=40;DerNodeType.Real=9;DerNodeType.Enumerated=10;DerNodeType.EmbeddedPdv=43;DerNodeType.Utf8String=12;DerNodeType.RelativeOid=13;DerNodeType.Sequence=48;DerNodeType.Set=49;DerNodeType.NumericString=18;
+DerNodeType.PrintableString=19;DerNodeType.T61String=20;DerNodeType.VideoTexString=21;DerNodeType.Ia5String=22;DerNodeType.UtcTime=23;DerNodeType.GeneralizedTime=24;DerNodeType.GraphicString=25;DerNodeType.VisibleString=26;DerNodeType.GeneralString=27;DerNodeType.UniversalString=28;DerNodeType.CharacterString=29;DerNodeType.BmpString=30;
+var DynamicBuffer=require("../../util/dynamic-buffer.js").DynamicBuffer,Blob=require("../../util/blob.js").Blob,DerDecodingException=require("./der-decoding-exception.js").DerDecodingException,DerEncodingException=require("./der-encoding-exception.js").DerEncodingException,DerNodeType=require("./der-node-type.js").DerNodeType,DerNode=function(a){this.nodeType_=a;this.parent_=null;this.header_=new Buffer(0);this.payload_=new DynamicBuffer(0);this.payloadPosition_=0};exports.DerNode=DerNode;
+DerNode.prototype.getSize=function(){return this.header_.length+this.payloadPosition_};
+DerNode.prototype.encodeHeader=function(a){var b=new DynamicBuffer(10),c=0;b.array[c++]=this.nodeType_;if(0>a)throw Error("encodeHeader: DER object has negative length");if(127>=a)b.array[c++]=a&255;else{var d=new DynamicBuffer(10),e=a;for(a=0;0!=e;)++a,d.ensureLengthFromBack(a),d.array[d.array.length-a]=e&255,e>>=8;e=a+1;d.ensureLengthFromBack(e);d.array[d.array.length-e]=(128|a)&255;b.copy(d.slice(d.array.length-e),c);c+=e}this.header_=b.slice(0,c)};
+DerNode.prototype.decodeHeader=function(a,b){var c=b,d=a[c]&255,c=c+1;this.nodeType_=d;var e=a[c]&255,c=c+1,f=new DynamicBuffer(10),g=0;f.array[g++]=d;d=f.array[g++]=e;if(0!=(e&128))for(e&=127,d=0;0<e;){var h=a[c],c=c+1;f.ensureLength(g+1);f.array[g++]=h;d=256*d+(h&255);e-=1}this.header_=f.slice(0,g);return d};DerNode.prototype.encode=function(){var a=new Buffer(this.getSize());this.header_.copy(a);this.payload_.slice(0,this.payloadPosition_).copy(a,this.header_.length);return new Blob(a,!1)};
+DerNode.prototype.decode=function(a,b){var c=b,d=this.decodeHeader(a,c),e=this.header_.length;0<d&&(c+=e,this.payloadAppend(a.slice(c,c+d)))};DerNode.prototype.payloadAppend=function(a){this.payloadPosition_=this.payload_.copy(a,this.payloadPosition_)};
+DerNode.parse=function(a,b){void 0==b&&(b=0);var c=a[b]&255;if(c===DerNodeType.Boolean)c=new DerNode.DerBoolean;else if(c===DerNodeType.Integer)c=new DerNode.DerInteger;else if(c===DerNodeType.BitString)c=new DerNode.DerBitString;else if(c===DerNodeType.OctetString)c=new DerNode.DerOctetString;else if(c===DerNodeType.Null)c=new DerNode.DerNull;else if(c===DerNodeType.ObjectIdentifier)c=new DerNode.DerOid;else if(c===DerNodeType.Sequence)c=new DerNode.DerSequence;else if(c===DerNodeType.PrintableString)c=
+new DerNode.DerPrintableString;else if(c===DerNodeType.GeneralizedTime)c=new DerNode.DerGeneralizedTime;else throw new DerDecodingException(Error("Unimplemented DER type "+c));c.decode(a,b);return c};DerNode.prototype.toVal=function(){return this.encode()};DerNode.prototype.getPayload=function(){return new Blob(this.payload_.slice(0,this.payloadPosition_),!0)};DerNode.prototype.getChildren=function(){throw new DerDecodingException(Error("getChildren: This DerNode is not DerSequence"));};
+DerNode.getSequence=function(a,b){if(0>b||b>=a.length)throw new DerDecodingException(Error("getSequence: Child index is out of bounds"));if(!(a[b]instanceof DerNode.DerSequence))throw new DerDecodingException(Error("getSequence: Child DerNode is not a DerSequence"));return a[b]};DerNode.DerStructure=function(a){DerNode.call(this,a);this.childChanged_=!1;this.nodeList_=[];this.size_=0};DerNode.DerStructure.prototype=new DerNode;DerNode.DerStructure.prototype.name="DerStructure";
+DerNode.DerStructure.prototype.getSize=function(){this.childChanged_&&(this.updateSize(),this.childChanged_=!1);this.encodeHeader(this.size_);return this.size_+this.header_.length};DerNode.DerStructure.prototype.getChildren=function(){return this.nodeList_};DerNode.DerStructure.prototype.updateSize=function(){for(var a=0,b=0;b<this.nodeList_.length;++b)a+=this.nodeList_[b].getSize();this.size_=a;this.childChanged_=!1};
+DerNode.DerStructure.prototype.addChild=function(a,b){a.parent_=this;this.nodeList_.push(a);b&&null!=this.parent_&&this.parent_.setChildChanged();this.childChanged_=!0};DerNode.DerStructure.prototype.setChildChanged=function(){null!=this.parent_&&this.parent_.setChildChanged();this.childChanged_=!0};
+DerNode.DerStructure.prototype.encode=function(){var a=new DynamicBuffer(10),b=0;this.updateSize();this.encodeHeader(this.size_);for(var b=a.copy(this.header_,b),c=0;c<this.nodeList_.length;++c)var d=this.nodeList_[c].encode(),b=a.copy(d.buf(),b);return new Blob(a.slice(0,b),!1)};DerNode.DerStructure.prototype.decode=function(a,b){var c=b;this.size_=this.decodeHeader(a,c);for(var c=c+this.header_.length,d=0;d<this.size_;){var e=DerNode.parse(a,c),f=e.getSize(),c=c+f,d=d+f;this.addChild(e,!1)}};
+DerNode.DerByteString=function(a,b){DerNode.call(this,b);null!=a&&(this.payloadAppend(a),this.encodeHeader(a.length))};DerNode.DerByteString.prototype=new DerNode;DerNode.DerByteString.prototype.name="DerByteString";DerNode.DerByteString.prototype.toVal=function(){return this.getPayload()};DerNode.DerBoolean=function(a){DerNode.call(this,DerNodeType.Boolean);void 0!=a&&(a=a?255:0,this.payload_.ensureLength(this.payloadPosition_+1),this.payload_.array[this.payloadPosition_++]=a,this.encodeHeader(1))};
+DerNode.DerBoolean.prototype=new DerNode;DerNode.DerBoolean.prototype.name="DerBoolean";DerNode.DerBoolean.prototype.toVal=function(){return 0!=this.payload_.array[0]};
+DerNode.DerInteger=function(a){DerNode.call(this,DerNodeType.Integer);if(void 0!=a){if(Buffer.isBuffer(a)){if(0<a.length&&128<=a[0])throw new DerEncodingException(Error("DerInteger: Negative integers are not currently supported"));0==a.length?this.payloadAppend(new Buffer([0])):this.payloadAppend(a)}else{a=Math.round(a);if(0>a)throw new DerEncodingException(Error("DerInteger: Negative integers are not currently supported"));for(var b=new DynamicBuffer(10),c=0;!(++c,b.ensureLengthFromBack(c),b.array[b.array.length-
+c]=a&255,a>>=8,0>=a););128<=b.array[b.array.length-c]&&(++c,b.ensureLengthFromBack(c),b.array[b.array.length-c]=0);this.payloadAppend(b.slice(b.array.length-c))}this.encodeHeader(this.payloadPosition_)}};DerNode.DerInteger.prototype=new DerNode;DerNode.DerInteger.prototype.name="DerInteger";
+DerNode.DerInteger.prototype.toVal=function(){if(0<this.payloadPosition_&&128<=this.payload_.array[0])throw new DerDecodingException(Error("DerInteger: Negative integers are not currently supported"));for(var a=0,b=0;b<this.payloadPosition_;++b)a<<=8,a+=this.payload_.array[b];return a};DerNode.DerBitString=function(a,b){DerNode.call(this,DerNodeType.BitString);void 0!=a&&(this.payload_.ensureLength(this.payloadPosition_+1),this.payload_.array[this.payloadPosition_++]=b&255,this.payloadAppend(a),this.encodeHeader(this.payloadPosition_))};
+DerNode.DerBitString.prototype=new DerNode;DerNode.DerBitString.prototype.name="DerBitString";DerNode.DerOctetString=function(a){DerNode.DerByteString.call(this,a,DerNodeType.OctetString)};DerNode.DerOctetString.prototype=new DerNode.DerByteString;DerNode.DerOctetString.prototype.name="DerOctetString";DerNode.DerNull=function(){DerNode.call(this,DerNodeType.Null);this.encodeHeader(0)};DerNode.DerNull.prototype=new DerNode;DerNode.DerNull.prototype.name="DerNull";
+DerNode.DerOid=function(a){DerNode.call(this,DerNodeType.ObjectIdentifier);if(void 0!=a)if("string"===typeof a){a=a.split(".");for(var b=[],c=0;c<a.length;++c)b.push(parseInt(a[c]));this.prepareEncoding(b)}else this.prepareEncoding(a.getIntegerList())};DerNode.DerOid.prototype=new DerNode;DerNode.DerOid.prototype.name="DerOid";
+DerNode.DerOid.prototype.prepareEncoding=function(a){var b;if(0==a.length)throw new DerEncodingException(Error("No integer in OID"));if(0<=a[0]&&2>=a[0])b=40*a[0];else throw new DerEncodingException(Error("First integer in OID is out of range"));if(2<=a.length)if(0<=a[1]&&39>=a[1])b+=a[1];else throw new DerEncodingException(Error("Second integer in OID is out of range"));var c=new DynamicBuffer(10),d=0,d=c.copy(DerNode.DerOid.encode128(b),d);if(2<a.length)for(b=2;b<a.length;++b)d=c.copy(DerNode.DerOid.encode128(a[b]),
+d);this.encodeHeader(d);this.payloadAppend(c.slice(0,d))};DerNode.DerOid.encode128=function(a){var b=new DynamicBuffer(10),c=0;if(128>a)++c,b.array[b.array.length-c]=a&127;else for(++c,b.array[b.array.length-c]=a&127,a>>=7;0!=a;)++c,b.ensureLengthFromBack(c),b.array[b.array.length-c]=a&127|128,a>>=7;return b.slice(b.array.length-c)};
+DerNode.DerOid.prototype.decode128=function(a,b){for(var c=0,d=a;0!=(this.payload_.array[a]&128);)c=128*c+(this.payload_.array[a]&255)-128,a+=1;c=128*c+(this.payload_.array[a]&255);b[0]=a-d+1;return c};DerNode.DerOid.prototype.toVal=function(){for(var a=0,b=[];a<this.payloadPosition_;){var c=[0],d=this.decode128(a,c),a=a+c[0];b.push(d)}a=b[0];a=Math.floor(a/40)+"."+a%40;for(c=1;c<b.length;++c)a+="."+b[c];return a};DerNode.DerSequence=function(){DerNode.DerStructure.call(this,DerNodeType.Sequence)};
+DerNode.DerSequence.prototype=new DerNode.DerStructure;DerNode.DerSequence.prototype.name="DerSequence";DerNode.DerPrintableString=function(a){DerNode.DerByteString.call(this,a,DerNodeType.PrintableString)};DerNode.DerPrintableString.prototype=new DerNode.DerByteString;DerNode.DerPrintableString.prototype.name="DerPrintableString";
+DerNode.DerGeneralizedTime=function(a){DerNode.call(this,DerNodeType.GeneralizedTime);void 0!=a&&(a=DerNode.DerGeneralizedTime.toDerTimeString(a),this.payloadAppend((new Blob(a)).buf()),this.encodeHeader(this.payloadPosition_))};DerNode.DerGeneralizedTime.prototype=new DerNode;DerNode.DerGeneralizedTime.prototype.name="DerGeneralizedTime";
+DerNode.DerGeneralizedTime.toDerTimeString=function(a){a=new Date(Math.round(a));return a.getUTCFullYear()+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCMonth()+1)+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCDate())+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCHours())+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCMinutes())+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCSeconds())+"Z"};
+DerNode.DerGeneralizedTime.to2DigitString=function(a){a=a.toString();return 1===a.length?"0"+a:a};DerNode.DerGeneralizedTime.prototype.toVal=function(){var a=this.payload_.slice(0,this.payloadPosition_).toString();return Date.UTC(parseInt(a.substr(0,4)),parseInt(a.substr(4,2)-1),parseInt(a.substr(6,2)),parseInt(a.substr(8,2)),parseInt(a.substr(10,2)),parseInt(a.substr(12,2)))};var fs=require("fs"),BoostInfoTree=function(a,b){this.subtrees=[];this.value=a;this.parent=b;this.lastChild=null};
+BoostInfoTree.prototype.addSubtree=function(a,b){var c=this.find(a);null!==c?c.push(b):this.subtrees.push({key:a,value:[b]});b.parent=this;this.lastChild=b};BoostInfoTree.prototype.createSubtree=function(a,b){var c=new BoostInfoTree(b,this);this.addSubtree(a,c);return c};
+BoostInfoTree.prototype.get=function(a){a=a.replace(/^\/+/,"");if(0===a.length)return[this];var b=a.split("/");a=this.find(b[0]);if(null===a)return[];if(1==b.length)return a.slice(0);for(var b=b.slice(1).join("/"),c=[],d=0;d<a.length;++d)var e=a[d].get(b),c=c.concat(e);return c};BoostInfoTree.prototype.getFirstValue=function(a){a=this.get(a);return 1<=a.length?a[0].value:null};BoostInfoTree.prototype.getValue=function(){return this.value};BoostInfoTree.prototype.getParent=function(){return this.parent};
+BoostInfoTree.prototype.getLastChild=function(){return this.lastChild};
+BoostInfoTree.prototype.prettyPrint=function(a){a=a||1;var b=Array(a+1).join(" "),c="";null!=this.parent&&(this.value&&0<this.value.length&&(c+='"'+this.value+'"'),c+="\n");if(0<this.subtrees.length){this.parent&&(c+=b+"{\n");for(var d=Array(a+2+1).join(" "),e=0;e<this.subtrees.length;++e)for(var f=0;f<this.subtrees[e].value.length;++f)c+=d+this.subtrees[e].key+" "+this.subtrees[e].value[f].prettyPrint(a+2);this.parent&&(c+=b+"}\n")}return c};BoostInfoTree.prototype.toString=function(){return this.prettyPrint()};
+BoostInfoTree.prototype.find=function(a){for(var b=0;b<this.subtrees.length;++b)if(this.subtrees[b].key==a)return this.subtrees[b].value;return null};var BoostInfoParser=function(){this.root=new BoostInfoTree};exports.BoostInfoParser=BoostInfoParser;exports.BoostInfoTree=BoostInfoTree;BoostInfoParser.prototype.read=function(a,b){var c;"string"==typeof b?c=a:(b=a,c=fs.readFileSync(a).toString());var d=this.root,e=this;c.split(/\r?\n/).forEach(function(a){d=e.parseLine(a.trim(),d)})};
+BoostInfoParser.prototype.write=function(a){fs.writeFileSync(a,""+this.root)};BoostInfoParser.prototype.getRoot=function(){return this.root};
+BoostInfoParser.shlex_split=function(a){var b=[];if(""==a)return b;for(var c=0;;){for(;0<=" \t\n\r".indexOf(a[c]);)if(c+=1,c>=a.length)return b;for(var d=c,e=!1,f="";;){if("\\"==a[d]){if(f+=a.substring(c,d),d=c=d+1,d>=a.length)break}else if(e)'"'==a[d]&&(f+=a.substring(c,d),c=d+1,e=!1);else if('"'==a[d])f+=a.substring(c,d),c=d+1,e=!0;else if(0<=" \t\n\r".indexOf(a[d]))break;d+=1;if(d>=a.length)break}f+=a.substring(c,d);b.push(f);if(d>=a.length)return b;c=d}};
+BoostInfoParser.prototype.parseLine=function(a,b){var c=a.indexOf(";");0<=c&&(a=a.substring(0,c).trim());if(0==a.length)return b;for(var c=BoostInfoParser.shlex_split(a),d=!1,e=!1,f=0;f<c.length;++f)d=d||"{"==c[f],e=e||"}"==c[f];if(!d&&!e){var d=c[0],g;1<c.length&&(g=c[1]);b.createSubtree(d,g);return b}c=a.indexOf("{");if(0<c)return g=a.substring(0,c),c=a.substring(c),g=this.parseLine(g,b),this.parseLine(c,g);if("{"==a[0])return b=b.getLastChild();if("}"==a[0])return b=b.getParent();throw runtime_error("BoostInfoParser: input line is malformed");
+};
+var Name=require("../name.js").Name,InterestFilter=require("../interest-filter.js").InterestFilter,ForwardingFlags=require("../forwarding-flags.js").ForwardingFlags,WireFormat=require("../encoding/wire-format.js").WireFormat,LOG=require("../log.js").Log.LOG,MemoryContentCache=function(a,b){b=b||1E3;this.face=a;this.cleanupIntervalMilliseconds=b;this.nextCleanupTime=(new Date).getTime()+b;this.onDataNotFoundForPrefix={};this.interestFilterIdList=[];this.registeredPrefixIdList=[];this.noStaleTimeCache=[];
+this.staleTimeCache=[];this.emptyComponent=new Name.Component;this.pendingInterestTable=[];var c=this;this.storePendingInterestCallback=function(a,b,f,g,h){c.storePendingInterest(b,f)}};exports.MemoryContentCache=MemoryContentCache;
+MemoryContentCache.prototype.registerPrefix=function(a,b,c,d,e,f){var g=c,h=d,k=e;c="object"===typeof g&&1===g.length&&"function"===typeof g[0]?g[0]:null;d="function"===typeof g?g:"function"===typeof h?h:null;e=g instanceof ForwardingFlags?g:h instanceof ForwardingFlags?h:k instanceof ForwardingFlags?k:new ForwardingFlags;f=g instanceof WireFormat?g:h instanceof WireFormat?h:k instanceof WireFormat?k:f instanceof WireFormat?f:WireFormat.getDefaultWireFormat();d&&(this.onDataNotFoundForPrefix[a.toUri()]=
+d);a=this.face.registerPrefix(a,this.onInterest.bind(this),b,c,e,f);this.registeredPrefixIdList.push(a)};MemoryContentCache.prototype.setInterestFilter=function(a,b){if(b){var c;c="object"===typeof a&&a instanceof InterestFilter?a.getPrefix():a;this.onDataNotFoundForPrefix[c.toUri()]=b}c=this.face.setInterestFilter(a,this.onInterest.bind(this));this.interestFilterIdList.push(c)};
+MemoryContentCache.prototype.unregisterAll=function(){for(var a=0;a<this.interestFilterIdList.length;++a)this.face.unsetInterestFilter(this.interestFilterIdList[a]);this.interestFilterIdList=[];for(a=0;a<this.registeredPrefixIdList.length;++a)this.face.removeRegisteredPrefix(this.registeredPrefixIdList[a]);this.registeredPrefixIdList=[];this.onDataNotFoundForPrefix={}};
+MemoryContentCache.prototype.add=function(a){this.doCleanup();if(null!=a.getMetaInfo().getFreshnessPeriod()&&0<=a.getMetaInfo().getFreshnessPeriod()){for(var b=new MemoryContentCache.StaleTimeContent(a),c=this.staleTimeCache.length-1;0<=c&&!(this.staleTimeCache[c].staleTimeMilliseconds<=b.staleTimeMilliseconds);)--c;this.staleTimeCache.splice(c+1,0,b)}else this.noStaleTimeCache.push(new MemoryContentCache.Content(a));b=(new Date).getTime();for(c=this.pendingInterestTable.length-1;0<=c;--c)if(this.pendingInterestTable[c].isTimedOut(b))this.pendingInterestTable.splice(c,
+1);else if(this.pendingInterestTable[c].getInterest().matchesName(a.getName())){try{this.pendingInterestTable[c].getFace().send(a.wireEncode().buf())}catch(d){0<LOG&&console.log(""+d);break}this.pendingInterestTable.splice(c,1)}};MemoryContentCache.prototype.storePendingInterest=function(a,b){this.pendingInterestTable.push(new MemoryContentCache.PendingInterest(a,b))};MemoryContentCache.prototype.getStorePendingInterest=function(){return this.storePendingInterestCallback};
+MemoryContentCache.prototype.onInterest=function(a,b,c,d,e){this.doCleanup();for(var f=0,g=null,h=this.staleTimeCache.length+this.noStaleTimeCache.length,k=0;k<h;++k){var l;l=k<this.staleTimeCache.length?this.staleTimeCache[k]:this.noStaleTimeCache[k-this.staleTimeCache.length];if(b.matchesName(l.getName())){if(0>b.getChildSelector()){c.send(l.getDataEncoding());return}var m;m=l.getName().size()>b.getName().size()?l.getName().get(b.getName().size()):this.emptyComponent;var q=!1;null===g?q=!0:0==b.getChildSelector()?
+0>m.compare(f)&&(q=!0):0<m.compare(f)&&(q=!0);q&&(f=m,g=l.getDataEncoding())}}null!==g?c.send(g):(f=this.onDataNotFoundForPrefix[a.toUri()])&&f(a,b,c,d,e)};MemoryContentCache.prototype.doCleanup=function(){var a=(new Date).getTime();if(a>=this.nextCleanupTime){for(;0<this.staleTimeCache.length&&this.staleTimeCache[0].isStale(a);)this.staleTimeCache.shift();this.nextCleanupTime=a+this.cleanupIntervalMilliseconds}};
+MemoryContentCache.Content=function(a){a&&(this.name=new Name(a.getName()),this.dataEncoding=a.wireEncode().buf())};MemoryContentCache.Content.prototype.getName=function(){return this.name};MemoryContentCache.Content.prototype.getDataEncoding=function(){return this.dataEncoding};MemoryContentCache.StaleTimeContent=function(a){MemoryContentCache.Content.call(this,a);this.staleTimeMilliseconds=(new Date).getTime()+a.getMetaInfo().getFreshnessPeriod()};MemoryContentCache.StaleTimeContent.prototype=new MemoryContentCache.Content;
+MemoryContentCache.StaleTimeContent.prototype.name="StaleTimeContent";MemoryContentCache.StaleTimeContent.prototype.isStale=function(a){return this.staleTimeMilliseconds<=a};MemoryContentCache.PendingInterest=function(a,b){this.interest=a;this.face=b;0<=this.interest.getInterestLifetimeMilliseconds()?this.timeoutMilliseconds=(new Date).getTime()+this.interest.getInterestLifetimeMilliseconds():this.timeoutMilliseconds=-1};MemoryContentCache.PendingInterest.prototype.getInterest=function(){return this.interest};
+MemoryContentCache.PendingInterest.prototype.getFace=function(){return this.face};MemoryContentCache.PendingInterest.prototype.isTimedOut=function(a){return 0<=this.timeoutTimeMilliseconds&&a>=this.timeoutTimeMilliseconds};var Name=require("../name.js").Name,NdnRegexMatcher=function(){};exports.NdnRegexMatcher=NdnRegexMatcher;NdnRegexMatcher.match=function(a,b){var c=b.toUri();a=NdnRegexMatcher.sanitizeSets(a);a=a.replace(/<>/g,"(?:<.+?>)");a=a.replace(/>/g,"");a=a.replace(/<(?!!)/g,"/");return c.match(new RegExp(a))};
+NdnRegexMatcher.sanitizeSets=function(a){for(var b=a,c=/\[(\^?)(.*?)\]/g,d;null!==(d=c.exec(a));){var e=c.lastIndex-1-d[2].length,f=e+d[2].length;0!==e-f&&(d=d[2].replace(/></g,">|<"),b=b.substr(0,e)+d+b.substr(f))}0<=b.indexOf("[^")?(b=b.replace(/\[\^/g,"(?:(?!"),b=b.replace(/\]/g,")(?:/.*)*)")):(b=b.replace(/\[/g,"("),b=b.replace(/\]/g,")"));return b};
+var Interest=require("../interest.js").Interest,Blob=require("./blob.js").Blob,KeyChain=require("../security/key-chain.js").KeyChain,NdnCommon=require("./ndn-common.js").NdnCommon,SegmentFetcher=function(a,b,c,d,e){this.face=a;this.validatorKeyChain=b;this.verifySegment=c;this.onComplete=d;this.onError=e;this.contentParts=[]};exports.SegmentFetcher=SegmentFetcher;SegmentFetcher.ErrorCode={INTEREST_TIMEOUT:1,DATA_HAS_NO_SEGMENT:2,SEGMENT_VERIFICATION_FAILED:3};SegmentFetcher.DontVerifySegment=function(a){return!0};
+SegmentFetcher.fetch=function(a,b,c,d,e){null==c||c instanceof KeyChain?(new SegmentFetcher(a,c,SegmentFetcher.DontVerifySegment,d,e)).fetchFirstSegment(b):(new SegmentFetcher(a,null,c,d,e)).fetchFirstSegment(b)};SegmentFetcher.prototype.fetchFirstSegment=function(a){a=new Interest(a);a.setChildSelector(1);a.setMustBeFresh(!0);var b=this;this.face.expressInterest(a,function(a,d){b.onData(a,d)},function(a){b.onTimeout(a)})};
+SegmentFetcher.prototype.fetchNextSegment=function(a,b,c){a=new Interest(a);a.setChildSelector(0);a.setMustBeFresh(!1);a.setName(b.getPrefix(-1).appendSegment(c));var d=this;this.face.expressInterest(a,function(a,b){d.onData(a,b)},function(a){d.onTimeout(a)})};
+SegmentFetcher.prototype.onData=function(a,b){if(null!=this.validatorKeyChain)try{var c=this;this.validatorKeyChain.verifyData(b,function(b){c.onVerified(b,a)},this.onValidationFailed.bind(this))}catch(d){console.log("Error in KeyChain.verifyData: "+d)}else if(this.verifySegment(b))this.onVerified(b,a);else try{this.onError(SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,"Segment verification failed")}catch(e){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(e))}};
+SegmentFetcher.prototype.onVerified=function(a,b){if(SegmentFetcher.endsWithSegmentNumber(a.getName())){var c=0;try{c=a.getName().get(-1).toSegment()}catch(d){try{this.onError(SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,"Error decoding the name segment number "+a.getName().get(-1).toEscapedString()+": "+d)}catch(e){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(e))}return}var f=this.contentParts.length;if(c!=f)this.fetchNextSegment(b,a.getName(),f);else{this.contentParts.push(a.getContent().buf());
+if(0<a.getMetaInfo().getFinalBlockId().getValue().size()){var g=0;try{g=a.getMetaInfo().getFinalBlockId().toSegment()}catch(h){try{this.onError(SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,"Error decoding the FinalBlockId segment number "+a.getMetaInfo().getFinalBlockId().toEscapedString()+": "+h)}catch(k){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(k))}return}if(c==g){c=Buffer.concat(this.contentParts);try{this.onComplete(new Blob(c,!1))}catch(l){console.log("Error in onComplete: "+
+NdnCommon.getErrorWithStackTrace(l))}return}}this.fetchNextSegment(b,a.getName(),f+1)}}else try{this.onError(SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,"Got an unexpected packet without a segment number: "+a.getName().toUri())}catch(m){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(m))}};
+SegmentFetcher.prototype.onValidationFailed=function(a,b){try{this.onError(SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,"Segment verification failed for "+a.getName().toUri()+" . Reason: "+b)}catch(c){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(c))}};SegmentFetcher.prototype.onTimeout=function(a){try{this.onError(SegmentFetcher.ErrorCode.INTEREST_TIMEOUT,"Time out for interest "+a.getName().toUri())}catch(b){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(b))}};
+SegmentFetcher.endsWithSegmentNumber=function(a){return 1<=a.size()&&a.get(-1).isSegment()};var Transport=function(){};exports.Transport=Transport;Transport.ConnectionInfo=function(){};Transport.prototype.isLocal=function(a,b,c){c("Transport.isLocal is not implemented")};
+var MicroForwarderTransport=function(){Transport.call(this);this.onReceivedObject=this.connectionInfo=this.elementReader=null;var a=this;window.addEventListener("message",function(b){if(b.source==window&&b.data.type&&"FromMicroForwarderStub"==b.data.type)if(b=b.data.object,b.type&&"Buffer"==b.type){if(null!=a.elementReader)a.elementReader.onReceivedData(new Buffer(b.data))}else if(a.onReceivedObject)a.onReceivedObject(b)},!1)};MicroForwarderTransport.prototype=new Transport;
+MicroForwarderTransport.prototype.name="MicroForwarderTransport";MicroForwarderTransport.ConnectionInfo=function(){Transport.ConnectionInfo.call(this)};MicroForwarderTransport.ConnectionInfo.prototype=new Transport.ConnectionInfo;MicroForwarderTransport.ConnectionInfo.prototype.name="MicroForwarderTransport.ConnectionInfo";MicroForwarderTransport.ConnectionInfo.prototype.equals=function(a){return null==a?!1:!0};MicroForwarderTransport.ConnectionInfo.prototype.toString=function(){return"{}"};
+MicroForwarderTransport.prototype.setOnReceivedObject=function(a){this.onReceivedObject=a};MicroForwarderTransport.prototype.isLocal=function(a,b,c){b(!0)};MicroForwarderTransport.prototype.connect=function(a,b,c,d){this.elementReader=new ElementReader(b);this.connectionInfo=a;c()};MicroForwarderTransport.prototype.sendObject=function(a){window.postMessage({type:"FromMicroForwarderTransport",object:a},"*")};
+MicroForwarderTransport.prototype.send=function(a){null==this.connectionInfo?console.log("MicroForwarderTransport connection is not established."):this.sendObject(a.toJSON())};var RuntimePortTransport=function(a){Transport.call(this);this.connectionInfo=this.elementReader=null;this.onReceivedObject=a;this.port=null};RuntimePortTransport.prototype=new Transport;RuntimePortTransport.prototype.name="RuntimePortTransport";
+RuntimePortTransport.ConnectionInfo=function(a){Transport.ConnectionInfo.call(this);this.port=a};RuntimePortTransport.ConnectionInfo.prototype=new Transport.ConnectionInfo;RuntimePortTransport.ConnectionInfo.prototype.name="RuntimePortTransport.ConnectionInfo";RuntimePortTransport.ConnectionInfo.prototype.equals=function(a){return null==a||void 0==a.port?!1:this.port==a.port};RuntimePortTransport.ConnectionInfo.prototype.toString=function(){return"{}"};
+RuntimePortTransport.prototype.setOnReceivedObject=function(a){this.onReceivedObject=a};RuntimePortTransport.prototype.isLocal=function(a,b,c){b(!0)};
+RuntimePortTransport.prototype.connect=function(a,b,c,d){this.elementReader=new ElementReader(b);this.connectionInfo=a;this.port=this.connectionInfo.port;var e=this;this.port.onMessage.addListener(function(a){if("Buffer"==a.type)e.elementReader.onReceivedData(Buffer.isBuffer(a.data)?a.data:new Buffer(a.data));else if(null!=e.onReceivedObject)e.onReceivedObject(a)});this.port.onDisconnect.addListener(function(){e.port=null;null!=d&&d()});c()};
+RuntimePortTransport.prototype.sendObject=function(a){null==this.port?console.log("RuntimePortTransport connection is not established."):this.port.postMessage(a)};RuntimePortTransport.prototype.send=function(a){this.sendObject(a.toJSON())};
+var ElementReader=require("../encoding/element-reader.js").ElementReader,LOG=require("../log.js").Log.LOG,Transport=require("./transport.js").Transport,Face,WebSocketTransport=function WebSocketTransport(){Transport.call(this);if(!WebSocket)throw Error("WebSocket support is not available on this platform.");this.elementReader=this.connectionInfo=this.ws=null;this.defaultGetConnectionInfo=Face.makeShuffledHostGetConnectionInfo("A.ws.ndn.ucla.edu B.ws.ndn.ucla.edu C.ws.ndn.ucla.edu D.ws.ndn.ucla.edu E.ws.ndn.ucla.edu F.ws.ndn.ucla.edu G.ws.ndn.ucla.edu H.ws.ndn.ucla.edu I.ws.ndn.ucla.edu J.ws.ndn.ucla.edu K.ws.ndn.ucla.edu L.ws.ndn.ucla.edu M.ws.ndn.ucla.edu N.ws.ndn.ucla.edu".split(" "),
+9696,function(b,c){return new WebSocketTransport.ConnectionInfo(b,c)})};WebSocketTransport.prototype=new Transport;WebSocketTransport.prototype.name="WebSocketTransport";WebSocketTransport.importFace=function(a){Face=a};exports.WebSocketTransport=WebSocketTransport;WebSocketTransport.ConnectionInfo=function(a,b){Transport.ConnectionInfo.call(this);this.host=a;this.port=void 0!==b?b:9696};WebSocketTransport.ConnectionInfo.prototype=new Transport.ConnectionInfo;
+WebSocketTransport.ConnectionInfo.prototype.name="WebSocketTransport.ConnectionInfo";WebSocketTransport.ConnectionInfo.prototype.equals=function(a){return null==a||void 0==a.host||void 0==a.port?!1:this.host==a.host&&this.port==a.port};WebSocketTransport.ConnectionInfo.prototype.toString=function(){return this.hostIsUri()?"{ uri: "+this.host+" }":"{ host: "+this.host+", port: "+this.port+" }"};
+WebSocketTransport.ConnectionInfo.prototype.hostIsUri=function(){return"ws:"==this.host.substr(0,3)||"wss:"==this.host.substr(0,4)};WebSocketTransport.prototype.isLocal=function(a,b,c){b(!1)};
+WebSocketTransport.prototype.connect=function(a,b,c,d){this.close();var e=a.hostIsUri()?a.host:"ws://"+a.host+":"+a.port;this.ws=new WebSocket(e);0<LOG&&console.log("ws connection created.");this.connectionInfo=a;this.ws.binaryType="arraybuffer";this.elementReader=new ElementReader(b);var f=this;this.ws.onmessage=function(a){a=a.data;if(null==a||void 0==a||""==a)console.log("INVALID ANSWER");else if(a instanceof ArrayBuffer){a=new Buffer(new Uint8Array(a));3<LOG&&console.log("BINARY RESPONSE IS "+
+a.toString("hex"));try{f.elementReader.onReceivedData(a)}catch(b){console.log("NDN.ws.onmessage exception: "+b)}}};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);c()};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(a){console.log("ws.onclose: WebSocket connection closed.");
+f.ws=null;null!=d&&d()}};WebSocketTransport.prototype.connectByFace=function(a,b){this.connect(a.connectionInfo,a,b,function(){a.closeByTransport()})};WebSocketTransport.prototype.send=function(a){if(null!=this.ws){var b=new Uint8Array(a.length);b.set(a);this.ws.send(b.buffer);3<LOG&&console.log("ws.send() returned.")}else console.log("WebSocket connection is not established.")};WebSocketTransport.prototype.close=function(){null!=this.ws&&delete this.ws};exports.TcpTransport=require("./transport/web-socket-transport").WebSocketTransport;
+Blob=require("./util/blob.js").Blob;DataUtils=require("./encoding/data-utils.js").DataUtils;LOG=require("./log.js").Log.LOG;DecodingException=require("./encoding/decoding-exception.js").DecodingException;
+Name=function Name(b){if("string"==typeof b)3<LOG&&console.log("Content Name String "+b),this.components=Name.createNameArray(b);else if("object"===typeof b)if(this.components=[],b instanceof Name)this.append(b);else for(var c=0;c<b.length;++c)this.append(b[c]);else null==b?this.components=[]:1<LOG&&console.log("NO CONTENT NAME GIVEN");this.changeCount=0};exports.Name=Name;
+Name.Component=function(a){"object"===typeof a&&a instanceof Name.Component?(this.value_=a.value_,this.type_=a.type_):(this.value_=a?"object"===typeof a&&"undefined"!==typeof ArrayBuffer&&a instanceof ArrayBuffer?new Blob(new Buffer(new Uint8Array(a)),!1):"object"===typeof a&&a instanceof Blob?a:new Blob(a):new Blob([]),this.type_=Name.Component.ComponentType.GENERIC)};Name.Component.ComponentType={IMPLICIT_SHA256_DIGEST:1,GENERIC:8};Name.Component.prototype.getValue=function(){return this.value_};
+Name.Component.prototype.getValueAsBuffer=function(){return this.value_.buf()};Object.defineProperty(Name.Component.prototype,"value",{get:function(){return this.getValueAsBuffer()}});Name.Component.prototype.toEscapedString=function(){return this.type_===Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST?"sha256digest="+this.value_.toHex():Name.toEscapedString(this.value_.buf())};Name.Component.prototype.isSegment=function(){return 1<=this.value_.size()&&0==this.value_.buf()[0]&&this.isGeneric()};
+Name.Component.prototype.isSegmentOffset=function(){return 1<=this.value_.size()&&251==this.value_.buf()[0]&&this.isGeneric()};Name.Component.prototype.isVersion=function(){return 1<=this.value_.size()&&253==this.value_.buf()[0]&&this.isGeneric()};Name.Component.prototype.isTimestamp=function(){return 1<=this.value_.size()&&252==this.value_.buf()[0]&&this.isGeneric()};Name.Component.prototype.isSequenceNumber=function(){return 1<=this.value_.size()&&254==this.value_.buf()[0]&&this.isGeneric()};
+Name.Component.prototype.isGeneric=function(){return this.type_===Name.Component.ComponentType.GENERIC};Name.Component.prototype.isImplicitSha256Digest=function(){return this.type_===Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST};Name.Component.prototype.toNumber=function(){return DataUtils.bigEndianToUnsignedInt(this.value_.buf())};
+Name.Component.prototype.toNumberWithMarker=function(a){if(0==this.value_.size()||this.value_.buf()[0]!=a)throw Error("Name component does not begin with the expected marker");return DataUtils.bigEndianToUnsignedInt(this.value_.buf().slice(1))};Name.Component.prototype.toSegment=function(){return this.toNumberWithMarker(0)};Name.Component.prototype.toSegmentOffset=function(){return this.toNumberWithMarker(251)};Name.Component.prototype.toVersion=function(){return this.toNumberWithMarker(253)};
+Name.Component.prototype.toTimestamp=function(){return this.toNumberWithMarker(252)};Name.Component.prototype.toSequenceNumber=function(){return this.toNumberWithMarker(254)};Name.Component.fromNumber=function(a){var b=new TlvEncoder(8);b.writeNonNegativeInteger(a);return new Name.Component(new Blob(b.getOutput(),!1))};
+Name.Component.fromNumberWithMarker=function(a,b){var c=new TlvEncoder(9);c.writeNonNegativeInteger(a);c.writeNonNegativeInteger(b);return new Name.Component(new Blob(c.getOutput(),!1))};Name.Component.fromSegment=function(a){return Name.Component.fromNumberWithMarker(a,0)};Name.Component.fromSegmentOffset=function(a){return Name.Component.fromNumberWithMarker(a,251)};Name.Component.fromVersion=function(a){return Name.Component.fromNumberWithMarker(a,253)};
+Name.Component.fromTimestamp=function(a){return Name.Component.fromNumberWithMarker(a,252)};Name.Component.fromSequenceNumber=function(a){return Name.Component.fromNumberWithMarker(a,254)};
+Name.Component.fromImplicitSha256Digest=function(a){digestBlob="object"===typeof a&&a instanceof Blob?a:new Blob(a,!0);if(32!==digestBlob.size())throw new DecodingException("Name.Component.fromImplicitSha256Digest: The digest length must be 32 bytes");a=new Name.Component(digestBlob);a.type_=Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST;return a};
+Name.Component.prototype.getSuccessor=function(){for(var a=new Buffer(this.value_.size()+1),b=!0,c=this.value_.size()-1;0<=c;--c)b?(a[c]=this.value_.buf()[c]+1&255,b=0===a[c]):a[c]=this.value_.buf()[c];b?a[a.length-1]=0:a=a.slice(0,this.value_.size());return new Name.Component(new Blob(a,!1))};Name.Component.prototype.equals=function(a){return"object"===typeof a&&a instanceof Name.Component&&this.value_.equals(a.value_)&&this.type_===a.type_};
+Name.Component.prototype.compare=function(a){return this.type_<a.type_?-1:this.type_>a.type_?1:Name.Component.compareBuffers(this.value_.buf(),a.value_.buf())};Name.Component.compareBuffers=function(a,b){if(a.length<b.length)return-1;if(a.length>b.length)return 1;for(var c=0;c<a.length;++c){if(a[c]<b[c])return-1;if(a[c]>b[c])return 1}return 0};Name.prototype.getName=function(){return this.toUri()};
+Name.createNameArray=function(a){a=a.trim();if(0>=a.length)return[];var b=a.indexOf(":");if(0<=b){var c=a.indexOf("/");if(0>c||b<c)a=a.substr(b+1,a.length-b-1).trim()}if("/"==a[0])if(2<=a.length&&"/"==a[1]){b=a.indexOf("/",2);if(0>b)return[];a=a.substr(b+1,a.length-b-1).trim()}else a=a.substr(1,a.length-1).trim();a=a.split("/");for(b=0;b<a.length;++b)"sha256digest="==a[b].substr(0,13)?(c=a[b].substr(13).trim(),c=Name.Component.fromImplicitSha256Digest(new Blob(new Buffer(c,"hex")),!1)):c=new Name.Component(Name.fromEscapedString(a[b])),
+c.getValue().isNull()?(a.splice(b,1),--b):a[b]=c;return a};Name.prototype.set=function(a){this.components=Name.createNameArray(a);++this.changeCount};
+Name.prototype.append=function(a){if("object"==typeof a&&a instanceof Name){a=a==this?this.components.slice(0,this.components.length):a.components;for(var b=0;b<a.length;++b)this.components.push(new Name.Component(a[b]))}else"object"===typeof a&&a instanceof Name.Component?this.components.push(a):this.components.push(new Name.Component(a));++this.changeCount;return this};Name.prototype.add=function(a){return this.append(a)};Name.prototype.clear=function(){this.components=[];++this.changeCount};
+Name.prototype.toUri=function(a){if(0==this.size())return a?"ndn:/":"/";a=a?"ndn:":"";for(var b=0;b<this.size();++b)a+="/"+this.components[b].toEscapedString();return a};Name.prototype.to_uri=function(){return this.toUri()};Name.prototype.toString=function(){return this.toUri()};Name.prototype.appendSegment=function(a){return this.append(Name.Component.fromSegment(a))};Name.prototype.appendSegmentOffset=function(a){return this.append(Name.Component.fromSegmentOffset(a))};
+Name.prototype.appendVersion=function(a){return this.append(Name.Component.fromVersion(a))};Name.prototype.appendTimestamp=function(a){return this.append(Name.Component.fromTimestamp(a))};Name.prototype.appendSequenceNumber=function(a){return this.append(Name.Component.fromSequenceNumber(a))};Name.prototype.appendImplicitSha256Digest=function(a){return this.append(Name.Component.fromImplicitSha256Digest(a))};Name.prototype.addSegment=function(a){return this.appendSegment(a)};
+Name.prototype.getSubName=function(a,b){0>a&&(a=this.components.length- -a);void 0==b&&(b=this.components.length-a);for(var c=new Name,d=a+b,e=a;e<d&&e<this.components.length;++e)c.components.push(this.components[e]);return c};Name.prototype.getPrefix=function(a){return 0>a?this.getSubName(0,this.components.length+a):this.getSubName(0,a)};Name.prototype.cut=function(a){return new Name(this.components.slice(0,this.components.length-a))};Name.prototype.size=function(){return this.components.length};
+Name.prototype.get=function(a){if(0<=a){if(a>=this.components.length)throw Error("Name.get: Index is out of bounds");return this.components[a]}if(a<-this.components.length)throw Error("Name.get: Index is out of bounds");return this.components[this.components.length- -a]};Name.prototype.getComponentCount=function(){return this.components.length};Name.prototype.getComponent=function(a){return new Buffer(this.components[a].getValue().buf())};
+Name.prototype.indexOfFileName=function(){for(var a=this.size()-1;0<=a;--a){var b=this.components[a].getValue().buf();if(!(0>=b.length||0==b[0]||192==b[0]||193==b[0]||245<=b[0]&&255>=b[0]))return a}return-1};Name.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeName(this)};Name.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeName(this,a.buf(),!1):b.decodeName(this,a,!0)};
+Name.prototype.compare=function(a,b,c,d,e){a instanceof Name&&(c=a,a=0,b=this.size());void 0==d&&(d=0);void 0==e&&(e=c.size());0>a&&(a=this.size()- -a);0>d&&(d=c.size()- -d);b=Math.min(b,this.size()-a);e=Math.min(e,c.size()-d);for(var f=Math.min(b,e),g=0;g<f;++g){var h=this.components[a+g].compare(c.components[d+g]);if(0!=h)return h}return b<e?-1:b>e?1:0};
+Name.prototype.equals=function(a){if(this.components.length!=a.components.length)return!1;for(var b=this.components.length-1;0<=b;--b)if(!this.components[b].equals(a.components[b]))return!1;return!0};Name.prototype.equalsName=function(a){return this.equals(a)};Name.prototype.getContentDigestValue=function(){for(var a=this.size()-1;0<=a;--a){var b=Name.getComponentContentDigestValue(this.components[a]);if(null!=b)return b}return null};
+Name.getComponentContentDigestValue=function(a){"object"==typeof a&&a instanceof Name.Component&&(a=a.getValue().buf());return a.length==Name.ContentDigestPrefix.length+32+Name.ContentDigestSuffix.length&&DataUtils.arraysEqual(a.slice(0,Name.ContentDigestPrefix.length),Name.ContentDigestPrefix)&&DataUtils.arraysEqual(a.slice(a.length-Name.ContentDigestSuffix.length,a.length),Name.ContentDigestSuffix)?a.slice(Name.ContentDigestPrefix.length,Name.ContentDigestPrefix.length+32):null};
+Name.ContentDigestPrefix=new Buffer([193,46,77,46,71,193,1,170,2,133]);Name.ContentDigestSuffix=new Buffer([0]);
+Name.toEscapedString=function(a){"object"==typeof a&&a instanceof Name.Component?a=a.getValue().buf():"object"===typeof a&&a instanceof Blob&&(a=a.buf());for(var b="",c=!1,d=0;d<a.length;++d)if(46!=a[d]){c=!0;break}if(c)for(d=0;d<a.length;++d)c=a[d],b=48<=c&&57>=c||65<=c&&90>=c||97<=c&&122>=c||43==c||45==c||46==c||95==c?b+String.fromCharCode(c):b+("%"+(16>c?"0":"")+c.toString(16).toUpperCase());else for(b="...",d=0;d<a.length;++d)b+=".";return b};
+Name.fromEscapedString=function(a){a=unescape(a.trim());return null==a.match(/[^.]/)?2>=a.length?new Blob:new Blob(DataUtils.toNumbersFromString(a.substr(3,a.length-3)),!1):new Blob(DataUtils.toNumbersFromString(a),!1)};Name.fromEscapedStringAsBuffer=function(a){return Name.fromEscapedString(a).buf()};Name.prototype.getSuccessor=function(){if(0==this.size()){var a=new Name;a.append(new Blob(new Buffer([0]),!1));return a}return this.getPrefix(-1).append(this.get(-1).getSuccessor())};
+Name.prototype.match=function(a){var b=this.components;a=a.components;if(b.length>a.length)return!1;for(var c=b.length-1;0<=c;--c)if(!b[c].equals(a[c]))return!1;return!0};Name.prototype.isPrefixOf=function(a){return this.match(a)};Name.prototype.getChangeCount=function(){return this.changeCount};
+var TlvEncoder=require("./encoding/tlv/tlv-encoder.js").TlvEncoder,WireFormat=require("./encoding/wire-format.js").WireFormat,Blob=require("./util/blob.js").Blob,ChangeCounter=require("./util/change-counter.js").ChangeCounter,Name=require("./name.js").Name,KeyLocatorType={KEYNAME:1,KEY_LOCATOR_DIGEST:2};exports.KeyLocatorType=KeyLocatorType;
+var KeyLocator=function KeyLocator(b,c){"object"===typeof b&&b instanceof KeyLocator?(this.type_=b.type_,this.keyName_=new ChangeCounter(new Name(b.getKeyName())),this.keyData_=b.keyData_):(this.type_=c,this.keyName_=new ChangeCounter(new Name),this.keyData_=new Blob,c==KeyLocatorType.KEYNAME?this.keyName_.set("object"===typeof b&&b instanceof Name?new Name(b):new Name):c==KeyLocatorType.KEY_LOCATOR_DIGEST&&(this.keyData_=new Blob(b)));this.changeCount_=0};exports.KeyLocator=KeyLocator;
+KeyLocator.prototype.getType=function(){return this.type_};KeyLocator.prototype.getKeyName=function(){return this.keyName_.get()};KeyLocator.prototype.getKeyData=function(){return this.keyData_};KeyLocator.prototype.getKeyDataAsBuffer=function(){return this.getKeyData().buf()};KeyLocator.prototype.setType=function(a){this.type_=a;++this.changeCount_};KeyLocator.prototype.setKeyName=function(a){this.keyName_.set("object"===typeof a&&a instanceof Name?new Name(a):new Name);++this.changeCount_};
+KeyLocator.prototype.setKeyData=function(a){this.keyData_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};KeyLocator.prototype.clear=function(){this.type_=null;this.keyName_.set(new Name);this.keyData_=new Blob;++this.changeCount_};
+KeyLocator.prototype.equals=function(a){if(this.type_!=a.type_)return!1;if(this.type_==KeyLocatorType.KEYNAME){if(!this.getKeyName().equals(a.getKeyName()))return!1}else if(this.type_==KeyLocatorType.KEY_LOCATOR_DIGEST&&!this.getKeyData().equals(a.getKeyData()))return!1;return!0};KeyLocator.canGetFromSignature=function(a){return a instanceof Sha256WithRsaSignature||a instanceof Sha256WithEcdsaSignature||a instanceof HmacWithSha256Signature};
+KeyLocator.getFromSignature=function(a){if(a instanceof Sha256WithRsaSignature||a instanceof Sha256WithEcdsaSignature||a instanceof HmacWithSha256Signature)return a.getKeyLocator();throw Error("KeyLocator.getFromSignature: Signature type does not have a KeyLocator");};KeyLocator.prototype.getChangeCount=function(){this.keyName_.checkChanged()&&++this.changeCount_;return this.changeCount_};Object.defineProperty(KeyLocator.prototype,"type",{get:function(){return this.getType()},set:function(a){this.setType(a)}});
+Object.defineProperty(KeyLocator.prototype,"keyData",{get:function(){return this.getKeyDataAsBuffer()},set:function(a){this.setKeyData(a)}});var Sha256WithRsaSignature=require("./sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("./sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,HmacWithSha256Signature=require("./hmac-with-sha256-signature.js").HmacWithSha256Signature,Name=require("./name.js").Name,ContentType={BLOB:0,LINK:1,KEY:2,NACK:3,OTHER_CODE:32767};
+exports.ContentType=ContentType;
+var MetaInfo=function MetaInfo(b,c,d,e,f,g){if(c)throw Error("MetaInfo constructor: timestamp support has been removed.");if(e)throw Error("MetaInfo constructor: locator support has been removed.");if("object"===typeof b&&b instanceof MetaInfo)this.publisher_=b.publisher_,this.type_=b.type_,this.otherTypeCode_=b.otherTypeCode_,this.freshnessPeriod_=b.freshnessPeriod_,this.finalBlockId_=b.finalBlockId_;else{if(b)throw Error("MetaInfo constructor: publisher support has been removed.");this.type=null==
+d||0>d?ContentType.BLOB:d;this.otherTypeCode_=-1;this.freshnessSeconds=f;this.finalBlockID=g}this.changeCount_=0};exports.MetaInfo=MetaInfo;MetaInfo.prototype.getType=function(){return this.type_};MetaInfo.prototype.getOtherTypeCode=function(){return this.otherTypeCode_};MetaInfo.prototype.getFreshnessPeriod=function(){return this.freshnessPeriod_};MetaInfo.prototype.getFinalBlockId=function(){return this.finalBlockId_};MetaInfo.prototype.getFinalBlockID=function(){return this.getFinalBlockId()};
+MetaInfo.prototype.getFinalBlockIDAsBuffer=function(){return this.finalBlockId_.getValue().buf()};MetaInfo.prototype.setType=function(a){this.type_=null==a||0>a?ContentType.BLOB:a;++this.changeCount_};MetaInfo.prototype.setOtherTypeCode=function(a){if(0>a)throw Error("MetaInfo other type code must be non-negative");this.otherTypeCode_=a;++this.changeCount_};MetaInfo.prototype.setFreshnessPeriod=function(a){this.freshnessPeriod_=null==a||0>a?null:a;++this.changeCount_};
+MetaInfo.prototype.setFinalBlockId=function(a){this.finalBlockId_="object"===typeof a&&a instanceof Name.Component?a:new Name.Component(a);++this.changeCount_};MetaInfo.prototype.setFinalBlockID=function(a){this.setFinalBlockId(a)};MetaInfo.prototype.getChangeCount=function(){return this.changeCount_};Object.defineProperty(MetaInfo.prototype,"type",{get:function(){return this.getType()},set:function(a){this.setType(a)}});
+Object.defineProperty(MetaInfo.prototype,"freshnessSeconds",{get:function(){return null==this.freshnessPeriod_||0>this.freshnessPeriod_?null:this.freshnessPeriod_/1E3},set:function(a){this.freshnessPeriod_=null==a||0>a?null:1E3*a;++this.changeCount_}});Object.defineProperty(MetaInfo.prototype,"finalBlockID",{get:function(){return this.getFinalBlockIDAsBuffer()},set:function(a){this.setFinalBlockId(a)}});Blob=require("./util/blob.js").Blob;ChangeCounter=require("./util/change-counter.js").ChangeCounter;
+KeyLocator=require("./key-locator.js").KeyLocator;Sha256WithEcdsaSignature=function Sha256WithEcdsaSignature(b){"object"===typeof b&&b instanceof Sha256WithEcdsaSignature?(this.keyLocator_=new ChangeCounter(new KeyLocator(b.getKeyLocator())),this.signature_=b.signature_):(this.keyLocator_=new ChangeCounter(new KeyLocator),this.signature_=new Blob);this.changeCount_=0};exports.Sha256WithEcdsaSignature=Sha256WithEcdsaSignature;Sha256WithEcdsaSignature.prototype.clone=function(){return new Sha256WithEcdsaSignature(this)};
+Sha256WithEcdsaSignature.prototype.getKeyLocator=function(){return this.keyLocator_.get()};Sha256WithEcdsaSignature.prototype.getSignature=function(){return this.signature_};Sha256WithEcdsaSignature.prototype.setKeyLocator=function(a){this.keyLocator_.set("object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator);++this.changeCount_};Sha256WithEcdsaSignature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};
+Sha256WithEcdsaSignature.prototype.getChangeCount=function(){this.keyLocator_.checkChanged()&&++this.changeCount_;return this.changeCount_};Blob=require("./util/blob.js").Blob;ChangeCounter=require("./util/change-counter.js").ChangeCounter;KeyLocator=require("./key-locator.js").KeyLocator;
+Sha256WithRsaSignature=function Sha256WithRsaSignature(b){"object"===typeof b&&b instanceof Sha256WithRsaSignature?(this.keyLocator_=new ChangeCounter(new KeyLocator(b.getKeyLocator())),this.signature_=b.signature_):(this.keyLocator_=new ChangeCounter(new KeyLocator),this.signature_=new Blob);this.changeCount_=0};exports.Sha256WithRsaSignature=Sha256WithRsaSignature;Sha256WithRsaSignature.prototype.clone=function(){return new Sha256WithRsaSignature(this)};
+Sha256WithRsaSignature.prototype.getKeyLocator=function(){return this.keyLocator_.get()};Sha256WithRsaSignature.prototype.getSignature=function(){return this.signature_};Sha256WithRsaSignature.prototype.getSignatureAsBuffer=function(){return this.signature_.buf()};Sha256WithRsaSignature.prototype.setKeyLocator=function(a){this.keyLocator_.set("object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator);++this.changeCount_};
+Sha256WithRsaSignature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};Sha256WithRsaSignature.prototype.getChangeCount=function(){this.keyLocator_.checkChanged()&&++this.changeCount_;return this.changeCount_};Object.defineProperty(Sha256WithRsaSignature.prototype,"keyLocator",{get:function(){return this.getKeyLocator()},set:function(a){this.setKeyLocator(a)}});
+Object.defineProperty(Sha256WithRsaSignature.prototype,"signature",{get:function(){return this.getSignatureAsBuffer()},set:function(a){this.setSignature(a)}});
+var Blob=require("./util/blob.js").Blob,GenericSignature=function GenericSignature(b){"object"===typeof b&&b instanceof GenericSignature?(this.signature_=b.signature_,this.signatureInfoEncoding_=b.signatureInfoEncoding_,this.typeCode_=b.typeCode_):(this.signature_=new Blob,this.signatureInfoEncoding_=new Blob,this.typeCode_=null);this.changeCount_=0};exports.GenericSignature=GenericSignature;GenericSignature.prototype.clone=function(){return new GenericSignature(this)};
+GenericSignature.prototype.getSignature=function(){return this.signature_};GenericSignature.prototype.getSignatureAsBuffer=function(){return this.signature_.buf()};GenericSignature.prototype.getSignatureInfoEncoding=function(){return this.signatureInfoEncoding_};GenericSignature.prototype.getTypeCode=function(){return this.typeCode_};GenericSignature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};
+GenericSignature.prototype.setSignatureInfoEncoding=function(a,b){this.signatureInfoEncoding_="object"===typeof a&&a instanceof Blob?a:new Blob(a);this.typeCode_=b;++this.changeCount_};GenericSignature.prototype.getChangeCount=function(){return this.changeCount_};Object.defineProperty(GenericSignature.prototype,"signature",{get:function(){return this.getSignatureAsBuffer()},set:function(a){this.setSignature(a)}});Blob=require("./util/blob.js").Blob;ChangeCounter=require("./util/change-counter.js").ChangeCounter;
+KeyLocator=require("./key-locator.js").KeyLocator;HmacWithSha256Signature=function HmacWithSha256Signature(b){"object"===typeof b&&b instanceof HmacWithSha256Signature?(this.keyLocator_=new ChangeCounter(new KeyLocator(b.getKeyLocator())),this.signature_=b.signature_):(this.keyLocator_=new ChangeCounter(new KeyLocator),this.signature_=new Blob);this.changeCount_=0};exports.HmacWithSha256Signature=HmacWithSha256Signature;HmacWithSha256Signature.prototype.clone=function(){return new HmacWithSha256Signature(this)};
+HmacWithSha256Signature.prototype.getKeyLocator=function(){return this.keyLocator_.get()};HmacWithSha256Signature.prototype.getSignature=function(){return this.signature_};HmacWithSha256Signature.prototype.getSignatureAsBuffer=function(){return this.signature_.buf()};HmacWithSha256Signature.prototype.setKeyLocator=function(a){this.keyLocator_.set("object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator);++this.changeCount_};
+HmacWithSha256Signature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};HmacWithSha256Signature.prototype.getChangeCount=function(){this.keyLocator_.checkChanged()&&++this.changeCount_;return this.changeCount_};Object.defineProperty(HmacWithSha256Signature.prototype,"keyLocator",{get:function(){return this.getKeyLocator()},set:function(a){this.setKeyLocator(a)}});
+Object.defineProperty(HmacWithSha256Signature.prototype,"signature",{get:function(){return this.getSignatureAsBuffer()},set:function(a){this.setSignature(a)}});var Blob=require("./util/blob.js").Blob,DigestSha256Signature=function DigestSha256Signature(b){this.signature_="object"===typeof b&&b instanceof DigestSha256Signature?b.signature_:new Blob;this.changeCount_=0};exports.DigestSha256Signature=DigestSha256Signature;DigestSha256Signature.prototype.clone=function(){return new DigestSha256Signature(this)};
+DigestSha256Signature.prototype.getSignature=function(){return this.signature_};DigestSha256Signature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};DigestSha256Signature.prototype.getChangeCount=function(){return this.changeCount_};Object.defineProperty(DigestSha256Signature.prototype,"signature",{get:function(){return this.getSignature()},set:function(a){this.setSignature(a)}});
+var Blob=require("./util/blob.js").Blob,SignedBlob=require("./util/signed-blob.js").SignedBlob,ChangeCounter=require("./util/change-counter.js").ChangeCounter,Name=require("./name.js").Name,Sha256WithRsaSignature=require("./sha256-with-rsa-signature.js").Sha256WithRsaSignature,MetaInfo=require("./meta-info.js").MetaInfo,IncomingFaceId=require("./lp/incoming-face-id.js").IncomingFaceId,WireFormat=require("./encoding/wire-format.js").WireFormat,Crypto=require("./crypto.js"),Data=function Data(b,c,d){b instanceof
+Data?(this.name_=new ChangeCounter(new Name(b.getName())),this.metaInfo_=new ChangeCounter(new MetaInfo(b.getMetaInfo())),this.signature_=new ChangeCounter(b.getSignature().clone()),this.content_=b.content_,this.defaultWireEncoding_=b.getDefaultWireEncoding(),this.defaultFullName_=b.defaultFullName_,this.defaultWireEncodingFormat_=b.defaultWireEncodingFormat_):(this.name_="string"===typeof b?new ChangeCounter(new Name(b)):new ChangeCounter("object"===typeof b&&b instanceof Name?new Name(b):new Name),
+"object"===typeof c&&c instanceof MetaInfo?(b=c,c=d):b=null,this.metaInfo_=new ChangeCounter("object"===typeof b&&b instanceof MetaInfo?new MetaInfo(b):new MetaInfo),this.content_="object"===typeof c&&c instanceof Blob?c:new Blob(c,!0),this.signature_=new ChangeCounter(new Sha256WithRsaSignature),this.defaultWireEncoding_=new SignedBlob,this.defaultFullName_=new Name,this.defaultWireEncodingFormat_=null);this.changeCount_=this.getDefaultWireEncodingChangeCount_=0;this.lpPacket_=null};
+exports.Data=Data;Data.prototype.getName=function(){return this.name_.get()};Data.prototype.getMetaInfo=function(){return this.metaInfo_.get()};Data.prototype.getSignature=function(){return this.signature_.get()};Data.prototype.getContent=function(){return this.content_};Data.prototype.getContentAsBuffer=function(){return this.content_.buf()};
+Data.prototype.getDefaultWireEncoding=function(){this.getDefaultWireEncodingChangeCount_!=this.getChangeCount()&&(this.defaultWireEncoding_=new SignedBlob,this.defaultWireEncodingFormat_=null,this.getDefaultWireEncodingChangeCount_=this.getChangeCount());return this.defaultWireEncoding_};Data.prototype.getDefaultWireEncodingFormat=function(){return this.defaultWireEncodingFormat_};
+Data.prototype.getIncomingFaceId=function(){var a=null===this.lpPacket_?null:IncomingFaceId.getFirstHeader(this.lpPacket_);return null===a?null:a.getFaceId()};
+Data.prototype.getFullName=function(a){a=a||WireFormat.getDefaultWireFormat();if(!this.getDefaultWireEncoding().isNull()&&0<this.defaultFullName_.size()&&this.getDefaultWireEncodingFormat()==a)return this.defaultFullName_;var b=new Name(this.getName()),c=Crypto.createHash("sha256");c.update(this.wireEncode(a).buf());b.appendImplicitSha256Digest(new Blob(c.digest(),!1));a==WireFormat.getDefaultWireFormat()&&(this.defaultFullName_=b);return b};
+Data.prototype.setName=function(a){this.name_.set("object"===typeof a&&a instanceof Name?new Name(a):new Name);++this.changeCount_;return this};Data.prototype.setMetaInfo=function(a){this.metaInfo_.set("object"===typeof a&&a instanceof MetaInfo?new MetaInfo(a):new MetaInfo);++this.changeCount_;return this};Data.prototype.setSignature=function(a){this.signature_.set(null==a?new Sha256WithRsaSignature:a.clone());++this.changeCount_;return this};
+Data.prototype.setContent=function(a){this.content_="object"===typeof a&&a instanceof Blob?a:new Blob(a,!0);++this.changeCount_;return this};
+Data.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();if(!this.getDefaultWireEncoding().isNull()&&this.getDefaultWireEncodingFormat()==a)return this.getDefaultWireEncoding();var b=a.encodeData(this),b=new SignedBlob(b.encoding,b.signedPortionBeginOffset,b.signedPortionEndOffset);a==WireFormat.getDefaultWireFormat()&&this.setDefaultWireEncoding(b,WireFormat.getDefaultWireFormat());return b};
+Data.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c;c="object"===typeof a&&a instanceof Blob?b.decodeData(this,a.buf(),!1):b.decodeData(this,a,!0);b==WireFormat.getDefaultWireFormat()?this.setDefaultWireEncoding(new SignedBlob(new Blob(a,!0),c.signedPortionBeginOffset,c.signedPortionEndOffset),WireFormat.getDefaultWireFormat()):this.setDefaultWireEncoding(new SignedBlob,null)};Data.prototype.setLpPacket=function(a){this.lpPacket_=a;return this};
+Data.prototype.getChangeCount=function(){var a=this.name_.checkChanged(),a=this.metaInfo_.checkChanged()||a;(a=this.signature_.checkChanged()||a)&&++this.changeCount_;return this.changeCount_};Data.prototype.setDefaultWireEncoding=function(a,b){this.defaultWireEncoding_=a;this.defaultWireEncodingFormat_=b;this.getDefaultWireEncodingChangeCount_=this.getChangeCount()};Object.defineProperty(Data.prototype,"name",{get:function(){return this.getName()},set:function(a){this.setName(a)}});
+Object.defineProperty(Data.prototype,"metaInfo",{get:function(){return this.getMetaInfo()},set:function(a){this.setMetaInfo(a)}});Object.defineProperty(Data.prototype,"signature",{get:function(){return this.getSignature()},set:function(a){this.setSignature(a)}});Object.defineProperty(Data.prototype,"content",{get:function(){return this.getContentAsBuffer()},set:function(a){this.setContent(a)}});function SecurityException(a){if(a)return a.__proto__=SecurityException.prototype,a}
+SecurityException.prototype=Error();SecurityException.prototype.name="SecurityException";exports.SecurityException=SecurityException;function UnrecognizedKeyFormatException(a){SecurityException.call(this,a)}UnrecognizedKeyFormatException.prototype=new SecurityException;UnrecognizedKeyFormatException.prototype.name="UnrecognizedKeyFormatException";exports.UnrecognizedKeyFormatException=UnrecognizedKeyFormatException;function UnrecognizedDigestAlgorithmException(a){SecurityException.call(this,a)}
+UnrecognizedDigestAlgorithmException.prototype=new SecurityException;UnrecognizedDigestAlgorithmException.prototype.name="UnrecognizedDigestAlgorithmException";exports.UnrecognizedDigestAlgorithmException=UnrecognizedDigestAlgorithmException;var KeyType=function(){};exports.KeyType=KeyType;KeyType.RSA=0;KeyType.ECDSA=1;KeyType.AES=128;var KeyClass=function(){};exports.KeyClass=KeyClass;KeyClass.PUBLIC=1;KeyClass.PRIVATE=2;KeyClass.SYMMETRIC=3;var DigestAlgorithm=function(){};
+exports.DigestAlgorithm=DigestAlgorithm;DigestAlgorithm.SHA256=1;var KeyType=require("./security-types.js").KeyType,KeyParams=function(a){this.keyType=a};exports.KeyParams=KeyParams;KeyParams.prototype.getKeyType=function(){return this.keyType};var RsaKeyParams=function RsaKeyParams(b){KeyParams.call(this,RsaKeyParams.getType());null==b&&(b=RsaKeyParams.getDefaultSize());this.size=b};RsaKeyParams.prototype=new KeyParams;RsaKeyParams.prototype.name="RsaKeyParams";exports.RsaKeyParams=RsaKeyParams;
+RsaKeyParams.prototype.getKeySize=function(){return this.size};RsaKeyParams.getDefaultSize=function(){return 2048};RsaKeyParams.getType=function(){return KeyType.RSA};var EcdsaKeyParams=function EcdsaKeyParams(b){KeyParams.call(this,EcdsaKeyParams.getType());null==b&&(b=EcdsaKeyParams.getDefaultSize());this.size=b};EcdsaKeyParams.prototype=new KeyParams;EcdsaKeyParams.prototype.name="EcdsaKeyParams";exports.EcdsaKeyParams=EcdsaKeyParams;EcdsaKeyParams.prototype.getKeySize=function(){return this.size};
+EcdsaKeyParams.getDefaultSize=function(){return 256};EcdsaKeyParams.getType=function(){return KeyType.ECDSA};var AesKeyParams=function AesKeyParams(b){KeyParams.call(this,AesKeyParams.getType());null==b&&(b=AesKeyParams.getDefaultSize());this.size=b};AesKeyParams.prototype=new KeyParams;AesKeyParams.prototype.name="AesKeyParams";exports.AesKeyParams=AesKeyParams;AesKeyParams.prototype.getKeySize=function(){return this.size};AesKeyParams.getDefaultSize=function(){return 64};AesKeyParams.getType=function(){return KeyType.AES};
+var Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,DerDecodingException=require("../../encoding/der/der-decoding-exception.js").DerDecodingException,DerNode=require("../../encoding/der/der-node.js").DerNode,SecurityException=require("../security-exception.js").SecurityException,UnrecognizedKeyFormatException=require("../security-exception.js").UnrecognizedKeyFormatException,KeyType=require("../security-types.js").KeyType,DigestAlgorithm=require("../security-types.js").DigestAlgorithm,
+PublicKey=function PublicKey(b){if(b){this.keyDer=b;var c=null;try{var d=DerNode.parse(b.buf(),0).getChildren(),c=DerNode.getSequence(d,0).getChildren()[0].toVal()}catch(e){throw new UnrecognizedKeyFormatException(Error("PublicKey.decodeKeyType: Error decoding the public key: "+e.message));}c==PublicKey.RSA_ENCRYPTION_OID?this.keyType=KeyType.RSA:c==PublicKey.EC_ENCRYPTION_OID&&(this.keyType=KeyType.ECDSA)}else this.keyDer=new Blob,this.keyType=null};exports.PublicKey=PublicKey;
+PublicKey.prototype.toDer=function(){return DerNode.parse(this.keyDer.buf())};PublicKey.prototype.getKeyType=function(){return this.keyType};PublicKey.prototype.getDigest=function(a){void 0==a&&(a=DigestAlgorithm.SHA256);if(a==DigestAlgorithm.SHA256)return a=Crypto.createHash("sha256"),a.update(this.keyDer.buf()),new Blob(a.digest(),!1);throw new SecurityException(Error("Wrong format!"));};PublicKey.prototype.getKeyDer=function(){return this.keyDer};PublicKey.RSA_ENCRYPTION_OID="1.2.840.113549.1.1.1";
+PublicKey.EC_ENCRYPTION_OID="1.2.840.10045.2.1";var DerNode=require("../../encoding/der/der-node.js").DerNode,OID=require("../../encoding/oid.js").OID,CertificateExtension=function(a,b,c){this.extensionId="string"===typeof a?new OID(a):a;this.isCritical=b;this.extensionValue=c};exports.CertificateExtension=CertificateExtension;
+CertificateExtension.prototype.toDer=function(){var a=new DerNode.DerSequence,b=new DerNode.DerOid(this.extensionId),c=new DerNode.DerBoolean(this.isCritical),d=new DerNode.DerOctetString(this.extensionValue.buf());a.addChild(b);a.addChild(c);a.addChild(d);a.getSize();return a};CertificateExtension.prototype.toDerBlob=function(){return this.toDer().encode()};CertificateExtension.prototype.getOid=function(){return this.extensionId};CertificateExtension.prototype.getIsCritical=function(){return this.isCritical};
+CertificateExtension.prototype.getValue=function(){return this.extensionValue};var Blob=require("../../util/blob.js").Blob,OID=require("../../encoding/oid.js").OID,DerNode=require("../../encoding/der/der-node.js").DerNode,CertificateSubjectDescription=function(a,b){this.oid="string"===typeof a?new OID(a):a;this.value=b};exports.CertificateSubjectDescription=CertificateSubjectDescription;
+CertificateSubjectDescription.prototype.toDer=function(){var a=new DerNode.DerSequence,b=new DerNode.DerOid(this.oid),c=new DerNode.DerPrintableString((new Blob(this.value)).buf());a.addChild(b);a.addChild(c);return a};CertificateSubjectDescription.prototype.getOidString=function(){return this.oid.toString()};CertificateSubjectDescription.prototype.getValue=function(){return this.value};
+var Data=require("../../data.js").Data,ContentType=require("../../meta-info.js").ContentType,WireFormat=require("../../encoding/wire-format.js").WireFormat,DerNode=require("../../encoding/der/der-node.js").DerNode,KeyType=require("../../security/security-types.js").KeyType,PublicKey=require("./public-key.js").PublicKey,CertificateSubjectDescription=require("./certificate-subject-description.js").CertificateSubjectDescription,CertificateExtension=require("./certificate-extension.js").CertificateExtension,
+Certificate=function(a){void 0!=a?Data.call(this,a):Data.call(this);this.subjectDescriptionList=[];this.extensionList=[];this.notBefore=Number.MAX_VALUE;this.notAfter=-Number.MAX_VALUE;this.key=new PublicKey;void 0!=a&&this.decode()};Certificate.prototype=new Data;Certificate.prototype.name="Certificate";exports.Certificate=Certificate;Certificate.prototype.encode=function(){var a=this.toDer();this.setContent(a.encode());this.getMetaInfo().setType(ContentType.KEY)};
+Certificate.prototype.addSubjectDescription=function(a){this.subjectDescriptionList.push(a)};Certificate.prototype.getSubjectDescriptionList=function(){return this.subjectDescriptionList};Certificate.prototype.addExtension=function(a){this.extensionList.push(a)};Certificate.prototype.getExtensionList=function(){return this.extensionList};Certificate.prototype.setNotBefore=function(a){this.notBefore=a};Certificate.prototype.getNotBefore=function(){return this.notBefore};
+Certificate.prototype.setNotAfter=function(a){this.notAfter=a};Certificate.prototype.getNotAfter=function(){return this.notAfter};Certificate.prototype.setPublicKeyInfo=function(a){this.key=a};Certificate.prototype.getPublicKeyInfo=function(){return this.key};Certificate.prototype.isTooEarly=function(){return(new Date).getTime()<this.notBefore};Certificate.prototype.isTooLate=function(){return(new Date).getTime()>this.notAfter};
+Certificate.prototype.toDer=function(){var a=new DerNode.DerSequence,b=new DerNode.DerSequence,c=new DerNode.DerGeneralizedTime(this.notBefore),d=new DerNode.DerGeneralizedTime(this.notAfter);b.addChild(c);b.addChild(d);a.addChild(b);c=new DerNode.DerSequence;for(b=0;b<this.subjectDescriptionList.length;++b)c.addChild(this.subjectDescriptionList[b].toDer());a.addChild(c);a.addChild(this.key.toDer());if(0<this.extensionList.length){c=new DerNode.DerSequence;for(b=0;b<this.extensionList.length;++b)c.addChild(this.extensionList[b].toDer());
+a.addChild(c)}return a};
+Certificate.prototype.decode=function(){var a=DerNode.parse(this.getContent().buf()).getChildren(),b=DerNode.getSequence(a,0).getChildren();this.notBefore=b[0].toVal();this.notAfter=b[1].toVal();for(var c=DerNode.getSequence(a,1).getChildren(),b=0;b<c.length;++b){var d=DerNode.getSequence(c,b).getChildren(),e=d[0].toVal(),d=d[1].toVal().buf().toString("binary");this.addSubjectDescription(new CertificateSubjectDescription(e,d))}b=a[2].encode();this.key=new PublicKey(b);if(3<a.length)for(a=DerNode.getSequence(a,
+3).getChildren(),b=0;b<a.length;++b)d=DerNode.getSequence(a,b).getChildren(),e=d[0].toVal(),c=d[1].toVal(),d=d[2].toVal(),this.addExtension(new CertificateExtension(e,c,d))};Certificate.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();Data.prototype.wireDecode.call(this,a,b);this.decode()};
+Certificate.prototype.toString=function(){var a;a="Certificate name:\n"+("  "+this.getName().toUri()+"\n");a+="Validity:\n";var b=Certificate.toIsoString(Math.round(this.notBefore)),c=Certificate.toIsoString(Math.round(this.notAfter));a=a+("  NotBefore: "+b+"\n")+("  NotAfter: "+c+"\n");for(b=0;b<this.subjectDescriptionList.length;++b)c=this.subjectDescriptionList[b],a+="Subject Description:\n",a+="  "+c.getOidString()+": "+c.getValue()+"\n";a+="Public key bits:\n";c=this.key.getKeyDer().buf().toString("base64");
+for(b=0;b<c.length;b+=64)a+=c.substring(b,Math.min(b+64,c.length))+"\n";if(0<this.extensionList.length)for(a+="Extensions:\n",b=0;b<this.extensionList.length;++b)c=this.extensionList[b],a+="  OID: "+c.getOid()+"\n",a+="  Is critical: "+(c.getIsCritical()?"Y":"N")+"\n",a+="  Value: "+c.getValue().toHex()+"\n";return a};
+Certificate.toIsoString=function(a){a=new Date(Math.round(a));return a.getUTCFullYear()+Certificate.to2DigitString(a.getUTCMonth()+1)+Certificate.to2DigitString(a.getUTCDate())+"T"+Certificate.to2DigitString(a.getUTCHours())+Certificate.to2DigitString(a.getUTCMinutes())+Certificate.to2DigitString(a.getUTCSeconds())};Certificate.to2DigitString=function(a){a=a.toString();return 1===a.length?"0"+a:a};
+var Data=require("../../data.js").Data,Name=require("../../name.js").Name,SecurityException=require("../../security//security-exception.js").SecurityException,Certificate=require("./certificate.js").Certificate,WireFormat=require("../../encoding/wire-format.js").WireFormat,IdentityCertificate=function IdentityCertificate(b){void 0!=b?Certificate.call(this,b):Certificate.call(this);this.publicKeyName=new Name;if(b instanceof IdentityCertificate)this.publicKeyName=new Name(b.publicKeyName);else if(b instanceof
+Data){if(!IdentityCertificate.isCorrectName(b.getName()))throw new SecurityException(Error("Wrong Identity Certificate Name!"));this.setPublicKeyName()}};IdentityCertificate.prototype=new Certificate;IdentityCertificate.prototype.name="IdentityCertificate";exports.IdentityCertificate=IdentityCertificate;
+IdentityCertificate.prototype.setName=function(a){if(!IdentityCertificate.isCorrectName(a))throw new SecurityException(Error("Wrong Identity Certificate Name!"));Certificate.prototype.setName.call(this,a);this.setPublicKeyName();return this};IdentityCertificate.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();Certificate.prototype.wireDecode.call(this,a,b);this.setPublicKeyName()};IdentityCertificate.prototype.getPublicKeyName=function(){return this.publicKeyName};
+IdentityCertificate.isIdentityCertificate=function(a){return IdentityCertificate.isCorrectName(a.getName())};
+IdentityCertificate.certificateNameToPublicKeyName=function(a){for(var b=!1,c=a.size()-1;0<c+1;--c)if("ID-CERT"==a.get(c).toEscapedString()){b=!0;break}if(!b)throw Error("Incorrect identity certificate name "+a.toUri());for(var b=a.getSubName(0,c),c=!1,d=0;d<b.size();d++)if("KEY"==b.get(d).toEscapedString()){c=!0;break}if(!c)throw Error("Incorrect identity certificate name "+a.toUri());return b.getSubName(0,d).append(b.getSubName(d+1,b.size()-d-1))};
+IdentityCertificate.isCorrectName=function(a){for(var b=a.size()-1;0<=b&&"ID-CERT"!=a.get(b).toEscapedString();b--);if(0>b)return!1;for(b=0;b<a.size()&&"KEY"!=a.get(b).toEscapedString();b++);return b>=a.size()?!1:!0};IdentityCertificate.prototype.setPublicKeyName=function(){this.publicKeyName=IdentityCertificate.certificateNameToPublicKeyName(this.getName())};
+var Name=require("../../name.js").Name,SecurityException=require("../security-exception.js").SecurityException,SyncPromise=require("../../util/sync-promise.js").SyncPromise,IdentityStorage=function(){};exports.IdentityStorage=IdentityStorage;IdentityStorage.prototype.doesIdentityExistPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.doesIdentityExistPromise is not implemented"))};
+IdentityStorage.prototype.doesIdentityExist=function(a){return SyncPromise.getValue(this.doesIdentityExistPromise(a,!0))};IdentityStorage.prototype.addIdentityPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.addIdentityPromise is not implemented"))};IdentityStorage.prototype.addIdentity=function(a){return SyncPromise.getValue(this.addIdentityPromise(a,!0))};IdentityStorage.prototype.revokeIdentity=function(){return SyncPromise.reject(Error("IdentityStorage.revokeIdentity is not implemented"))};
+IdentityStorage.prototype.getNewKeyNamePromise=function(a,b,c){for(var d=Math.floor((new Date).getTime()/1E3);d<=IdentityStorage.lastTimestamp;)d+=1;IdentityStorage.lastTimestamp=d;d=""+d;b=b?"ksk-"+d:"dsk-"+d;var e=(new Name(a)).append(b);return this.doesKeyExistPromise(e,c).then(function(a){if(a)throw new SecurityException(Error("Key name already exists"));return SyncPromise.resolve(e)})};
+IdentityStorage.prototype.getNewKeyName=function(a,b){return SyncPromise.getValue(this.getNewKeyNamePromise(a,b,!0))};IdentityStorage.prototype.doesKeyExistPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.doesKeyExistPromise is not implemented"))};IdentityStorage.prototype.doesKeyExist=function(a){return SyncPromise.getValue(this.doesKeyExistPromise(a,!0))};IdentityStorage.prototype.addKeyPromise=function(a,b,c,d){return SyncPromise.reject(Error("IdentityStorage.addKeyPromise is not implemented"))};
+IdentityStorage.prototype.addKey=function(a,b,c){return SyncPromise.getValue(this.addKeyPromise(a,b,c,!0))};IdentityStorage.prototype.getKeyPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.getKeyPromise is not implemented"))};IdentityStorage.prototype.getKey=function(a){return SyncPromise.getValue(this.getKeyPromise(a,!0))};IdentityStorage.prototype.activateKey=function(a){throw Error("IdentityStorage.activateKey is not implemented");};
+IdentityStorage.prototype.deactivateKey=function(a){throw Error("IdentityStorage.deactivateKey is not implemented");};IdentityStorage.prototype.doesCertificateExistPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.doesCertificateExistPromise is not implemented"))};IdentityStorage.prototype.doesCertificateExist=function(a){return SyncPromise.getValue(this.doesCertificateExistPromise(a,!0))};IdentityStorage.prototype.addCertificatePromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.addCertificatePromise is not implemented"))};
+IdentityStorage.prototype.addCertificate=function(a){return SyncPromise.getValue(this.addCertificatePromise(a,!0))};IdentityStorage.prototype.getCertificatePromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.getCertificatePromise is not implemented"))};IdentityStorage.prototype.getCertificate=function(a){return SyncPromise.getValue(this.getValuePromise(a,!0))};IdentityStorage.prototype.getTpmLocatorPromise=function(a){return SyncPromise.reject(Error("IdentityStorage.getTpmLocatorPromise is not implemented"))};
+IdentityStorage.prototype.getTpmLocator=function(){return SyncPromise.getValue(this.getTpmLocatorPromise(!0))};IdentityStorage.prototype.getDefaultIdentityPromise=function(a){return SyncPromise.reject(Error("IdentityStorage.getDefaultIdentityPromise is not implemented"))};IdentityStorage.prototype.getDefaultIdentity=function(){return SyncPromise.getValue(this.getDefaultIdentityPromise(!0))};IdentityStorage.prototype.getDefaultKeyNameForIdentityPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.getDefaultKeyNameForIdentityPromise is not implemented"))};
+IdentityStorage.prototype.getDefaultKeyNameForIdentity=function(a){return SyncPromise.getValue(this.getDefaultKeyNameForIdentityPromise(a,!0))};IdentityStorage.prototype.getDefaultCertificateNameForIdentityPromise=function(a,b){var c=this;return this.getDefaultKeyNameForIdentityPromise(a).then(function(a){return c.getDefaultCertificateNameForKeyPromise(a)})};
+IdentityStorage.prototype.getDefaultCertificateNameForIdentity=function(a){return SyncPromise.getValue(this.getDefaultCertificateNameForIdentityPromise(a,!0))};IdentityStorage.prototype.getDefaultCertificateNameForKeyPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.getDefaultCertificateNameForKeyPromise is not implemented"))};IdentityStorage.prototype.getDefaultCertificateNameForKey=function(a){return SyncPromise.getValue(this.getDefaultCertificateNameForKeyPromise(a,!0))};
+IdentityStorage.prototype.getAllIdentitiesPromise=function(a,b,c){return SyncPromise.reject(Error("IdentityStorage.getAllIdentitiesPromise is not implemented"))};IdentityStorage.prototype.getAllKeyNamesOfIdentityPromise=function(a,b,c,d){return SyncPromise.reject(Error("IdentityStorage.getAllKeyNamesOfIdentityPromise is not implemented"))};IdentityStorage.prototype.getAllCertificateNamesOfKeyPromise=function(a,b,c,d){return SyncPromise.reject(Error("IdentityStorage.getAllCertificateNamesOfKeyPromise is not implemented"))};
+IdentityStorage.prototype.getAllKeyNamesOfIdentity=function(a,b,c){return SyncPromise.getValue(this.getAllKeyNamesOfIdentityPromise(a,b,c,!0))};IdentityStorage.prototype.setDefaultIdentityPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.setDefaultIdentityPromise is not implemented"))};IdentityStorage.prototype.setDefaultIdentity=function(a){return SyncPromise.getValue(this.setDefaultIdentityPromise(a,!0))};
+IdentityStorage.prototype.setDefaultKeyNameForIdentityPromise=function(a,b,c){return SyncPromise.reject(Error("IdentityStorage.setDefaultKeyNameForIdentityPromise is not implemented"))};IdentityStorage.prototype.setDefaultKeyNameForIdentity=function(a,b){return SyncPromise.getValue(this.setDefaultKeyNameForIdentityPromise(a,b,!0))};IdentityStorage.prototype.setDefaultCertificateNameForKeyPromise=function(a,b,c){return SyncPromise.reject(Error("IdentityStorage.setDefaultCertificateNameForKeyPromise is not implemented"))};
+IdentityStorage.prototype.setDefaultCertificateNameForKey=function(a,b){return SyncPromise.getValue(this.setDefaultCertificateNameForKeyPromise(a,b,!0))};IdentityStorage.prototype.getDefaultCertificatePromise=function(a){var b=this;return this.getDefaultIdentityPromise(a).then(function(c){return b.getDefaultCertificateNameForIdentityPromise(c,a)},function(a){return SyncPromise.resolve(null)}).then(function(c){return null==c?SyncPromise.resolve(null):b.getCertificatePromise(c,a)})};
+IdentityStorage.prototype.getDefaultCertificate=function(){return SyncPromise.getValue(this.getDefaultCertificatePromise(!0))};IdentityStorage.prototype.deleteCertificateInfoPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.deleteCertificateInfoPromise is not implemented"))};IdentityStorage.prototype.deleteCertificateInfo=function(a){return SyncPromise.getValue(this.deleteCertificateInfoPromise(a,!0))};IdentityStorage.prototype.deletePublicKeyInfoPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.deletePublicKeyInfoPromise is not implemented"))};
+IdentityStorage.prototype.deletePublicKeyInfo=function(a){return SyncPromise.getValue(this.deletePublicKeyInfoPromise(a,!0))};IdentityStorage.prototype.deleteIdentityInfoPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.deleteIdentityInfoPromise is not implemented"))};IdentityStorage.prototype.deleteIdentityInfo=function(a){return SyncPromise.getValue(this.deleteIdentityInfoPromise(a,!0))};IdentityStorage.lastTimestamp=Math.floor((new Date).getTime()/1E3);
+var IndexedDbIdentityStorage=function(){IdentityStorage.call(this);this.database=new Dexie("ndnsec-public-info");this.database.version(1).stores({globals:"key",identity:"identityNameUri",publicKey:"keyNameUri",certificate:"certificateNameUri"});this.database.open()};IndexedDbIdentityStorage.prototype=new IdentityStorage;IndexedDbIdentityStorage.prototype.name="IndexedDbIdentityStorage";
+IndexedDbIdentityStorage.prototype.doesIdentityExistPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.doesIdentityExistPromise is only supported for async"))):this.database.identity.where("identityNameUri").equals(a.toUri()).count().then(function(a){return Promise.resolve(0<a)})};
+IndexedDbIdentityStorage.prototype.addIdentityPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.addIdentityPromise is only supported for async")));var c=this;return this.doesIdentityExistPromise(a).then(function(b){return b?Promise.resolve():c.database.identity.put({identityNameUri:a.toUri(),defaultKeyUri:null})})};
+IndexedDbIdentityStorage.prototype.doesKeyExistPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.doesKeyExistPromise is only supported for async"))):this.database.publicKey.where("keyNameUri").equals(a.toUri()).count().then(function(a){return Promise.resolve(0<a)})};
+IndexedDbIdentityStorage.prototype.addKeyPromise=function(a,b,c,d){if(d)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.addKeyPromise is only supported for async")));if(0===a.size())return Promise.resolve();var e=this;return this.doesKeyExistPromise(a).then(function(d){if(d)return Promise.resolve();d=a.getPrefix(-1);return e.addIdentityPromise(d).then(function(){return e.database.publicKey.put({keyNameUri:a.toUri(),keyType:b,keyDer:(new Blob(c,!0)).buf(),defaultCertificate:null})})})};
+IndexedDbIdentityStorage.prototype.getKeyPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getKeyPromise is only supported for async"))):0===a.size()?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage::getKeyPromise: Empty keyName"))):this.database.publicKey.get(a.toUri()).then(function(a){return a?Promise.resolve(new Blob(a.keyDer)):Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage::getKeyPromise: The key does not exist")))})};
+IndexedDbIdentityStorage.prototype.doesCertificateExistPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.doesCertificateExistPromise is only supported for async"))):this.database.certificate.where("certificateNameUri").equals(a.toUri()).count().then(function(a){return Promise.resolve(0<a)})};
+IndexedDbIdentityStorage.prototype.addCertificatePromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.addCertificatePromise is only supported for async")));var c=a.getName(),d=a.getPublicKeyName(),e=this;return this.addKeyPromise(d,a.getPublicKeyInfo().getKeyType(),a.getPublicKeyInfo().getKeyDer(),b).then(function(){return e.doesCertificateExistPromise(c)}).then(function(b){return b?Promise.resolve():e.database.certificate.put({certificateNameUri:c.toUri(),
+encoding:a.wireEncode().buf()})})};IndexedDbIdentityStorage.prototype.getCertificatePromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getCertificatePromise is only supported for async"))):this.database.certificate.get(a.toUri()).then(function(a){if(a){var b=new IdentityCertificate;try{b.wireDecode(a.encoding)}catch(e){return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage::getCertificatePromise: The certificate cannot be decoded")))}return Promise.resolve(b)}return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage::getCertificatePromise: The certificate does not exist")))})};
+IndexedDbIdentityStorage.prototype.getDefaultIdentityPromise=function(a){return this.database.globals.get("defaultIdentityUri").then(function(a){if(a)return Promise.resolve(new Name(a.value));throw new SecurityException(Error("IndexedDbIdentityStorage.getDefaultIdentity: The default identity is not defined"));})};
+IndexedDbIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getDefaultKeyNameForIdentityPromise is only supported for async"))):this.database.identity.get(a.toUri()).then(function(a){if(a){if(null!=a.defaultKeyUri)return Promise.resolve(new Name(a.defaultKeyUri));throw new SecurityException(Error("No default key set."));}throw new SecurityException(Error("Identity not found."));})};
+IndexedDbIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getDefaultCertificateNameForKeyPromise is only supported for async"))):this.database.publicKey.get(a.toUri()).then(function(a){if(a){if(null!=a.defaultCertificateUri)return Promise.resolve(new Name(a.defaultCertificateUri));throw new SecurityException(Error("No default certificate set."));}throw new SecurityException(Error("Key not found."));
+})};
+IndexedDbIdentityStorage.prototype.getAllIdentitiesPromise=function(a,b,c){if(c)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getAllIdentitiesPromise is only supported for async")));var d=null,e=this;return this.getDefaultIdentityPromise().then(function(a){d=a;return SyncPromise.resolve()},function(a){return SyncPromise.resolve()}).then(function(){return e.database.identity.each(function(c){c=new Name(c.identityNameUri);var e=null!==d&&c.equals(d);b&&e?a.push(c):b||e||
+a.push(c)})})};
+IndexedDbIdentityStorage.prototype.getAllKeyNamesOfIdentityPromise=function(a,b,c,d){if(d)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getAllKeyNamesOfIdentityPromise is only supported for async")));var e=null,f=this;return this.getDefaultKeyNameForIdentityPromise(a).then(function(a){e=a;return SyncPromise.resolve()},function(a){return SyncPromise.resolve()}).then(function(){return f.database.publicKey.each(function(d){d=new Name(d.keyNameUri);if(d.getPrefix(-1).equals(a)){var f=null!==
+e&&d.equals(e);c&&f?b.push(d):c||f||b.push(d)}})})};
+IndexedDbIdentityStorage.prototype.getAllCertificateNamesOfKeyPromise=function(a,b,c,d){if(d)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getAllCertificateNamesOfKeyPromise is only supported for async")));var e=null,f=this;return this.getDefaultCertificateNameForKeyPromise(a).then(function(a){e=a;return SyncPromise.resolve()},function(a){return SyncPromise.resolve()}).then(function(){return f.database.certificate.each(function(d){d=new Name(d.certificateNameUri);if(IdentityCertificate.certificateNameToPublicKeyName(d).equals(a)){var f=
+null!==e&&d.equals(e);c&&f?b.push(d):c||f||b.push(d)}})})};IndexedDbIdentityStorage.prototype.setDefaultIdentityPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.setDefaultIdentityPromise is only supported for async")));var c=this;return this.doesIdentityExistPromise(a).then(function(b){return b?c.database.globals.put({key:"defaultIdentityUri",value:a.toUri()}):c.database.globals["delete"]("defaultIdentityUri")})};
+IndexedDbIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise=function(a,b,c){c="boolean"===typeof b?b:c;b=b instanceof Name?b:null;if(c)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.setDefaultKeyNameForIdentityPromise is only supported for async")));c=a.getPrefix(-1);return null!=b&&0<b.size()&&!b.equals(c)?Promise.reject(new SecurityException(Error("The specified identity name does not match the key name"))):this.database.identity.update(c.toUri(),{defaultKeyUri:a.toUri()})};
+IndexedDbIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise=function(a,b,c){return c?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.setDefaultCertificateNameForKeyPromise is only supported for async"))):this.database.publicKey.update(a.toUri(),{defaultCertificateUri:b.toUri()})};
+IndexedDbIdentityStorage.prototype.deleteCertificateInfoPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.deleteCertificateInfoPromise is only supported for async"))):0===a.size()?Promise.resolve():this.database.certificate["delete"](a.toUri())};
+IndexedDbIdentityStorage.prototype.deletePublicKeyInfoPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.deletePublicKeyInfoPromise is only supported for async")));if(0===a.size())return Promise.resolve();var c=this;return this.database.publicKey["delete"](a.toUri()).then(function(){return c.database.certificate.each(function(b){IdentityCertificate.certificateNameToPublicKeyName(new Name(b.certificateNameUri)).equals(a)&&c.database.certificate["delete"](b.certificateNameUri)})})};
+IndexedDbIdentityStorage.prototype.deleteIdentityInfoPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.deleteIdentityInfoPromise is only supported for async")));var c=this;return this.database.identity["delete"](a.toUri()).then(function(){return c.database.publicKey.each(function(b){(new Name(b.keyNameUri)).getPrefix(-1).equals(a)&&c.database.publicKey["delete"](b.keyNameUri)})}).then(function(){return c.database.certificate.each(function(b){IdentityCertificate.certificateNameToPublicKeyName(new Name(b.certificateNameUri)).getPrefix(-1).equals(a)&&
+c.database.certificate["delete"](b.certificateNameUri)})})};
+var Name=require("../../name.js").Name,Blob=require("../../util/blob.js").Blob,SecurityException=require("../security-exception.js").SecurityException,IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,SyncPromise=require("../../util/sync-promise.js").SyncPromise,IdentityStorage=require("./identity-storage.js").IdentityStorage,MemoryIdentityStorage=function(){IdentityStorage.call(this);this.identityStore={};this.defaultIdentity="";this.keyStore={};this.certificateStore=
+{}};MemoryIdentityStorage.prototype=new IdentityStorage;MemoryIdentityStorage.prototype.name="MemoryIdentityStorage";exports.MemoryIdentityStorage=MemoryIdentityStorage;MemoryIdentityStorage.prototype.doesIdentityExistPromise=function(a){return SyncPromise.resolve(void 0!==this.identityStore[a.toUri()])};MemoryIdentityStorage.prototype.addIdentityPromise=function(a){a=a.toUri();void 0===this.identityStore[a]&&(this.identityStore[a]={defaultKey:null});return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.doesKeyExistPromise=function(a){return SyncPromise.resolve(void 0!==this.keyStore[a.toUri()])};MemoryIdentityStorage.prototype.addKeyPromise=function(a,b,c){if(0===a.size()||this.doesKeyExist(a))return SyncPromise.resolve();var d=a.getSubName(0,a.size()-1);this.addIdentity(d);this.keyStore[a.toUri()]={keyType:b,keyDer:new Blob(c),defaultCertificate:null};return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.getKeyPromise=function(a){if(0===a.size())return SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage::getKeyPromise: Empty keyName")));a=a.toUri();a=this.keyStore[a];return void 0===a?SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage::getKeyPromise: The key does not exist"))):SyncPromise.resolve(a.keyDer)};MemoryIdentityStorage.prototype.doesCertificateExistPromise=function(a){return SyncPromise.resolve(void 0!==this.certificateStore[a.toUri()])};
+MemoryIdentityStorage.prototype.addCertificatePromise=function(a){var b=a.getName(),c=a.getPublicKeyName();this.addKey(c,a.getPublicKeyInfo().getKeyType(),a.getPublicKeyInfo().getKeyDer());if(this.doesCertificateExist(b))return SyncPromise.resolve();this.certificateStore[b.toUri()]=a.wireEncode();return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.getCertificatePromise=function(a){a=a.toUri();if(void 0===this.certificateStore[a])return SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage::getCertificatePromise: The certificate does not exist")));var b=new IdentityCertificate;try{b.wireDecode(this.certificateStore[a])}catch(c){return SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage::getCertificatePromise: The certificate cannot be decoded")))}return SyncPromise.resolve(b)};
+IdentityStorage.prototype.getTpmLocatorPromise=function(a){return SyncPromise.resolve("tpm-memory:")};MemoryIdentityStorage.prototype.getDefaultIdentityPromise=function(){return 0===this.defaultIdentity.length?SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage.getDefaultIdentity: The default identity is not defined"))):SyncPromise.resolve(new Name(this.defaultIdentity))};
+MemoryIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise=function(a){a=a.toUri();return void 0!==this.identityStore[a]?null!=this.identityStore[a].defaultKey?SyncPromise.resolve(this.identityStore[a].defaultKey):SyncPromise.reject(new SecurityException(Error("No default key set."))):SyncPromise.reject(new SecurityException(Error("Identity not found.")))};
+MemoryIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise=function(a){a=a.toUri();return void 0!==this.keyStore[a]?null!=this.keyStore[a].defaultCertificate?SyncPromise.resolve(this.keyStore[a].defaultCertificate):SyncPromise.reject(new SecurityException(Error("No default certificate set."))):SyncPromise.reject(new SecurityException(Error("Key not found.")))};
+MemoryIdentityStorage.prototype.setDefaultIdentityPromise=function(a){a=a.toUri();this.defaultIdentity=void 0!==this.identityStore[a]?a:"";return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise=function(a,b){b=b instanceof Name?b:null;var c=a.getPrefix(-1);if(null!=b&&0<b.size()&&!b.equals(c))return SyncPromise.reject(new SecurityException(Error("The specified identity name does not match the key name")));c=c.toUri();void 0!==this.identityStore[c]&&(this.identityStore[c].defaultKey=new Name(a));return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise=function(a,b){var c=a.toUri();void 0!==this.keyStore[c]&&(this.keyStore[c].defaultCertificate=new Name(b));return SyncPromise.resolve()};MemoryIdentityStorage.prototype.deleteCertificateInfoPromise=function(a){return SyncPromise.reject(Error("MemoryIdentityStorage.deleteCertificateInfoPromise is not implemented"))};MemoryIdentityStorage.prototype.deletePublicKeyInfoPromise=function(a){return SyncPromise.reject(Error("MemoryIdentityStorage.deletePublicKeyInfoPromise is not implemented"))};
+MemoryIdentityStorage.prototype.deleteIdentityInfoPromise=function(a){return SyncPromise.reject(Error("MemoryIdentityStorage.deleteIdentityInfoPromise is not implemented"))};var SyncPromise=require("../../util/sync-promise.js").SyncPromise,DerNode=require("../../encoding/der/der-node.js").DerNode,PrivateKeyStorage=function(){};exports.PrivateKeyStorage=PrivateKeyStorage;PrivateKeyStorage.prototype.generateKeyPairPromise=function(a,b,c){return SyncPromise.reject(Error("PrivateKeyStorage.generateKeyPairPromise is not implemented"))};
+PrivateKeyStorage.prototype.generateKeyPair=function(a,b){SyncPromise.getValue(this.generateKeyPairPromise(a,b,!0))};PrivateKeyStorage.prototype.deleteKeyPairPromise=function(a,b){return SyncPromise.reject(Error("PrivateKeyStorage.deleteKeyPairPromise is not implemented"))};PrivateKeyStorage.prototype.deleteKeyPair=function(a){SyncPromise.getValue(this.deleteKeyPairPromise(a,!0))};PrivateKeyStorage.prototype.getPublicKeyPromise=function(a,b){return SyncPromise.reject(Error("PrivateKeyStorage.getPublicKeyPromise is not implemented"))};
+PrivateKeyStorage.prototype.getPublicKey=function(a){return SyncPromise.getValue(this.getPublicKeyPromise(a,!0))};PrivateKeyStorage.prototype.signPromise=function(a,b,c,d){return SyncPromise.reject(Error("PrivateKeyStorage.sign is not implemented"))};PrivateKeyStorage.prototype.sign=function(a,b,c){return SyncPromise.getValue(this.signPromise(a,b,c,!0))};PrivateKeyStorage.prototype.decrypt=function(a,b,c){throw Error("PrivateKeyStorage.decrypt is not implemented");};
+PrivateKeyStorage.prototype.encrypt=function(a,b,c){throw Error("PrivateKeyStorage.encrypt is not implemented");};PrivateKeyStorage.prototype.generateKey=function(a,b){throw Error("PrivateKeyStorage.generateKey is not implemented");};PrivateKeyStorage.prototype.doesKeyExistPromise=function(a,b,c){return SyncPromise.reject(Error("PrivateKeyStorage.doesKeyExist is not implemented"))};PrivateKeyStorage.prototype.doesKeyExist=function(a,b){return SyncPromise.getValue(this.doesKeyExistPromise(a,b,!0))};
+PrivateKeyStorage.encodePkcs8PrivateKey=function(a,b,c){var d=new DerNode.DerSequence;d.addChild(new DerNode.DerOid(b));d.addChild(c);b=new DerNode.DerSequence;b.addChild(new DerNode.DerInteger(0));b.addChild(d);b.addChild(new DerNode.DerOctetString(a));return b.encode()};
+PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey=function(a){var b=new DerNode.DerSequence;b.addChild(new DerNode.DerInteger(0));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.n)));b.addChild(new DerNode.DerInteger(a.e));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.d)));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.p)));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.q)));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.dmp1)));
+b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.dmq1)));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.coeff)));return b.encode()};
+PrivateKeyStorage.encodePublicKeyFromRSAKey=function(a){var b=new DerNode.DerSequence;b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.n)));b.addChild(new DerNode.DerInteger(a.e));a=new DerNode.DerSequence;a.addChild(new DerNode.DerOid(new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID)));a.addChild(new DerNode.DerNull);var c=new DerNode.DerSequence;c.addChild(a);c.addChild(new DerNode.DerBitString(b.encode().buf(),0));return c.encode()};
+PrivateKeyStorage.bigIntegerToBuffer=function(a){a=a.toString(16);if("-"==a.substr(0,1))throw Error("PrivateKeyStorage.bigIntegerToBuffer: Negative integers are not currently supported");1==a.length%2?a="0"+a:a.match(/^[0-7]/)||(a="00"+a);return new Buffer(a,"hex")};PrivateKeyStorage.RSA_ENCRYPTION_OID="1.2.840.113549.1.1.1";PrivateKeyStorage.EC_ENCRYPTION_OID="1.2.840.10045.2.1";
+var Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,SecurityException=require("../security-exception.js").SecurityException,PublicKey=require("../certificate/public-key.js").PublicKey,KeyClass=require("../security-types.js").KeyClass,KeyType=require("../security-types").KeyType,DigestAlgorithm=require("../security-types.js").DigestAlgorithm,DataUtils=require("../../encoding/data-utils.js").DataUtils,PrivateKeyStorage=require("./private-key-storage.js").PrivateKeyStorage,
+DerNode=require("../../encoding/der/der-node.js").DerNode,OID=require("../../encoding/oid.js").OID,SyncPromise=require("../../util/sync-promise.js").SyncPromise,UseSubtleCrypto=require("../../use-subtle-crypto-node.js").UseSubtleCrypto,rsaKeygen=null;try{rsaKeygen=require("rsa-keygen")}catch(e$$44){}var MemoryPrivateKeyStorage=function(){PrivateKeyStorage.call(this);this.publicKeyStore={};this.privateKeyStore={}};MemoryPrivateKeyStorage.prototype=new PrivateKeyStorage;
+MemoryPrivateKeyStorage.prototype.name="MemoryPrivateKeyStorage";exports.MemoryPrivateKeyStorage=MemoryPrivateKeyStorage;MemoryPrivateKeyStorage.prototype.setPublicKeyForKeyName=function(a,b,c){this.publicKeyStore[a.toUri()]=new PublicKey(new Blob(c,!0))};
+MemoryPrivateKeyStorage.prototype.setPrivateKeyForKeyName=function(a,b,c){c=c.toString("base64");var d;if(b===KeyType.RSA){d="-----BEGIN RSA PRIVATE KEY-----\n";for(var e=0;e<c.length;e+=64)d+=c.substr(e,64)+"\n";d+="-----END RSA PRIVATE KEY-----"}else if(b===KeyType.ECDSA){d="-----BEGIN EC PRIVATE KEY-----\n";for(e=0;e<c.length;e+=64)d+=c.substr(e,64)+"\n";d+="-----END EC PRIVATE KEY-----"}else throw new SecurityException(Error("MemoryPrivateKeyStorage: KeyType is not supported"));this.privateKeyStore[a.toUri()]=
+{keyType:b,privateKey:d}};MemoryPrivateKeyStorage.prototype.setKeyPairForKeyName=function(a,b,c,d){this.setPublicKeyForKeyName(a,b,c);this.setPrivateKeyForKeyName(a,b,d)};
+MemoryPrivateKeyStorage.prototype.generateKeyPairPromise=function(a,b,c){if(this.doesKeyExist(a,KeyClass.PUBLIC))return SyncPromise.reject(new SecurityException(Error("Public key already exists")));if(this.doesKeyExist(a,KeyClass.PRIVATE))return SyncPromise.reject(new SecurityException(Error("Private key already exists")));var d=this;if(UseSubtleCrypto()&&!c){if(b.getKeyType()===KeyType.RSA){var e=null,f=null;return crypto.subtle.generateKey({name:"RSASSA-PKCS1-v1_5",modulusLength:b.getKeySize(),
+publicExponent:new Uint8Array([1,0,1]),hash:{name:"SHA-256"}},!0,["sign","verify"]).then(function(a){e=a.privateKey;return crypto.subtle.exportKey("spki",a.publicKey)}).then(function(a){f=(new Blob(new Uint8Array(a),!1)).buf();return crypto.subtle.exportKey("pkcs8",e)}).then(function(c){c=DerNode.parse((new Blob(new Uint8Array(c),!1)).buf()).getChildren()[2].toVal();d.setKeyPairForKeyName(a,b.getKeyType(),f,c.buf());d.privateKeyStore[a.toUri()].subtleKey=e;return Promise.resolve()})}return SyncPromise.reject(new SecurityException(Error("Only RSA key generation currently supported")))}return SyncPromise.resolve().then(function(){if("undefined"!==
+typeof RSAKey)if(b.getKeyType()===KeyType.RSA){var c=new RSAKey;c.generate(b.getKeySize(),"010001");d.setKeyPairForKeyName(a,b.getKeyType(),PrivateKeyStorage.encodePublicKeyFromRSAKey(c).buf(),PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey(c).buf())}else return SyncPromise.reject(new SecurityException(Error("Only RSA key generation currently supported")));else{var e;if(b.getKeyType()===KeyType.RSA){if(!rsaKeygen)return SyncPromise.reject(new SecurityException(Error("Need to install rsa-keygen: sudo npm install rsa-keygen")));
+e=rsaKeygen.generate(b.getKeySize());c=e.public_key.toString().replace("-----BEGIN PUBLIC KEY-----","").replace("-----END PUBLIC KEY-----","");c=new Buffer(c,"base64");e=e.private_key.toString()}else return SyncPromise.reject(new SecurityException(Error("Only RSA key generation currently supported")));d.setPublicKeyForKeyName(a,b.getKeyType(),c);d.privateKeyStore[a.toUri()]={keyType:b.getKeyType(),privateKey:e}}return SyncPromise.resolve()})};
+MemoryPrivateKeyStorage.prototype.deleteKeyPairPromise=function(a){a=a.toUri();delete this.publicKeyStore[a];delete this.privateKeyStore[a];return SyncPromise.resolve()};MemoryPrivateKeyStorage.prototype.getPublicKeyPromise=function(a){var b=a.toUri(),b=this.publicKeyStore[b];return void 0===b?SyncPromise.reject(new SecurityException(Error("MemoryPrivateKeyStorage: Cannot find public key "+a.toUri()))):SyncPromise.resolve(b)};
+MemoryPrivateKeyStorage.prototype.signPromise=function(a,b,c,d){d="boolean"===typeof c?c:d;c="boolean"!==typeof c&&c?c:DigestAlgorithm.SHA256;if(c!=DigestAlgorithm.SHA256)return SyncPromise.reject(new SecurityException(Error("MemoryPrivateKeyStorage.sign: Unsupported digest algorithm")));b=b.toUri();var e=this.privateKeyStore[b];if(void 0===e)return SyncPromise.reject(new SecurityException(Error("MemoryPrivateKeyStorage: Cannot find private key "+b)));if(UseSubtleCrypto()&&!d){var f={name:"RSASSA-PKCS1-v1_5",
+hash:{name:"SHA-256"}};e.subtleKey?d=crypto.subtle.sign(f,e.subtleKey,a):(d=DataUtils.privateKeyPemToDer(e.privateKey),d=PrivateKeyStorage.encodePkcs8PrivateKey(d,new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),new DerNode.DerNull).buf(),d=crypto.subtle.importKey("pkcs8",d.buffer,f,!0,["sign"]).then(function(b){e.subtleKey=b;return crypto.subtle.sign(f,b,a)}));return d.then(function(a){a=new Blob(new Uint8Array(a),!0);return Promise.resolve(a)})}if(e.keyType===KeyType.RSA)d=Crypto.createSign("RSA-SHA256");
+else if(e.keyType===KeyType.ECDSA)d=Crypto.createSign("sha256");else return SyncPromise.reject(new SecurityException(Error("MemoryPrivateKeyStorage.sign: Unrecognized private key type")));d.update(a);d=new Buffer(DataUtils.toNumbersIfString(d.sign(e.privateKey)));d=new Blob(d,!1);return SyncPromise.resolve(d)};
+MemoryPrivateKeyStorage.prototype.doesKeyExistPromise=function(a,b){var c=a.toUri(),d=!1;b==KeyClass.PUBLIC?d=void 0!==this.publicKeyStore[c]:b==KeyClass.PRIVATE&&(d=void 0!==this.privateKeyStore[c]);return SyncPromise.resolve(d)};var Crypto=require("../../crypto.js"),IndexedDbPrivateKeyStorage=function(){PrivateKeyStorage.call(this);this.database=new Dexie("ndnsec-tpm");this.database.version(1).stores({publicKey:"nameHash",privateKey:"nameHash"});this.database.open()};
+IndexedDbPrivateKeyStorage.prototype=new PrivateKeyStorage;IndexedDbPrivateKeyStorage.prototype.name="IndexedDbPrivateKeyStorage";
+IndexedDbPrivateKeyStorage.prototype.generateKeyPairPromise=function(a,b,c){if(c)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.generateKeyPairPromise is only supported for async")));var d=this;return d.doesKeyExistPromise(a,KeyClass.PUBLIC).then(function(b){if(b)throw Error("Public key already exists");return d.doesKeyExistPromise(a,KeyClass.PRIVATE)}).then(function(c){if(c)throw Error("Private key already exists");if(b.getKeyType()===KeyType.RSA){var f=null,g=null;
+return crypto.subtle.generateKey({name:"RSASSA-PKCS1-v1_5",modulusLength:b.getKeySize(),publicExponent:new Uint8Array([1,0,1]),hash:{name:"SHA-256"}},!0,["sign","verify"]).then(function(a){f=a.privateKey;return crypto.subtle.exportKey("spki",a.publicKey)}).then(function(a){g=new Uint8Array(a);return crypto.subtle.exportKey("pkcs8",f)}).then(function(b){return d.database.transaction("rw",d.database.privateKey,d.database.publicKey,function(){d.database.publicKey.put({nameHash:IndexedDbPrivateKeyStorage.transformName(a),
+encoding:g});d.database.privateKey.put({nameHash:IndexedDbPrivateKeyStorage.transformName(a),encoding:new Uint8Array(b)})})})}throw Error("Only RSA key generation currently supported");})};IndexedDbPrivateKeyStorage.prototype.deleteKeyPairPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.deleteKeyPairPromise is only supported for async")));var c=this;return this.database.publicKey["delete"](IndexedDbPrivateKeyStorage.transformName(a)).then(function(){return c.database.privateKey["delete"](IndexedDbPrivateKeyStorage.transformName(a))})};
+IndexedDbPrivateKeyStorage.prototype.getPublicKeyPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.getPublicKeyPromise is only supported for async"))):this.database.publicKey.get(IndexedDbPrivateKeyStorage.transformName(a)).then(function(a){return Promise.resolve(new PublicKey(new Blob(a.encoding)))})};
+IndexedDbPrivateKeyStorage.prototype.signPromise=function(a,b,c,d){d="boolean"===typeof c?c:d;c="boolean"!==typeof c&&c?c:DigestAlgorithm.SHA256;if(d)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.signPromise is only supported for async")));if(c!=DigestAlgorithm.SHA256)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.sign: Unsupported digest algorithm")));var e={name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};return this.database.privateKey.get(IndexedDbPrivateKeyStorage.transformName(b)).then(function(a){return crypto.subtle.importKey("pkcs8",
+(new Blob(a.encoding)).buf(),e,!0,["sign"])}).then(function(b){return crypto.subtle.sign(e,b,a)}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!0))})};
+IndexedDbPrivateKeyStorage.prototype.doesKeyExistPromise=function(a,b,c){if(c)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.doesKeyExistPromise is only supported for async")));c=null;if(b==KeyClass.PUBLIC)c=this.database.publicKey;else if(b==KeyClass.PRIVATE)c=this.database.privateKey;else return Promise.resolve(!1);return c.where("nameHash").equals(IndexedDbPrivateKeyStorage.transformName(a)).count().then(function(a){return Promise.resolve(0<a)})};
+IndexedDbPrivateKeyStorage.transformName=function(a){var b=Crypto.createHash("sha256");b.update(new Buffer(a.toUri()));return b.digest("base64").replace(/\//g,"%")};
+var Crypto=require("../../crypto.js"),Name=require("../../name.js").Name,Data=require("../../data.js").Data,Blob=require("../../util/blob.js").Blob,ConfigFile=require("../../util/config-file.js").ConfigFile,DigestSha256Signature=require("../../digest-sha256-signature.js").DigestSha256Signature,Sha256WithRsaSignature=require("../../sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("../../sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,KeyLocatorType=require("../../key-locator.js").KeyLocatorType,
+WireFormat=require("../../encoding/wire-format.js").WireFormat,SecurityException=require("../security-exception.js").SecurityException,DigestAlgorithm=require("../security-types.js").DigestAlgorithm,KeyType=require("../security-types.js").KeyType,RsaKeyParams=require("../key-params.js").RsaKeyParams,IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,PublicKey=require("../certificate/public-key.js").PublicKey,CertificateSubjectDescription=require("../certificate/certificate-subject-description.js").CertificateSubjectDescription,
+SyncPromise=require("../../util/sync-promise.js").SyncPromise,BasicIdentityStorage=require("./basic-identity-storage.js").BasicIdentityStorage,FilePrivateKeyStorage=require("./file-private-key-storage.js").FilePrivateKeyStorage,IdentityManager=function IdentityManager(b,c){if(c){if(!b)throw Error("IdentityManager: A custom privateKeyStorage is supplied with a null identityStorage");this.identityStorage=b;this.privateKeyStorage=c}else{if(!ConfigFile)throw new SecurityException(Error("IdentityManager: If not in Node.js then you must supply identityStorage and privateKeyStorage."));
+var d=new ConfigFile,e=[null],f=this;this.identityStorage=b?b:IdentityManager.getDefaultIdentityStorage_(d,function(){return f.checkTpmPromise_(e[0])});this.privateKeyStorage=IdentityManager.getDefaultPrivateKeyStorage_(d,e)}};exports.IdentityManager=IdentityManager;
+IdentityManager.prototype.createIdentityAndCertificatePromise=function(a,b,c){var d=this,e=!0,f=null;return this.identityStorage.addIdentityPromise(a,c).then(function(){return d.identityStorage.getDefaultKeyNameForIdentityPromise(a,c).then(function(a){f=a;return d.identityStorage.getKeyPromise(f,c).then(function(a){(new PublicKey(a)).getKeyType()==b.getKeyType()&&(e=!1);return SyncPromise.resolve()})},function(a){if(!(a instanceof SecurityException))throw a;return SyncPromise.resolve()})}).then(function(){return e?
+d.generateKeyPairPromise(a,!0,b,c).then(function(a){f=a;return d.identityStorage.setDefaultKeyNameForIdentityPromise(f,c)}):SyncPromise.resolve()}).then(function(){return d.identityStorage.getDefaultCertificateNameForKeyPromise(f,c).then(function(a){return SyncPromise.resolve(a)},function(a){if(!(a instanceof SecurityException))throw a;var b;return d.selfSignPromise(f,c).then(function(a){b=a.getName();return d.addCertificateAsIdentityDefaultPromise(a,c)}).then(function(){return SyncPromise.resolve(b)})})})};
+IdentityManager.prototype.createIdentityAndCertificate=function(a,b,c,d){return SyncPromise.complete(c,d,this.createIdentityAndCertificatePromise(a,b,!c))};IdentityManager.prototype.createIdentity=function(a,b){return IdentityCertificate.certificateNameToPublicKeyName(this.createIdentityAndCertificate(a,b))};
+IdentityManager.prototype.deleteIdentity=function(a,b,c){var d=this,e=!0,f=this.identityStorage.getDefaultIdentityPromise(!b).then(function(b){b.equals(a)&&(e=!1);return SyncPromise.resolve()},function(a){return SyncPromise.resolve()}).then(function(){if(!e)return SyncPromise.resolve();var b=[];return d.identityStorage.getAllKeyNamesOfIdentityPromise(a,b,!0).then(function(){return d.identityStorage.getAllKeyNamesOfIdentityPromise(a,b,!1)}).then(function(){return d.identityStorage.deleteIdentityInfoPromise(a)}).then(function(){function a(c){return c>=
+b.length?SyncPromise.resolve():d.privateKeyStorage.deleteKeyPairPromise(b[c]).then(function(){return a(c+1)})}return a(0)})});return SyncPromise.complete(b,c,f)};IdentityManager.prototype.setDefaultIdentityPromise=function(a,b){return this.identityStorage.setDefaultIdentityPromise(a,b)};IdentityManager.prototype.setDefaultIdentity=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.setDefaultIdentityPromise(a,!b))};IdentityManager.prototype.getDefaultIdentityPromise=function(a){return this.identityStorage.getDefaultIdentityPromise(a)};
+IdentityManager.prototype.getDefaultIdentity=function(a,b){return SyncPromise.complete(a,b,this.identityStorage.getDefaultIdentityPromise(!a))};IdentityManager.prototype.getDefaultCertificatePromise=function(a){return this.identityStorage.getDefaultCertificatePromise(a)};IdentityManager.prototype.generateRSAKeyPair=function(a,b,c){return SyncPromise.getValue(this.generateKeyPairPromise(a,b,new RsaKeyParams(c),!0))};
+IdentityManager.prototype.setDefaultKeyForIdentity=function(a,b,c,d){d="function"===typeof b?c:d;c="function"===typeof b?b:c;b="function"!==typeof b&&b?b:new Name;return SyncPromise.complete(c,d,this.identityStorage.setDefaultKeyNameForIdentityPromise(a,b,!c))};IdentityManager.prototype.getDefaultKeyNameForIdentity=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.getDefaultKeyNameForIdentityPromise(a,!b))};
+IdentityManager.prototype.generateRSAKeyPairAsDefaultPromise=function(a,b,c,d){var e,f=this;return this.generateKeyPairPromise(a,b,new RsaKeyParams(c)).then(function(a){e=a;return f.identityStorage.setDefaultKeyNameForIdentityPromise(e)}).then(function(){return SyncPromise.resolve(e)})};IdentityManager.prototype.generateRSAKeyPairAsDefault=function(a,b,c){return SyncPromise.getValue(this.generateRSAKeyPairAsDefaultPromise(a,b,c,!0))};
+IdentityManager.prototype.getPublicKey=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.getKeyPromise(a,!b).then(function(a){return SyncPromise.resolve(new PublicKey(a))}))};
+IdentityManager.prototype.prepareUnsignedIdentityCertificate=function(a,b,c,d,e,f,g,h,k){b instanceof PublicKey||(k=h,h=g,g=f,f=e,e=d,d=c,c=b,b=null);var l=g,m=h;g=l instanceof Name?l:null;"function"===typeof l?(h=l,k=m):"function"===typeof m?h=m:k=h=null;a=null==b?this.prepareUnsignedIdentityCertificatePromise(a,c,d,e,f,g,!h):this.prepareUnsignedIdentityCertificatePromise(a,b,c,d,e,f,g,!h);return SyncPromise.complete(h,k,a)};
+IdentityManager.prototype.prepareUnsignedIdentityCertificatePromise=function(a,b,c,d,e,f,g,h){b instanceof PublicKey||(h=g,g=f,f=e,e=d,d=c,c=b,b=null);var k=g;g=k instanceof Name?k:null;return(null==b?this.identityStorage.getKeyPromise(a,"boolean"===typeof k?k:"boolean"===typeof h?h:!1).then(function(a){b=new PublicKey(a);return SyncPromise.resolve()}):SyncPromise.resolve()).then(function(){return SyncPromise.resolve(IdentityManager.prepareUnsignedIdentityCertificateHelper_(a,b,c,d,e,f,g))})};
+IdentityManager.prepareUnsignedIdentityCertificateHelper_=function(a,b,c,d,e,f,g){if(1>a.size())return null;var h=a.get(-1).toEscapedString();if(4>h.length)return null;keyIdPrefix=h.substr(0,4);if("ksk-"!=keyIdPrefix&&"dsk-"!=keyIdPrefix)return null;var h=new IdentityCertificate,k=new Name;if(null==g)c.match(a)?k.append(c).append("KEY").append(a.getSubName(c.size())).append("ID-CERT").appendVersion((new Date).getTime()):k.append(a.getPrefix(-1)).append("KEY").append(a.get(-1)).append("ID-CERT").appendVersion((new Date).getTime());
+else if(g.match(a)&&!g.equals(a))k.append(g).append("KEY").append(a.getSubName(g.size())).append("ID-CERT").appendVersion((new Date).getTime());else return null;h.setName(k);h.setNotBefore(d);h.setNotAfter(e);h.setPublicKeyInfo(b);if(null==f||0===f.length)h.addSubjectDescription(new CertificateSubjectDescription("2.5.4.41",a.getPrefix(-1).toUri()));else for(a=0;a<f.length;++a)h.addSubjectDescription(f[a]);try{h.encode()}catch(l){throw SecurityException(Error("DerEncodingException: "+l));}return h};
+IdentityManager.prototype.addCertificate=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.addCertificatePromise(a,!b))};IdentityManager.prototype.setDefaultCertificateForKeyPromise=function(a,b){var c=this,d=a.getPublicKeyName();return this.identityStorage.doesKeyExistPromise(d,b).then(function(e){if(!e)throw new SecurityException(Error("No corresponding Key record for certificate!"));return c.identityStorage.setDefaultCertificateNameForKeyPromise(d,a.getName(),b)})};
+IdentityManager.prototype.setDefaultCertificateForKey=function(a,b,c){return SyncPromise.complete(b,c,this.setDefaultCertificateForKeyPromise(a,!b))};IdentityManager.prototype.addCertificateAsIdentityDefaultPromise=function(a,b){var c=this;return this.identityStorage.addCertificatePromise(a,b).then(function(){var d=a.getPublicKeyName();return c.identityStorage.setDefaultKeyNameForIdentityPromise(d,b)}).then(function(){return c.setDefaultCertificateForKeyPromise(a,b)})};
+IdentityManager.prototype.addCertificateAsDefault=function(a,b,c){var d=!b,e=this;return SyncPromise.complete(b,c,this.identityStorage.addCertificatePromise(a,d).then(function(){return e.setDefaultCertificateForKeyPromise(a,d)}))};IdentityManager.prototype.getCertificate=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.getCertificatePromise(a,!1,!b))};
+IdentityManager.prototype.getDefaultCertificateNameForIdentityPromise=function(a,b){return this.identityStorage.getDefaultCertificateNameForIdentityPromise(a,b)};IdentityManager.prototype.getDefaultCertificateNameForIdentity=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.getDefaultCertificateNameForIdentityPromise(a,!b))};
+IdentityManager.prototype.getDefaultCertificateName=function(a,b){var c=!a,d=this;return SyncPromise.complete(a,b,this.identityStorage.getDefaultIdentityPromise(c).then(function(a){return d.identityStorage.getDefaultCertificateNameForIdentityPromise(a,c)}))};IdentityManager.prototype.getAllIdentities=function(a,b,c,d){return SyncPromise.complete(c,d,this.identityStorage.getAllIdentitiesPromise(a,b,!c))};
+IdentityManager.prototype.getAllKeyNamesOfIdentity=function(a,b,c,d,e){return SyncPromise.complete(d,e,this.identityStorage.getAllKeyNamesOfIdentityPromise(a,b,c,!d))};IdentityManager.prototype.getAllCertificateNamesOfKey=function(a,b,c,d,e){return SyncPromise.complete(d,e,this.identityStorage.getAllCertificateNamesOfKeyPromise(a,b,c,!d))};
+IdentityManager.prototype.signByCertificatePromise=function(a,b,c,d){d="boolean"===typeof c?c:d;c="boolean"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();var e=IdentityManager.certificateNameToPublicKeyName(b),f=this;if(a instanceof Data){var g=[0];return this.makeSignatureByCertificatePromise(b,g,d).then(function(b){a.setSignature(b);b=a.wireEncode(c);return f.privateKeyStorage.signPromise(b.signedBuf(),e,g[0],d)}).then(function(b){a.getSignature().setSignature(b);a.wireEncode(c);return SyncPromise.resolve(a)})}g=
+[0];return this.makeSignatureByCertificatePromise(b,g,d).then(function(b){return f.privateKeyStorage.signPromise(a,e,g[0],d)}).then(function(a){signature.setSignature(a);return SyncPromise.resolve(signature)})};IdentityManager.prototype.signByCertificate=function(a,b,c,d,e){e="function"===typeof c?d:e;d="function"===typeof c?c:d;c="function"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();return SyncPromise.complete(d,e,this.signByCertificatePromise(a,b,c,!d))};
+IdentityManager.prototype.signInterestByCertificatePromise=function(a,b,c,d){d="boolean"===typeof c?c:d;c="boolean"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();var e=this,f,g=[0];return this.makeSignatureByCertificatePromise(b,g,d).then(function(h){f=h;a.getName().append(c.encodeSignatureInfo(f));a.getName().append(new Name.Component);h=a.wireEncode(c);var k=IdentityManager.certificateNameToPublicKeyName(b);return e.privateKeyStorage.signPromise(h.signedBuf(),k,g[0],d)}).then(function(b){f.setSignature(b);
+a.setName(a.getName().getPrefix(-1).append(c.encodeSignatureValue(f)));return SyncPromise.resolve(a)})};IdentityManager.prototype.signInterestByCertificate=function(a,b,c,d,e){e="function"===typeof c?d:e;d="function"===typeof c?c:d;c="function"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();return SyncPromise.complete(d,e,this.signInterestByCertificatePromise(a,b,c,!d))};
+IdentityManager.prototype.signWithSha256=function(a,b){b=b||WireFormat.getDefaultWireFormat();a.setSignature(new DigestSha256Signature);var c=a.wireEncode(b),d=Crypto.createHash("sha256");d.update(c.signedBuf());a.getSignature().setSignature(new Blob(d.digest(),!1));a.wireEncode(b)};
+IdentityManager.prototype.signInterestWithSha256=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=new DigestSha256Signature;a.getName().append(b.encodeSignatureInfo(c));a.getName().append(new Name.Component);var d=a.wireEncode(b),e=Crypto.createHash("sha256");e.update(d.signedBuf());c.setSignature(new Blob(e.digest(),!1));a.setName(a.getName().getPrefix(-1).append(b.encodeSignatureValue(c)))};
+IdentityManager.prototype.selfSignPromise=function(a,b){var c=new IdentityCertificate,d=this;return this.identityStorage.getKeyPromise(a,b).then(function(e){e=new PublicKey(e);var f=(new Date).getTime(),g=f+63072E6;c.setNotBefore(f);c.setNotAfter(g);f=a.getPrefix(-1).append("KEY").append(a.get(-1)).append("ID-CERT").appendVersion(c.getNotBefore());c.setName(f);c.setPublicKeyInfo(e);c.addSubjectDescription(new CertificateSubjectDescription("2.5.4.41",a.toUri()));c.encode();return d.signByCertificatePromise(c,
+c.getName(),b)})};IdentityManager.prototype.selfSign=function(a,b,c){return SyncPromise.complete(b,c,this.selfSignPromise(a,!b))};IdentityManager.certificateNameToPublicKeyName=function(a){for(var b=a.size()-1;0<=b&&"ID-CERT"!=a.get(b).toEscapedString();)--b;a=a.getSubName(0,b);for(b=0;b<a.size()&&"KEY"!=a.get(b).toEscapedString();)++b;return a.getSubName(0,b).append(a.getSubName(b+1,a.size()-b-1))};
+IdentityManager.prototype.makeSignatureByCertificatePromise=function(a,b,c){var d=IdentityManager.certificateNameToPublicKeyName(a);return this.privateKeyStorage.getPublicKeyPromise(d,c).then(function(c){c=c.getKeyType();var d=null;if(c==KeyType.RSA)d=new Sha256WithRsaSignature,b[0]=DigestAlgorithm.SHA256,d.getKeyLocator().setType(KeyLocatorType.KEYNAME),d.getKeyLocator().setKeyName(a.getPrefix(-1));else if(c==KeyType.ECDSA)d=new Sha256WithEcdsaSignature,b[0]=DigestAlgorithm.SHA256,d.getKeyLocator().setType(KeyLocatorType.KEYNAME),
+d.getKeyLocator().setKeyName(a.getPrefix(-1));else throw new SecurityException(Error("Key type is not recognized"));return SyncPromise.resolve(d)})};
+IdentityManager.prototype.generateKeyPairPromise=function(a,b,c,d){var e,f=this;return this.identityStorage.getNewKeyNamePromise(a,b,d).then(function(a){e=a;return f.privateKeyStorage.generateKeyPairPromise(e,c,d)}).then(function(){return f.privateKeyStorage.getPublicKeyPromise(e,d)}).then(function(a){return f.identityStorage.addKeyPromise(e,c.getKeyType(),a.getKeyDer())}).then(function(){return SyncPromise.resolve(e)})};
+IdentityManager.getDefaultIdentityStorage_=function(a,b){var c=a.get("pib","");if(""!==c&&"pib-sqlite3"!==c)throw new SecurityException(Error("Invalid config file pib value: "+c));return new BasicIdentityStorage(b)};
+IdentityManager.getDefaultPrivateKeyStorage_=function(a,b){var c=a.get("tpm","");if(""===c){if("darwin"===process.platform)throw b[0]="tpm-osxkeychain:",new SecurityException(Error("IdentityManager: OS X key chain storage is not yet implemented. You must supply a privateKeyStorage."));b[0]="tpm-file:";return new FilePrivateKeyStorage}if("tpm-osxkeychain"===c)throw b[0]="tpm-osxkeychain:",new SecurityException(Error("IdentityManager: tpm-osxkeychain is not yet implemented."));if("tpm-file"===c)return b[0]=
+"tpm-file:",new FilePrivateKeyStorage;throw new SecurityException(Error("Invalid config file tpm value: "+c));};IdentityManager.prototype.checkTpmPromise_=function(a){return this.identityStorage.getTpmLocatorPromise().then(function(b){return""!==b&&b!==a?Promise.reject(new SecurityException(Error("The TPM locator supplied does not match the TPM locator in the PIB: "+b+" != "+a))):Promise.resolve()},function(a){return Promise.resolve()})};
+var ValidationRequest=function(a,b,c,d,e){this.interest=a;this.onVerified=b;this.onValidationFailed=c;this.retry=d;this.stepCount=e};exports.ValidationRequest=ValidationRequest;
+var Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,DataUtils=require("../../encoding/data-utils.js").DataUtils,SecurityException=require("../security-exception.js").SecurityException,DigestSha256Signature=require("../../digest-sha256-signature.js").DigestSha256Signature,Sha256WithRsaSignature=require("../../sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("../../sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,UseSubtleCrypto=
+require("../../use-subtle-crypto-node.js").UseSubtleCrypto,PolicyManager=function(){};exports.PolicyManager=PolicyManager;PolicyManager.prototype.skipVerifyAndTrust=function(a){throw Error("PolicyManager.skipVerifyAndTrust is not implemented");};PolicyManager.prototype.requireVerify=function(a){throw Error("PolicyManager.requireVerify is not implemented");};PolicyManager.prototype.checkVerificationPolicy=function(a,b,c,d,e){throw Error("PolicyManager.checkVerificationPolicy is not implemented");};
+PolicyManager.prototype.checkSigningPolicy=function(a,b){throw Error("PolicyManager.checkSigningPolicy is not implemented");};PolicyManager.prototype.inferSigningIdentity=function(a){throw Error("PolicyManager.inferSigningIdentity is not implemented");};PolicyManager.verifyUsesString_=null;PolicyManager.setVerifyUsesString_=function(){var a=Crypto.createHash("sha256").digest();PolicyManager.verifyUsesString_="string"===typeof a};
+PolicyManager.verifySignature=function(a,b,c,d){if(a instanceof Sha256WithRsaSignature)c.isNull()?d(!1):PolicyManager.verifySha256WithRsaSignature(a.getSignature(),b,c,d);else if(a instanceof Sha256WithEcdsaSignature)c.isNull()?d(!1):PolicyManager.verifySha256WithEcdsaSignature(a.getSignature(),b,c,d);else if(a instanceof DigestSha256Signature)PolicyManager.verifyDigestSha256Signature(a.getSignature(),b,d);else throw new SecurityException(Error("PolicyManager.verify: Signature type is unknown"));
+};
+PolicyManager.verifySha256WithRsaSignature=function(a,b,c,d){if(UseSubtleCrypto()){var e={name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};crypto.subtle.importKey("spki",c.buf().buffer,e,!0,["verify"]).then(function(c){return crypto.subtle.verify(e,c,a.buf(),b.signedBuf())}).then(function(a){d(a)})}else{null===PolicyManager.verifyUsesString_&&PolicyManager.setVerifyUsesString_();var f=c.buf().toString("base64");c="-----BEGIN PUBLIC KEY-----\n";for(var g=0;g<f.length;g+=64)c+=f.substr(g,64)+"\n";c+=
+"-----END PUBLIC KEY-----";f=Crypto.createVerify("RSA-SHA256");f.update(b.signedBuf());g=PolicyManager.verifyUsesString_?DataUtils.toString(a.buf()):a.buf();d(f.verify(c,g))}};
+PolicyManager.verifySha256WithEcdsaSignature=function(a,b,c,d){if(UseSubtleCrypto())d(!1);else{null===PolicyManager.verifyUsesString_&&PolicyManager.setVerifyUsesString_();var e=c.buf().toString("base64");c="-----BEGIN PUBLIC KEY-----\n";for(var f=0;f<e.length;f+=64)c+=e.substr(f,64)+"\n";c+="-----END PUBLIC KEY-----";e=Crypto.createVerify("sha256");e.update(b.signedBuf());a=PolicyManager.verifyUsesString_?DataUtils.toString(a.buf()):a.buf();d(e.verify(c,a))}};
+PolicyManager.verifyDigestSha256Signature=function(a,b,c){var d=Crypto.createHash("sha256");d.update(b.signedBuf());b=new Blob(d.digest(),!1);c(b.equals(a))};var IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,CertificateCache=function(){this.cache={}};exports.CertificateCache=CertificateCache;CertificateCache.prototype.insertCertificate=function(a){var b=a.getName().getPrefix(-1);this.cache[b.toUri()]=a.wireEncode()};
+CertificateCache.prototype.deleteCertificate=function(a){delete this.cache[a.toUri()]};CertificateCache.prototype.getCertificate=function(a){a=this.cache[a.toUri()];if(void 0===a)return null;var b=new IdentityCertificate;b.wireDecode(a);return b};CertificateCache.prototype.reset=function(){this.cache={}};
+var fs=require("fs"),path=require("path"),Name=require("../../name.js").Name,Data=require("../../data.js").Data,Interest=require("../../interest.js").Interest,KeyLocator=require("../../key-locator.js").KeyLocator,KeyLocatorType=require("../../key-locator.js").KeyLocatorType,Blob=require("../../util/blob.js").Blob,IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,BoostInfoParser=require("../../util/boost-info-parser.js").BoostInfoParser,NdnRegexMatcher=require("../../util/ndn-regex-matcher.js").NdnRegexMatcher,
+CertificateCache=require("./certificate-cache.js").CertificateCache,ValidationRequest=require("./validation-request.js").ValidationRequest,SecurityException=require("../security-exception.js").SecurityException,WireFormat=require("../../encoding/wire-format.js").WireFormat,PolicyManager=require("./policy-manager.js").PolicyManager,NdnCommon=require("../../util/ndn-common.js").NdnCommon,ConfigPolicyManager=function(a,b,c,d,e,f){PolicyManager.call(this);void 0==b&&(b=null);void 0==c&&(c=5);void 0==
+d&&(d=3E3);void 0==e&&(e=36E5);void 0==f&&(f=1E3);this.certificateCache=null==b?new CertificateCache:b;this.maxDepth=c;this.keyGraceInterval=d;this.keyTimestampTtl=e;this.maxTrackedKeys=f;this.reset();null!=a&&""!=a&&this.load(a)};ConfigPolicyManager.prototype=new PolicyManager;ConfigPolicyManager.prototype.name="ConfigPolicyManager";exports.ConfigPolicyManager=ConfigPolicyManager;
+ConfigPolicyManager.prototype.reset=function(){this.certificateCache.reset();this.fixedCertificateCache={};this.keyTimestamps={};this.requiresVerification=!0;this.config=new BoostInfoParser;this.refreshManager=new ConfigPolicyManager.TrustAnchorRefreshManager};ConfigPolicyManager.prototype.load=function(a,b){this.reset();this.config.read(a,b);this.loadTrustAnchorCertificates()};ConfigPolicyManager.prototype.requireVerify=function(a){return this.requiresVerification};
+ConfigPolicyManager.prototype.checkSigningPolicy=function(a,b){return!0};ConfigPolicyManager.prototype.skipVerifyAndTrust=function(a){return!this.requiresVerification};
+ConfigPolicyManager.prototype.checkVerificationPolicy=function(a,b,c,d,e){if(b>this.maxDepth){try{d(a,"The verification stepCount "+b+" exceeded the maxDepth "+this.maxDepth)}catch(f){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(f))}return null}e=ConfigPolicyManager.extractSignature(a,e);if(null==e){try{d(a,"Cannot extract the signature from "+a.getName().toUri())}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}return null}if(!KeyLocator.canGetFromSignature(e)){try{d(a,
+"The signature type does not support a KeyLocator")}catch(h){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(h))}return null}var k=null;try{k=KeyLocator.getFromSignature(e)}catch(l){try{d(a,"Error in KeyLocator.getFromSignature: "+l)}catch(m){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(m))}return null}k=k.getKeyName();if(0==k.size()){try{d(a,"The signature KeyLocator doesn't have a key name")}catch(q){console.log("Error in onValidationFailed: "+
+NdnCommon.getErrorWithStackTrace(q))}return null}var p=a.getName(),s="data";a instanceof Interest&&(p=p.getPrefix(-4),s="interest");var w=this.findMatchingRule(p,s);if(null==w){try{d(a,"No matching rule found for "+p.toUri())}catch(M){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(M))}return null}s=["unknown"];if(!this.checkSignatureMatch(k,p,w,s)){try{d(a,s[0])}catch(O){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(O))}return null}this.refreshManager.refreshAnchors();
+p=this.refreshManager.getCertificate(k);null==p&&(p=this.certificateCache.getCertificate(k));var K=this;if(null==p)return e=new Interest(k),new ValidationRequest(e,function(e){var f;try{f=new IdentityCertificate(e)}catch(g){try{d(a,"Cannot decode certificate "+e.getName().toUri())}catch(h){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(h))}return null}K.certificateCache.insertCertificate(f);K.checkVerificationPolicy(a,b+1,c,d)},d,2,b+1);if(a instanceof Interest){var x=
+p.getPublicKeyName(),A=a.getName().get(-4).toNumber();if(!this.interestTimestampIsFresh(x,A,s)){try{d(a,s[0])}catch(I){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(I))}return null}}this.verify(e,a.wireEncode(),function(b,e){if(b){try{c(a)}catch(f){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(f))}a instanceof Interest&&K.updateTimestampForKey(x,A)}else try{d(a,e)}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}})};
+ConfigPolicyManager.prototype.loadTrustAnchorCertificates=function(){for(var a=this.config.getRoot().get("validator/trust-anchor"),b=0;b<a.length;++b){var c=a[b],d=c.get("type")[0].getValue(),e=!1,f;if("file"==d)f=c.get("file-name")[0].getValue(),e=!0;else if("base64"==d)f=c.get("base64-string")[0].getValue(),e=!1;else if("dir"==d){d=c.get("dir")[0].getValue();e=0;c=c.get("refresh");1<=c.length&&(c=c[0].getValue().match(/(\d+)([hms])/),null==c?e=0:(e=parseInt(c[1]),"s"!=c[2]&&(e*=60,"m"!=c[2]&&(e*=
+60))));this.refreshManager.addDirectory(d,1E3*e);continue}else if("any"==d){this.requiresVerification=!1;break}this.lookupCertificate(f,e)}};
+ConfigPolicyManager.prototype.checkSignatureMatch=function(a,b,c,d){c=c.get("checker")[0];var e=c.get("type")[0].getValue();if("fixed-signer"==e){b=c.get("signer")[0];c=b.get("type")[0].getValue();if("file"==c){if(c=this.lookupCertificate(b.get("file-name")[0].getValue(),!0),null==c)return d[0]="Can't find fixed-signer certificate file: "+b.get("file-name")[0].getValue(),!1}else if("base64"==c){if(c=this.lookupCertificate(b.get("base64-string")[0].getValue(),!1),null==c)return d[0]="Can't find fixed-signer certificate base64: "+
+b.get("base64-string")[0].getValue(),!1}else return d[0]="Unrecognized fixed-signer signerType: "+c,!1;if(c.getName().equals(a))return!0;d[0]='fixed-signer cert name "'+c.getName().toUri()+'" does not equal signatureName "'+a.toUri()+'"';return!1}if("hierarchical"==e){c=NdnRegexMatcher.match("^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>",a);if(null!=c){a=(new Name(c[1])).append(new Name(c[2]));if(ConfigPolicyManager.matchesRelation(b,a,"is-prefix-of"))return!0;d[0]='The hierarchical objectName "'+b.toUri()+
+'" is not a prefix of "'+a.toUri()+'"';return!1}d[0]='The hierarchical identityRegex "^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>" does not match signatureName "'+a.toUri()+'"';return!1}if("customized"==e){var f=c.get("key-locator")[0];c=f.getFirstValue("relation");if(null!=c){b=new Name(f.get("name")[0].getValue());if(ConfigPolicyManager.matchesRelation(a,b,c))return!0;d[0]='The custom signatureName "'+a.toUri()+'" does not match matchName "'+b.toUri()+'" using relation '+c;return!1}var g=f.getFirstValue("regex");
+if(null!=g){if(null!=NdnRegexMatcher.match(g,a))return!0;d[0]='The custom signatureName "'+a.toUri()+'" does not regex match simpleKeyRegex "'+g+'"';return!1}c=f.get("hyper-relation");if(1<=c.length){c=c[0];var g=c.getFirstValue("k-regex"),h=c.getFirstValue("k-expand"),f=c.getFirstValue("p-regex"),k=c.getFirstValue("p-expand");c=c.getFirstValue("h-relation");if(null!=g&&null!=h&&null!=f&&null!=k&&null!=c){e=NdnRegexMatcher.match(g,a);if(null==e||void 0===e[1])return d[0]='The custom hyper-relation signatureName "'+
+a.toUri()+'" does not match the keyRegex "'+g+'"',!1;a=ConfigPolicyManager.expand(e,h);e=NdnRegexMatcher.match(f,b);if(null==e||void 0===e[1])return d[0]='The custom hyper-relation objectName "'+b.toUri()+'" does not match the nameRegex "'+f+'"',!1;b=ConfigPolicyManager.expand(e,k);if(ConfigPolicyManager.matchesRelation(new Name(b),new Name(a),c))return!0;d[0]='The custom hyper-relation nameMatch "'+b+'" does not match the keyMatchPrefix "'+a+'" using relation '+c;return!1}}}d[0]="Unrecognized checkerType: "+
+e;return!1};ConfigPolicyManager.expand=function(a,b){return b.replace(/\\(\d)/g,function(b,d){return a[parseInt(d)]})};
+ConfigPolicyManager.prototype.lookupCertificate=function(a,b){var c;c=this.fixedCertificateCache[a];if(void 0===c){if(b)c=ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile(a);else{var d=new Buffer(a,"base64");c=new IdentityCertificate;c.wireDecode(d)}d=c.getName().getPrefix(-1).toUri();this.fixedCertificateCache[a]=d;this.certificateCache.insertCertificate(c)}else c=this.certificateCache.getCertificate(new Name(c));return c};
+ConfigPolicyManager.prototype.findMatchingRule=function(a,b){for(var c=this.config.getRoot().get("validator/rule"),d=0;d<c.length;++d){var e=c[d];if(e.get("for")[0].getValue()==b){var f=!0,g=e.get("filter");if(0==g.length)return e;for(var h=0;h<g.length;++h){var k=g[h],f=k.getFirstValue("regex");null===f?(f=k.get("relation")[0].getValue(),k=k.get("name")[0].getValue(),k=new Name(k),f=ConfigPolicyManager.matchesRelation(a,k,f)):f=null!==NdnRegexMatcher.match(f,a);if(!f)break}if(f)return e}}return null};
+ConfigPolicyManager.matchesRelation=function(a,b,c){var d=!1;"is-strict-prefix-of"==c?b.size()==a.size()?d=!1:b.match(a)&&(d=!0):"is-prefix-of"==c?b.match(a)&&(d=!0):"equal"==c&&b.equals(a)&&(d=!0);return d};ConfigPolicyManager.extractSignature=function(a,b){if(a instanceof Data)return a.getSignature();if(a instanceof Interest){b=b||WireFormat.getDefaultWireFormat();try{var c=b.decodeSignatureInfoAndValue(a.getName().get(-2).getValue().buf(),a.getName().get(-1).getValue().buf(),!1)}catch(d){return null}return c}return null};
+ConfigPolicyManager.prototype.interestTimestampIsFresh=function(a,b,c){a=this.keyTimestamps[a.toUri()];if(void 0==a){a=(new Date).getTime();var d=a+this.keyGraceInterval;if(b>a-this.keyGraceInterval&&b<d)return!0;c[0]="The command interest timestamp is not within the first use grace period of "+this.keyGraceInterval+" milliseconds.";return!1}return b<=a?(c[0]="The command interest timestamp is not newer than the previous timestamp",!1):!0};
+ConfigPolicyManager.prototype.updateTimestampForKey=function(a,b){this.keyTimestamps[a.toUri()]=b;var c=0,d=[],e=(new Date).getTime(),f=e,g=null,h;for(h in this.keyTimestamps){++c;var k=this.keyTimestamps[h];e-k>this.keyTimestampTtl?d.push(h):k<f&&(f=k,g=h)}if(c>=this.maxTrackedKeys){for(e=0;e<d.length;++e)delete this.keyTimestamps[d[e]],--c;c>this.maxTrackedKeys&&delete this.keyTimestamps[g]}};
+ConfigPolicyManager.prototype.verify=function(a,b,c){var d=KeyLocator.getFromSignature(a);if(d.getType()==KeyLocatorType.KEYNAME){var e=d.getKeyName(),d=this.refreshManager.getCertificate(e);null==d&&(d=this.certificateCache.getCertificate(e));null==d?c(!1,"Cannot find a certificate with name "+e.toUri()):(e=d.getPublicKeyInfo().getKeyDer(),e.isNull()?c(!1,"There is no public key in the certificate with name "+d.getName().toUri()):PolicyManager.verifySignature(a,b,e,function(a){a?c(!0):c(!1,"The signature did not verify with the given public key")}))}else c(!1,
+"The KeyLocator does not have a key name")};ConfigPolicyManager.TrustAnchorRefreshManager=function(){this.certificateCache=new CertificateCache;this.refreshDirectories={}};ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile=function(a){a=fs.readFileSync(a).toString();a=new Buffer(a,"base64");var b=new IdentityCertificate;b.wireDecode(new Blob(a,!1));return b};ConfigPolicyManager.TrustAnchorRefreshManager.prototype.getCertificate=function(a){return this.certificateCache.getCertificate(a)};
+ConfigPolicyManager.TrustAnchorRefreshManager.prototype.addDirectory=function(a,b){var c;try{c=fs.readdirSync(a)}catch(d){throw new SecurityException(Error("Cannot list files in directory "+a));}for(var e=[],f=0;f<c.length;++f){var g;try{var h=path.join(a,c[f]);g=ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile(h)}catch(k){continue}var l=g.getName().getPrefix(-1).toUri();this.certificateCache.insertCertificate(g);e.push(l)}this.refreshDirectories[a]={certificates:e,nextRefresh:(new Date).getTime()+
+b,refreshPeriod:b}};ConfigPolicyManager.TrustAnchorRefreshManager.prototype.refreshAnchors=function(){var a=(new Date).getTime(),b;for(b in this.refreshDirectories){var c=this.refreshDirectories[b];if(c.nextRefresh<=a){var d=c.certificates.slice(0),e;for(e in d)this.certificateCache.deleteCertificate(new Name(e));this.addDirectory(b,c.refreshPeriod)}}};
+var Name=require("../../name.js").Name,PolicyManager=require("./policy-manager.js").PolicyManager,NdnCommon=require("../../util/ndn-common.js").NdnCommon,NoVerifyPolicyManager=function(){PolicyManager.call(this)};NoVerifyPolicyManager.prototype=new PolicyManager;NoVerifyPolicyManager.prototype.name="NoVerifyPolicyManager";exports.NoVerifyPolicyManager=NoVerifyPolicyManager;NoVerifyPolicyManager.prototype.skipVerifyAndTrust=function(a){return!0};NoVerifyPolicyManager.prototype.requireVerify=function(a){return!1};
+NoVerifyPolicyManager.prototype.checkVerificationPolicy=function(a,b,c,d,e){try{c(a)}catch(f){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(f))}return null};NoVerifyPolicyManager.prototype.checkSigningPolicy=function(a,b){return!0};NoVerifyPolicyManager.prototype.inferSigningIdentity=function(a){return new Name};
+var Name=require("../../name.js").Name,Interest=require("../../interest.js").Interest,Data=require("../../data.js").Data,Blob=require("../../util/blob.js").Blob,IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,KeyLocator=require("../../key-locator.js").KeyLocator,KeyLocatorType=require("../../key-locator.js").KeyLocatorType,SecurityException=require("../security-exception.js").SecurityException,WireFormat=require("../../encoding/wire-format.js").WireFormat,
+SyncPromise=require("../../util/sync-promise.js").SyncPromise,PolicyManager=require("./policy-manager.js").PolicyManager,NdnCommon=require("../../util/ndn-common.js").NdnCommon,SelfVerifyPolicyManager=function(a){PolicyManager.call(this);this.identityStorage=a};SelfVerifyPolicyManager.prototype=new PolicyManager;SelfVerifyPolicyManager.prototype.name="SelfVerifyPolicyManager";exports.SelfVerifyPolicyManager=SelfVerifyPolicyManager;SelfVerifyPolicyManager.prototype.skipVerifyAndTrust=function(a){return!1};
+SelfVerifyPolicyManager.prototype.requireVerify=function(a){return!0};
+SelfVerifyPolicyManager.prototype.checkVerificationPolicy=function(a,b,c,d,e){e=e||WireFormat.getDefaultWireFormat();if(a instanceof Data)this.verify(a.getSignature(),a.wireEncode(),function(b,e){if(b)try{c(a)}catch(f){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(f))}else try{d(a,e)}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}});else if(a instanceof Interest){if(2>a.getName().size()){try{d(a,"The signed interest has less than 2 components: "+
+a.getName().toUri())}catch(f){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(f))}return}var g;try{g=e.decodeSignatureInfoAndValue(a.getName().get(-2).getValue().buf(),a.getName().get(-1).getValue().buf(),!1)}catch(h){try{d(a,"Error decoding the signed interest signature: "+h)}catch(k){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(k))}return}this.verify(g,a.wireEncode(),function(b,e){if(b)try{c(a)}catch(f){console.log("Error in onVerified: "+
+NdnCommon.getErrorWithStackTrace(f))}else try{d(a,e)}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}})}else throw new SecurityException(Error("checkVerificationPolicy: unrecognized type for dataOrInterest"));return null};SelfVerifyPolicyManager.prototype.checkSigningPolicy=function(a,b){return!0};SelfVerifyPolicyManager.prototype.inferSigningIdentity=function(a){return new Name};
+SelfVerifyPolicyManager.prototype.verify=function(a,b,c){if(KeyLocator.canGetFromSignature(a))this.getPublicKeyDer(KeyLocator.getFromSignature(a),function(d,f){if(d.isNull())c(!1,f);else try{PolicyManager.verifySignature(a,b,d,function(a){a?c(!0):c(!1,"The signature did not verify with the given public key")})}catch(g){c(!1,"Error in verifySignature: "+g)}});else try{PolicyManager.verifySignature(a,b,null,function(a){a?c(!0):c(!1,"The signature did not verify with the given public key")})}catch(d){c(!1,
+"Error in verifySignature: "+d)}};
+SelfVerifyPolicyManager.prototype.getPublicKeyDer=function(a,b){if(a.getType()==KeyLocatorType.KEYNAME&&null!=this.identityStorage){var c;try{c=IdentityCertificate.certificateNameToPublicKeyName(a.getKeyName())}catch(d){b(new Blob,"Cannot get a public key name from the certificate named: "+a.getKeyName().toUri());return}SyncPromise.complete(b,function(a){b(new Blob,"The identityStorage doesn't have the key named "+c.toUri())},this.identityStorage.getKeyPromise(c))}else b(new Blob,"The signature KeyLocator doesn't have a key name")};
+Crypto=require("../crypto.js");Name=require("../name.js").Name;Interest=require("../interest.js").Interest;Data=require("../data.js").Data;Blob=require("../util/blob.js").Blob;WireFormat=require("../encoding/wire-format.js").WireFormat;SecurityException=require("./security-exception.js").SecurityException;RsaKeyParams=require("./key-params.js").RsaKeyParams;IdentityCertificate=require("./certificate/identity-certificate.js").IdentityCertificate;SyncPromise=require("../util/sync-promise.js").SyncPromise;
+NdnCommon=require("../util/ndn-common.js").NdnCommon;IdentityManager=require("./identity/identity-manager.js").IdentityManager;NoVerifyPolicyManager=require("./policy/no-verify-policy-manager.js").NoVerifyPolicyManager;KeyChain=function(a,b){a||(a=new IdentityManager);b||(b=new NoVerifyPolicyManager);this.identityManager=a;this.policyManager=b;this.face=null};exports.KeyChain=KeyChain;
+KeyChain.prototype.createIdentityAndCertificate=function(a,b,c,d){d="function"===typeof b?c:d;c="function"===typeof b?b:c;b="function"!==typeof b&&b?b:KeyChain.DEFAULT_KEY_PARAMS;return this.identityManager.createIdentityAndCertificate(a,b,c,d)};KeyChain.prototype.createIdentity=function(a,b){return IdentityCertificate.certificateNameToPublicKeyName(this.createIdentityAndCertificate(a,b))};KeyChain.prototype.deleteIdentity=function(a,b,c){this.identityManager.deleteIdentity(a,b,c)};
+KeyChain.prototype.getDefaultIdentity=function(a,b){return this.identityManager.getDefaultIdentity(a,b)};KeyChain.prototype.getDefaultCertificateName=function(a,b){return this.identityManager.getDefaultCertificateName(a,b)};KeyChain.prototype.generateRSAKeyPair=function(a,b,c){(c="boolean"===typeof b?b:c)||(c=2048);return this.identityManager.generateRSAKeyPair(a,"boolean"===typeof b?b:!1,c)};
+KeyChain.prototype.setDefaultKeyForIdentity=function(a,b,c,d){return this.identityManager.setDefaultKeyForIdentity(a,b,c,d)};KeyChain.prototype.generateRSAKeyPairAsDefault=function(a,b,c){return this.identityManager.generateRSAKeyPairAsDefault(a,b,c)};KeyChain.prototype.createSigningRequest=function(a){return this.identityManager.getPublicKey(a).getKeyDer()};KeyChain.prototype.installIdentityCertificate=function(a,b,c){this.identityManager.addCertificate(a,b,c)};
+KeyChain.prototype.setDefaultCertificateForKey=function(a,b,c){this.identityManager.setDefaultCertificateForKey(a,b,c)};KeyChain.prototype.getCertificate=function(a,b,c){return this.identityManager.getCertificate(a,b,c)};KeyChain.prototype.getIdentityCertificate=function(a,b,c){return this.identityManager.getCertificate(a,b,c)};KeyChain.prototype.revokeKey=function(a){};KeyChain.prototype.revokeCertificate=function(a){};KeyChain.prototype.getIdentityManager=function(){return this.identityManager};
+KeyChain.prototype.getPolicyManager=function(){return this.policyManager};KeyChain.prototype.sign=function(a,b,c,d,e){var f=b,g=c,h=d;b=f instanceof Name?f:null;c=f instanceof WireFormat?f:g instanceof WireFormat?g:null;"function"===typeof f?(d=f,e=g):"function"===typeof g?(d=g,e=h):"function"===typeof h?d=h:e=d=null;return SyncPromise.complete(d,e,this.signPromise(a,b,c,!d))};
+KeyChain.prototype.signPromise=function(a,b,c,d){var e=b,f=c,g=d;b=e instanceof Name?e:null;c=e instanceof WireFormat?e:f instanceof WireFormat?f:null;d="boolean"===typeof e?e:"boolean"===typeof f?f:"boolean"===typeof g?g:!1;var h=this;return SyncPromise.resolve().then(function(){return null!=b?SyncPromise.resolve():h.identityManager.getDefaultCertificatePromise(d).then(function(a){return null!=a?(b=a.getName(),SyncPromise.resolve()):h.prepareDefaultCertificateNamePromise_(d).then(function(a){b=a;
+return SyncPromise.resolve()})})}).then(function(){return a instanceof Interest?h.identityManager.signInterestByCertificatePromise(a,b,c,d):a instanceof Data?h.identityManager.signByCertificatePromise(a,b,c,d):h.identityManager.signByCertificatePromise(a,b,d)})};
+KeyChain.prototype.signByIdentity=function(a,b,c,d,e){e="function"===typeof c?d:e;d="function"===typeof c?c:d;c="function"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();var f=!d,g=this;null==b&&(b=new Name);if(a instanceof Data){var h=SyncPromise.resolve().then(function(){if(0==b.size()){var c=g.policyManager.inferSigningIdentity(a.getName());return 0==c.size()?g.identityManager.getDefaultCertificateNamePromise(f):g.identityManager.getDefaultCertificateNameForIdentityPromise(c,f)}return g.identityManager.getDefaultCertificateNameForIdentityPromise(b,
+f)}).then(function(b){if(0==b.size())throw new SecurityException(Error("No qualified certificate name found!"));if(!g.policyManager.checkSigningPolicy(a.getName(),b))throw new SecurityException(Error("Signing Cert name does not comply with signing policy"));return g.identityManager.signByCertificatePromise(a,b,c,f)});return SyncPromise.complete(d,e,h)}return SyncPromise.complete(d,e,this.identityManager.getDefaultCertificateNameForIdentityPromise(b,f).then(function(b){if(0==b.size())throw new SecurityException(Error("No qualified certificate name found!"));
+return g.identityManager.signByCertificatePromise(a,b,c,f)}))};KeyChain.prototype.signWithSha256=function(a,b){a instanceof Interest?this.identityManager.signInterestWithSha256(a,b):this.identityManager.signWithSha256(a,b)};
+KeyChain.prototype.verifyData=function(a,b,c,d){null==d&&(d=0);if(this.policyManager.requireVerify(a)){var e=this.policyManager.checkVerificationPolicy(a,d,b,c);if(null!=e){var f=this;this.face.expressInterest(e.interest,function(a,b){f.onCertificateData(a,b,e)},function(b){f.onCertificateInterestTimeout(b,e.retry,c,a,e)})}}else if(this.policyManager.skipVerifyAndTrust(a))try{b(a)}catch(g){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(g))}else try{c(a,"The packet has no verify rule but skipVerifyAndTrust is false")}catch(h){console.log("Error in onValidationFailed: "+
+NdnCommon.getErrorWithStackTrace(h))}};
+KeyChain.prototype.verifyInterest=function(a,b,c,d,e){null==d&&(d=0);e=e||WireFormat.getDefaultWireFormat();if(this.policyManager.requireVerify(a)){var f=this.policyManager.checkVerificationPolicy(a,d,b,c,e);if(null!=f){var g=this;this.face.expressInterest(f.interest,function(a,b){g.onCertificateData(a,b,f)},function(b){g.onCertificateInterestTimeout(b,f.retry,c,a,f)})}}else if(this.policyManager.skipVerifyAndTrust(a))try{b(a)}catch(h){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(h))}else try{c(a,
+"The packet has no verify rule but skipVerifyAndTrust is false")}catch(k){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(k))}};KeyChain.prototype.setFace=function(a){this.face=a};
+KeyChain.signWithHmacWithSha256=function(a,b,c){c=c||WireFormat.getDefaultWireFormat();if(a instanceof Data)c=a.wireEncode(c),b=Crypto.createHmac("sha256",b.buf()),b.update(c.signedBuf()),a.getSignature().setSignature(new Blob(b.digest(),!1));else throw new SecurityException(Error("signWithHmacWithSha256: Unrecognized target type"));};
+KeyChain.verifyDataWithHmacWithSha256=function(a,b,c){c=c||WireFormat.getDefaultWireFormat();c=a.wireEncode(c);b=Crypto.createHmac("sha256",b.buf());b.update(c.signedBuf());return(new Blob(b.digest(),!1)).equals(a.getSignature().getSignature())};KeyChain.DEFAULT_KEY_PARAMS=new RsaKeyParams;KeyChain.prototype.onCertificateData=function(a,b,c){this.verifyData(b,c.onVerified,c.onValidationFailed,c.stepCount)};
+KeyChain.prototype.onCertificateInterestTimeout=function(a,b,c,d,e){if(0<b){var f=this;this.face.expressInterest(a,function(a,b){f.onCertificateData(a,b,e)},function(a){f.onCertificateInterestTimeout(a,b-1,c,d,e)})}else try{c(d,"The retry count is zero after timeout for fetching "+a.getName().toUri())}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}};
+KeyChain.prototype.prepareDefaultCertificateNamePromise_=function(a){var b,c=this;return this.identityManager.getDefaultCertificatePromise(a).then(function(d){b=d;return null!=b?SyncPromise.resolve():c.setDefaultCertificatePromise_(a).then(function(){return c.identityManager.getDefaultCertificatePromise(a)}).then(function(a){b=a;return SyncPromise.resolve()})}).then(function(){return SyncPromise.resolve(b.getName())})};
+KeyChain.prototype.setDefaultCertificatePromise_=function(a){var b=this;return this.identityManager.getDefaultCertificatePromise(a).then(function(c){if(null!=c)return SyncPromise.resolve();var d;return b.identityManager.getDefaultIdentityPromise(a).then(function(a){d=a;return SyncPromise.resolve()},function(a){randomComponent=Crypto.randomBytes(4);d=(new Name).append("tmp-identity").append(new Blob(randomComponent,!1));return SyncPromise.resolve()}).then(function(){return b.identityManager.createIdentityAndCertificatePromise(d,
+KeyChain.DEFAULT_KEY_PARAMS,a)}).then(function(){return b.identityManager.setDefaultIdentityPromise(d,a)})})};var Name=require("./name.js").Name,DataUtils=require("./encoding/data-utils.js").DataUtils,Blob=require("./util/blob.js").Blob,Exclude=function Exclude(b){this.values=[];if("object"===typeof b&&b instanceof Exclude)this.values=b.values.slice(0);else if(b)for(var c=this.changeCount=0;c<b.length;++c)b[c]==Exclude.ANY?this.appendAny():this.appendComponent(b[c]);this.changeCount=0};
+exports.Exclude=Exclude;Exclude.ANY="*";Exclude.prototype.size=function(){return this.values.length};Exclude.prototype.get=function(a){return this.values[a]};Exclude.prototype.appendAny=function(){this.values.push(Exclude.ANY);++this.changeCount;return this};Exclude.prototype.appendComponent=function(a){this.values.push(new Name.Component(a));++this.changeCount;return this};Exclude.prototype.clear=function(){++this.changeCount;this.values=[]};
+Exclude.prototype.toUri=function(){if(null==this.values||0==this.values.length)return"";for(var a="",b=0;b<this.values.length;++b)0<b&&(a+=","),a=this.values[b]==Exclude.ANY?a+"*":a+this.values[b].toEscapedString();return a};
+Exclude.prototype.matches=function(a){"object"==typeof a&&a instanceof Name.Component||(a=new Name.Component(a));for(var b=0;b<this.values.length;++b)if(this.values[b]==Exclude.ANY){var c=null;0<b&&(c=this.values[b-1]);var d,e=null;for(d=b+1;d<this.values.length;++d)if(this.values[d]!=Exclude.ANY){e=this.values[d];break}if(null!=e){if(null!=c){if(0<a.compare(c)&&0>a.compare(e))return!0}else if(0>a.compare(e))return!0;b=d-1}else if(null!=c){if(0<a.compare(c))return!0}else return!0}else if(a.equals(this.values[b]))return!0;
+return!1};Exclude.compareComponents=function(a,b){"object"==typeof a&&a instanceof Name.Component&&(a=a.getValue().buf());"object"==typeof b&&b instanceof Name.Component&&(b=b.getValue().buf());return Name.Component.compareBuffers(a,b)};Exclude.prototype.getChangeCount=function(){return this.changeCount};
+var Crypto=require("./crypto.js"),Blob=require("./util/blob.js").Blob,SignedBlob=require("./util/signed-blob.js").SignedBlob,ChangeCounter=require("./util/change-counter.js").ChangeCounter,Name=require("./name.js").Name,Exclude=require("./exclude.js").Exclude,Link=require("./link.js").Link,KeyLocator=require("./key-locator.js").KeyLocator,IncomingFaceId=require("./lp/incoming-face-id.js").IncomingFaceId,WireFormat=require("./encoding/wire-format.js").WireFormat,Interest=function Interest(b,c,d,e,
+f,g,h,k,l,m){if(e)throw Error("Interest constructor: PublisherPublicKeyDigest support has been removed.");if(h)throw Error("Interest constructor: answerOriginKind support has been removed. Use setMustBeFresh().");if(k)throw Error("Interest constructor: scope support has been removed.");"object"===typeof b&&b instanceof Interest?(this.name_=new ChangeCounter(new Name(b.getName())),this.maxSuffixComponents_=b.maxSuffixComponents_,this.minSuffixComponents_=b.minSuffixComponents_,this.keyLocator_=new ChangeCounter(new KeyLocator(b.getKeyLocator())),
+this.exclude_=new ChangeCounter(new Exclude(b.getExclude())),this.childSelector_=b.childSelector_,this.mustBeFresh_=b.mustBeFresh_,this.interestLifetimeMilliseconds_=b.interestLifetimeMilliseconds_,this.nonce_=b.nonce_,this.linkWireEncoding_=b.linkWireEncoding_,this.linkWireEncodingFormat_=b.linkWireEncodingFormat_,this.link_=new ChangeCounter(null),null!=b.link_.get()&&this.link_.set(new Link(b.link_.get())),this.selectedDelegationIndex_=b.selectedDelegationIndex_,this.defaultWireEncoding_=b.getDefaultWireEncoding(),
+this.defaultWireEncodingFormat_=b.defaultWireEncodingFormat_):(this.name_=new ChangeCounter("object"===typeof b&&b instanceof Name?new Name(b):new Name),this.maxSuffixComponents_=d,this.minSuffixComponents_=c,this.keyLocator_=new ChangeCounter(new KeyLocator),this.exclude_=new ChangeCounter("object"===typeof f&&f instanceof Exclude?new Exclude(f):new Exclude),this.childSelector_=g,this.mustBeFresh_=!0,this.interestLifetimeMilliseconds_=l,this.nonce_="object"===typeof m&&m instanceof Blob?m:new Blob(m,
+!0),this.linkWireEncoding_=new Blob,this.linkWireEncodingFormat_=null,this.link_=new ChangeCounter(null),this.selectedDelegationIndex_=null,this.defaultWireEncoding_=new SignedBlob,this.defaultWireEncodingFormat_=null);this.changeCount_=this.getDefaultWireEncodingChangeCount_=this.getNonceChangeCount_=0;this.lpPacket_=null};exports.Interest=Interest;Interest.RECURSIVE_POSTFIX="*";Interest.CHILD_SELECTOR_LEFT=0;Interest.CHILD_SELECTOR_RIGHT=1;
+Interest.prototype.matchesName=function(a){return!this.getName().match(a)||null!=this.minSuffixComponents_&&!(a.size()+1-this.getName().size()>=this.minSuffixComponents_)||null!=this.maxSuffixComponents_&&!(a.size()+1-this.getName().size()<=this.maxSuffixComponents_)||null!=this.getExclude()&&a.size()>this.getName().size()&&this.getExclude().matches(a.get(this.getName().size()))?!1:!0};Interest.prototype.matches_name=function(a){return this.matchesName(a)};
+Interest.prototype.matchesData=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=this.getName().size(),d=a.getName(),e=d.size()+1,f=null!=this.getMinSuffixComponents()?this.getMinSuffixComponents():0;if(!(c+f<=e&&(null==this.getMaxSuffixComponents()||c+this.getMaxSuffixComponents()>=e)))return!1;if(c===e)if(this.getName().get(-1).isImplicitSha256Digest()){if(!this.getName().equals(a.getFullName(b)))return!1}else return!1;else if(!this.getName().isPrefixOf(d))return!1;if(0<this.getExclude().size()&&
+e>c)if(c==e-1){if(this.getExclude().matches(a.getFullName(b).get(c)))return!1}else if(this.getExclude().matches(d.get(c)))return!1;c=this.getKeyLocator();return!c.getType()||(d=a.getSignature(),KeyLocator.canGetFromSignature(d)&&c.equals(KeyLocator.getFromSignature(d)))?!0:!1};Interest.prototype.clone=function(){return new Interest(this)};Interest.prototype.getName=function(){return this.name_.get()};Interest.prototype.getMinSuffixComponents=function(){return this.minSuffixComponents_};
+Interest.prototype.getMaxSuffixComponents=function(){return this.maxSuffixComponents_};Interest.prototype.getKeyLocator=function(){return this.keyLocator_.get()};Interest.prototype.getExclude=function(){return this.exclude_.get()};Interest.prototype.getChildSelector=function(){return this.childSelector_};Interest.prototype.getMustBeFresh=function(){return this.mustBeFresh_};
+Interest.prototype.getNonce=function(){this.getNonceChangeCount_!=this.getChangeCount()&&(this.nonce_=new Blob,this.getNonceChangeCount_=this.getChangeCount());return this.nonce_};Interest.prototype.getNonceAsBuffer=function(){return this.getNonce().buf()};Interest.prototype.hasLink=function(){return null!=this.link_.get()||!this.linkWireEncoding_.isNull()};
+Interest.prototype.getLink=function(){if(null!=this.link_.get())return this.link_.get();if(this.linkWireEncoding_.isNull())return null;var a=new Link;a.wireDecode(this.linkWireEncoding_,this.linkWireEncodingFormat_);this.link_.set(a);this.linkWireEncoding_=new Blob;this.linkWireEncodingFormat_=null;return a};
+Interest.prototype.getLinkWireEncoding=function(a){a=a||WireFormat.getDefaultWireFormat();if(!this.linkWireEncoding_.isNull()&&this.linkWireEncodingFormat_==a)return this.linkWireEncoding_;var b=this.getLink();return null!=b?b.wireEncode(a):new Blob};Interest.prototype.getSelectedDelegationIndex=function(){return this.selectedDelegationIndex_};Interest.prototype.getInterestLifetimeMilliseconds=function(){return this.interestLifetimeMilliseconds_};
+Interest.prototype.getDefaultWireEncoding=function(){this.getDefaultWireEncodingChangeCount_!=this.getChangeCount()&&(this.defaultWireEncoding_=new SignedBlob,this.defaultWireEncodingFormat_=null,this.getDefaultWireEncodingChangeCount_=this.getChangeCount());return this.defaultWireEncoding_};Interest.prototype.getDefaultWireEncodingFormat=function(){return this.defaultWireEncodingFormat_};
+Interest.prototype.getIncomingFaceId=function(){var a=null===this.lpPacket_?null:IncomingFaceId.getFirstHeader(this.lpPacket_);return null===a?null:a.getFaceId()};Interest.prototype.setName=function(a){this.name_.set("object"===typeof a&&a instanceof Name?new Name(a):new Name);++this.changeCount_;return this};Interest.prototype.setMinSuffixComponents=function(a){this.minSuffixComponents_=a;++this.changeCount_;return this};
+Interest.prototype.setMaxSuffixComponents=function(a){this.maxSuffixComponents_=a;++this.changeCount_;return this};Interest.prototype.setKeyLocator=function(a){this.keyLocator_.set("object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator);++this.changeCount_;return this};Interest.prototype.setExclude=function(a){this.exclude_.set("object"===typeof a&&a instanceof Exclude?new Exclude(a):new Exclude);++this.changeCount_;return this};
+Interest.prototype.setLinkWireEncoding=function(a,b){b=b||WireFormat.getDefaultWireFormat();this.linkWireEncoding_=a;this.linkWireEncodingFormat_=b;this.link_.set(null);++this.changeCount_;return this};Interest.prototype.unsetLink=function(){return this.setLinkWireEncoding(new Blob,null)};Interest.prototype.setSelectedDelegationIndex=function(a){this.selectedDelegationIndex_=a;++this.changeCount_;return this};
+Interest.prototype.setChildSelector=function(a){this.childSelector_=a;++this.changeCount_;return this};Interest.prototype.setMustBeFresh=function(a){this.mustBeFresh_=a?!0:!1;++this.changeCount_;return this};Interest.prototype.setInterestLifetimeMilliseconds=function(a){this.interestLifetimeMilliseconds_=a;++this.changeCount_;return this};
+Interest.prototype.setNonce=function(a){this.nonce_="object"===typeof a&&a instanceof Blob?a:new Blob(a,!0);++this.changeCount_;this.getNonceChangeCount_=this.getChangeCount();return this};
+Interest.prototype.toUri=function(){var a="";null!=this.minSuffixComponents_&&(a+="&ndn.MinSuffixComponents="+this.minSuffixComponents_);null!=this.maxSuffixComponents_&&(a+="&ndn.MaxSuffixComponents="+this.maxSuffixComponents_);null!=this.childSelector_&&(a+="&ndn.ChildSelector="+this.childSelector_);a+="&ndn.MustBeFresh="+(this.mustBeFresh_?1:0);null!=this.interestLifetimeMilliseconds_&&(a+="&ndn.InterestLifetime="+this.interestLifetimeMilliseconds_);0<this.getNonce().size()&&(a+="&ndn.Nonce="+
+Name.toEscapedString(this.getNonce().buf()));null!=this.getExclude()&&0<this.getExclude().size()&&(a+="&ndn.Exclude="+this.getExclude().toUri());var b=this.getName().toUri();""!=a&&(b+="?"+a.substr(1));return b};
+Interest.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();if(!this.getDefaultWireEncoding().isNull()&&this.getDefaultWireEncodingFormat()==a)return this.getDefaultWireEncoding();var b=a.encodeInterest(this),b=new SignedBlob(b.encoding,b.signedPortionBeginOffset,b.signedPortionEndOffset);a==WireFormat.getDefaultWireFormat()&&this.setDefaultWireEncoding(b,WireFormat.getDefaultWireFormat());return b};
+Interest.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c;c="object"===typeof a&&a instanceof Blob?b.decodeInterest(this,a.buf(),!1):b.decodeInterest(this,a,!0);b==WireFormat.getDefaultWireFormat()?this.setDefaultWireEncoding(new SignedBlob(new Blob(a,!0),c.signedPortionBeginOffset,c.signedPortionEndOffset),WireFormat.getDefaultWireFormat()):this.setDefaultWireEncoding(new SignedBlob,null)};
+Interest.prototype.refreshNonce=function(){var a=this.getNonce();if(0!==a.size()){for(var b;b=new Blob(Crypto.randomBytes(a.size()),!1),b.equals(a););this.nonce_=b;++this.changeCount_;this.getNonceChangeCount_=this.getChangeCount()}};Interest.prototype.setLpPacket=function(a){this.lpPacket_=a;return this};Interest.prototype.getChangeCount=function(){var a=this.name_.checkChanged(),a=this.keyLocator_.checkChanged()||a;(a=this.exclude_.checkChanged()||a)&&++this.changeCount_;return this.changeCount_};
+Interest.prototype.setDefaultWireEncoding=function(a,b){this.defaultWireEncoding_=a;this.defaultWireEncodingFormat_=b;this.getDefaultWireEncodingChangeCount_=this.getChangeCount()};Object.defineProperty(Interest.prototype,"name",{get:function(){return this.getName()},set:function(a){this.setName(a)}});Object.defineProperty(Interest.prototype,"minSuffixComponents",{get:function(){return this.getMinSuffixComponents()},set:function(a){this.setMinSuffixComponents(a)}});
+Object.defineProperty(Interest.prototype,"maxSuffixComponents",{get:function(){return this.getMaxSuffixComponents()},set:function(a){this.setMaxSuffixComponents(a)}});Object.defineProperty(Interest.prototype,"keyLocator",{get:function(){return this.getKeyLocator()},set:function(a){this.setKeyLocator(a)}});Object.defineProperty(Interest.prototype,"exclude",{get:function(){return this.getExclude()},set:function(a){this.setExclude(a)}});
+Object.defineProperty(Interest.prototype,"childSelector",{get:function(){return this.getChildSelector()},set:function(a){this.setChildSelector(a)}});Object.defineProperty(Interest.prototype,"interestLifetime",{get:function(){return this.getInterestLifetimeMilliseconds()},set:function(a){this.setInterestLifetimeMilliseconds(a)}});Object.defineProperty(Interest.prototype,"nonce",{get:function(){return this.getNonceAsBuffer()},set:function(a){this.setNonce(a)}});
+ForwardingFlags=function ForwardingFlags(b){"object"===typeof b&&b instanceof ForwardingFlags?(this.childInherit=b.childInherit,this.capture=b.capture):(this.childInherit=!0,this.capture=!1)};exports.ForwardingFlags=ForwardingFlags;ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT=1;ForwardingFlags.NfdForwardingFlags_CAPTURE=2;
+ForwardingFlags.prototype.getNfdForwardingFlags=function(){var a=0;this.childInherit&&(a|=ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT);this.capture&&(a|=ForwardingFlags.NfdForwardingFlags_CAPTURE);return a};ForwardingFlags.prototype.setNfdForwardingFlags=function(a){this.childInherit=0!=(a&ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT);this.capture=0!=(a&ForwardingFlags.NfdForwardingFlags_CAPTURE)};ForwardingFlags.prototype.getChildInherit=function(){return this.childInherit};
+ForwardingFlags.prototype.getCapture=function(){return this.capture};ForwardingFlags.prototype.setChildInherit=function(a){this.childInherit=a};ForwardingFlags.prototype.setCapture=function(a){this.capture=a};
+var ForwardingFlags=require("./forwarding-flags.js").ForwardingFlags,Name=require("./name.js").Name,WireFormat=require("./encoding/wire-format.js").WireFormat,Blob=require("./util/blob.js").Blob,ControlParameters=function ControlParameters(b){"object"===typeof b&&b instanceof ControlParameters?(this.name=null==b.name?null:new Name(b.name),this.faceId=b.faceId,this.uri=b.uri,this.localControlFeature=b.localControlFeature,this.origin=b.origin,this.cost=b.cost,this.forwardingFlags=new ForwardingFlags(b.forwardingFlags),
+this.strategy=new Name(b.strategy),this.expirationPeriod=b.expirationPeriod):(this.faceId=this.name=null,this.uri="",this.cost=this.origin=this.localControlFeature=null,this.forwardingFlags=new ForwardingFlags,this.strategy=new Name,this.expirationPeriod=null)};exports.ControlParameters=ControlParameters;
+ControlParameters.prototype.clear=function(){this.faceId=this.name=null;this.uri="";this.cost=this.origin=this.localControlFeature=null;this.forwardingFlags=new ForwardingFlags;this.strategy=new Name;this.expirationPeriod=null};ControlParameters.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeControlParameters(this)};
+ControlParameters.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeControlParameters(this,a.buf(),!1):b.decodeControlParameters(this,a,!0)};ControlParameters.prototype.getName=function(){return this.name};ControlParameters.prototype.getFaceId=function(){return this.faceId};ControlParameters.prototype.getUri=function(){return this.uri};ControlParameters.prototype.getLocalControlFeature=function(){return this.localControlFeature};
+ControlParameters.prototype.getOrigin=function(){return this.origin};ControlParameters.prototype.getCost=function(){return this.cost};ControlParameters.prototype.getForwardingFlags=function(){return this.forwardingFlags};ControlParameters.prototype.getStrategy=function(){return this.strategy};ControlParameters.prototype.getExpirationPeriod=function(){return this.expirationPeriod};ControlParameters.prototype.setName=function(a){this.name="object"===typeof a&&a instanceof Name?new Name(a):null};
+ControlParameters.prototype.setFaceId=function(a){this.faceId=a};ControlParameters.prototype.setUri=function(a){this.uri=a||""};ControlParameters.prototype.setLocalControlFeature=function(a){this.localControlFeature=a};ControlParameters.prototype.setOrigin=function(a){this.origin=a};ControlParameters.prototype.setCost=function(a){this.cost=a};ControlParameters.prototype.setForwardingFlags=function(a){this.forwardingFlags="object"===typeof a&&a instanceof ForwardingFlags?new ForwardingFlags(a):new ForwardingFlags};
+ControlParameters.prototype.setStrategy=function(a){this.strategy="object"===typeof a&&a instanceof Name?new Name(a):new Name};ControlParameters.prototype.setExpirationPeriod=function(a){this.expirationPeriod=a};
+var ControlParameters=require("./control-parameters.js").ControlParameters,WireFormat=require("./encoding/wire-format.js").WireFormat,Blob=require("./util/blob.js").Blob,ControlResponse=function ControlResponse(b){"object"===typeof b&&b instanceof ControlResponse?(this.statusCode_=b.statusCode_,this.statusText_=b.statusText_,this.bodyAsControlParameters_=null==b.bodyAsControlParameters_?null:new ControlParameters(b.bodyAsControlParameters_)):(this.statusCode_=null,this.statusText_="",this.bodyAsControlParameters_=
+null)};exports.ControlResponse=ControlResponse;ControlResponse.prototype.clear=function(){this.statusCode_=null;this.statusText_="";this.bodyAsControlParameters_=null};ControlResponse.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeControlResponse(this)};ControlResponse.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeControlResponse(this,a.buf(),!1):b.decodeControlResponse(this,a,!0)};
+ControlResponse.prototype.getStatusCode=function(){return this.statusCode_};ControlResponse.prototype.getStatusText=function(){return this.statusText_};ControlResponse.prototype.getBodyAsControlParameters=function(){return this.bodyAsControlParameters_};ControlResponse.prototype.setStatusCode=function(a){this.statusCode_=a;return this};ControlResponse.prototype.setStatusText=function(a){this.statusText_=a||"";return this};
+ControlResponse.prototype.setBodyAsControlParameters=function(a){this.bodyAsControlParameters_="object"===typeof a&&a instanceof ControlParameters?new ControlParameters(a):null;return this};Name=require("./name.js").Name;NdnRegexMatcher=require("./util/ndn-regex-matcher.js").NdnRegexMatcher;
+InterestFilter=function InterestFilter(b,c){"object"===typeof b&&b instanceof InterestFilter?(this.prefix=new Name(b.prefix),this.regexFilter=b.regexFilter,this.regexFilterPattern=b.regexFilterPattern):(this.prefix=new Name(b),c?(this.regexFilter=c,this.regexFilterPattern=InterestFilter.makePattern(c)):this.regexFilterPattern=this.regexFilter=null)};exports.InterestFilter=InterestFilter;
+InterestFilter.prototype.doesMatch=function(a){return a.size()<this.prefix.size()?!1:this.hasRegexFilter()?this.prefix.match(a)?null!=NdnRegexMatcher.match(this.regexFilterPattern,a.getSubName(this.prefix.size())):!1:this.prefix.match(a)};InterestFilter.prototype.getPrefix=function(){return this.prefix};InterestFilter.prototype.hasRegexFilter=function(){return null!=this.regexFilter};InterestFilter.prototype.getRegexFilter=function(){return this.regexFilter};
+InterestFilter.makePattern=function(a){if(0==a.length)return"^$";"^"!=a[0]&&(a="^"+a);"$"!=a[a.length-1]&&(a+="$");return a};var Name=require("./name.js").Name,Blob=require("./util/blob.js").Blob,WireFormat=require("./encoding/wire-format.js").WireFormat,DelegationSet=function DelegationSet(b){this.delegations_="object"===typeof b&&b instanceof DelegationSet?b.delegations_.slice(0):[]};exports.DelegationSet=DelegationSet;DelegationSet.Delegation=function(a,b){this.preference_=a;this.name_=new Name(b)};
+DelegationSet.Delegation.prototype.getPreference=function(){return this.preference_};DelegationSet.Delegation.prototype.getName=function(){return this.name_};DelegationSet.Delegation.prototype.compare=function(a){return this.preference_<a.preference_?-1:this.preference_>a.preference_?1:this.name_.compare(a.name_)};
+DelegationSet.prototype.add=function(a,b){this.remove(b);for(var c=new DelegationSet.Delegation(a,b),d=0;d<this.delegations_.length&&!(0<=this.delegations_[d].compare(c));)++d;this.delegations_.splice(d,0,c)};DelegationSet.prototype.addUnsorted=function(a,b){this.delegations_.push(new DelegationSet.Delegation(a,b))};DelegationSet.prototype.remove=function(a){for(var b=!1,c=this.delegations_.length-1;0<=c;--c)this.delegations_[c].getName().equals(a)&&(b=!0,this.delegations_.splice(c,1));return b};
+DelegationSet.prototype.clear=function(){this.delegations_=[]};DelegationSet.prototype.size=function(){return this.delegations_.length};DelegationSet.prototype.get=function(a){return this.delegations_[a]};DelegationSet.prototype.find=function(a){for(var b=0;b<this.delegations_.length;++b)if(this.delegations_[b].getName().equals(a))return b;return-1};DelegationSet.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeDelegationSet(this)};
+DelegationSet.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeDelegationSet(this,a.buf(),!1):b.decodeDelegationSet(this,a,!0)};DelegationSet=require("./delegation-set.js").DelegationSet;ContentType=require("./meta-info.js").ContentType;WireFormat=require("./encoding/wire-format.js").WireFormat;Data=require("./data.js").Data;
+Link=function(a){this.delegations_=new DelegationSet;if(a instanceof Data){if(Data.call(this,a),!this.getContent().isNull())try{this.delegations_.wireDecode(this.getContent()),this.getMetaInfo().setType(ContentType.LINK)}catch(b){this.delegations_.clear()}}else void 0!=a?Data.call(this,a):Data.call(this),this.getMetaInfo().setType(ContentType.LINK)};Link.prototype=new Data;Link.prototype.name="Link";exports.Link=Link;
+Link.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();Data.prototype.wireDecode.call(this,a,b);if(this.getMetaInfo().getType()!=ContentType.LINK)throw Error("Link.wireDecode: MetaInfo ContentType is not LINK.");this.delegations_.wireDecode(this.getContent())};Link.prototype.addDelegation=function(a,b,c){c=c||WireFormat.getDefaultWireFormat();this.delegations_.add(a,b);this.encodeContent(c);return this};
+Link.prototype.removeDelegation=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=this.delegations_.remove(a);c&&this.encodeContent(b);return c};Link.prototype.getDelegations=function(){return this.delegations_};Link.prototype.encodeContent=function(a){this.setContent(this.delegations_.wireEncode(a));this.getMetaInfo().setType(ContentType.LINK)};var NetworkNack=function NetworkNack(){this.reason_=NetworkNack.Reason.NONE;this.otherReasonCode_=-1};exports.NetworkNack=NetworkNack;
+NetworkNack.Reason={NONE:0,CONGESTION:50,DUPLICATE:100,NO_ROUTE:150,OTHER_CODE:32767};NetworkNack.prototype.getReason=function(){return this.reason_};NetworkNack.prototype.getOtherReasonCode=function(){return this.otherReasonCode_};NetworkNack.prototype.setReason=function(a){this.reason_=a};NetworkNack.prototype.setOtherReasonCode=function(a){if(0>a)throw Error("NetworkNack other reason code must be non-negative");this.otherReasonCode_=a};
+NetworkNack.getFirstHeader=function(a){for(var b=0;b<a.countHeaderFields();++b){var c=a.getHeaderField(b);if(c instanceof NetworkNack)return c}return null};
+var Crypto=require("../crypto.js"),Blob=require("../util/blob.js").Blob,Name=require("../name.js").Name,ForwardingFlags=require("../forwarding-flags").ForwardingFlags,Tlv=require("./tlv/tlv.js").Tlv,TlvEncoder=require("./tlv/tlv-encoder.js").TlvEncoder,TlvDecoder=require("./tlv/tlv-decoder.js").TlvDecoder,WireFormat=require("./wire-format.js").WireFormat,Exclude=require("../exclude.js").Exclude,ContentType=require("../meta-info.js").ContentType,KeyLocatorType=require("../key-locator.js").KeyLocatorType,
+Sha256WithRsaSignature=require("../sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("../sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,GenericSignature=require("../generic-signature.js").GenericSignature,HmacWithSha256Signature=require("../hmac-with-sha256-signature.js").HmacWithSha256Signature,DigestSha256Signature=require("../digest-sha256-signature.js").DigestSha256Signature,ControlParameters=require("../control-parameters.js").ControlParameters,
+ForwardingFlags=require("../forwarding-flags.js").ForwardingFlags,NetworkNack=require("../network-nack.js").NetworkNack,IncomingFaceId=require("../lp/incoming-face-id.js").IncomingFaceId,DecodingException=require("./decoding-exception.js").DecodingException,Tlv0_2WireFormat=function(){WireFormat.call(this)};Tlv0_2WireFormat.prototype=new WireFormat;Tlv0_2WireFormat.prototype.name="Tlv0_2WireFormat";exports.Tlv0_2WireFormat=Tlv0_2WireFormat;Tlv0_2WireFormat.instance=null;
+Tlv0_2WireFormat.prototype.encodeName=function(a){var b=new TlvEncoder;Tlv0_2WireFormat.encodeName(a,b);return new Blob(b.getOutput(),!1)};Tlv0_2WireFormat.prototype.decodeName=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);Tlv0_2WireFormat.decodeName(a,b,c)};
+Tlv0_2WireFormat.prototype.encodeInterest=function(a){var b=new TlvEncoder(256),c=b.getLength();b.writeOptionalNonNegativeIntegerTlv(Tlv.SelectedDelegation,a.getSelectedDelegationIndex());var d=a.getLinkWireEncoding(this);d.isNull()||b.writeBuffer(d.buf());b.writeOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime,a.getInterestLifetimeMilliseconds());if(a.getNonce().isNull()||0==a.getNonce().size())b.writeBlobTlv(Tlv.Nonce,Crypto.randomBytes(4));else if(4>a.getNonce().size()){d=Buffer(4);a.getNonce().buf().copy(d);
+for(var e=a.getNonce().size();4>e;++e)d[e]=Crypto.randomBytes(1)[0];b.writeBlobTlv(Tlv.Nonce,d)}else 4==a.getNonce().size()?b.writeBlobTlv(Tlv.Nonce,a.getNonce().buf()):b.writeBlobTlv(Tlv.Nonce,a.getNonce().buf().slice(0,4));Tlv0_2WireFormat.encodeSelectors(a,b);d=Tlv0_2WireFormat.encodeName(a.getName(),b);a=b.getLength()-d.signedPortionBeginOffset;d=b.getLength()-d.signedPortionEndOffset;b.writeTypeAndLength(Tlv.Interest,b.getLength()-c);c=b.getLength()-a;a=b.getLength()-d;return{encoding:new Blob(b.getOutput(),
+!1),signedPortionBeginOffset:c,signedPortionEndOffset:a}};
+Tlv0_2WireFormat.prototype.decodeInterest=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);var d=b.readNestedTlvsStart(Tlv.Interest),e=Tlv0_2WireFormat.decodeName(a.getName(),b,c);b.peekType(Tlv.Selectors,d)&&Tlv0_2WireFormat.decodeSelectors(a,b,c);var f=b.readBlobTlv(Tlv.Nonce);a.setInterestLifetimeMilliseconds(b.readOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime,d));if(b.peekType(Tlv.Data,d)){var g=b.getOffset(),h=b.readNestedTlvsStart(Tlv.Data);b.seek(h);a.setLinkWireEncoding(new Blob(b.getSlice(g,
+h),c),this)}else a.unsetLink();a.setSelectedDelegationIndex(b.readOptionalNonNegativeIntegerTlv(Tlv.SelectedDelegation,d));if(null!=a.getSelectedDelegationIndex()&&0<=a.getSelectedDelegationIndex()&&!a.hasLink())throw Error("Interest has a selected delegation, but no link object");a.setNonce(new Blob(f,c));b.finishNestedTlvs(d);return e};
+Tlv0_2WireFormat.prototype.encodeData=function(a){var b=new TlvEncoder(1500),c=b.getLength();b.writeBlobTlv(Tlv.SignatureValue,a.getSignature().getSignature().buf());var d=b.getLength();Tlv0_2WireFormat.encodeSignatureInfo_(a.getSignature(),b);b.writeBlobTlv(Tlv.Content,a.getContent().buf());Tlv0_2WireFormat.encodeMetaInfo(a.getMetaInfo(),b);Tlv0_2WireFormat.encodeName(a.getName(),b);a=b.getLength();b.writeTypeAndLength(Tlv.Data,b.getLength()-c);c=b.getLength()-a;d=b.getLength()-d;return{encoding:new Blob(b.getOutput(),
+!1),signedPortionBeginOffset:c,signedPortionEndOffset:d}};
+Tlv0_2WireFormat.prototype.decodeData=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);var d=b.readNestedTlvsStart(Tlv.Data),e=b.getOffset();Tlv0_2WireFormat.decodeName(a.getName(),b,c);Tlv0_2WireFormat.decodeMetaInfo(a.getMetaInfo(),b,c);a.setContent(new Blob(b.readBlobTlv(Tlv.Content),c));Tlv0_2WireFormat.decodeSignatureInfo(a,b,c);var f=b.getOffset();a.getSignature().setSignature(new Blob(b.readBlobTlv(Tlv.SignatureValue),c));b.finishNestedTlvs(d);return{signedPortionBeginOffset:e,signedPortionEndOffset:f}};
+Tlv0_2WireFormat.prototype.encodeControlParameters=function(a){var b=new TlvEncoder(256);Tlv0_2WireFormat.encodeControlParameters(a,b);return new Blob(b.getOutput(),!1)};Tlv0_2WireFormat.prototype.decodeControlParameters=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);Tlv0_2WireFormat.decodeControlParameters(a,b,c)};
+Tlv0_2WireFormat.prototype.encodeControlResponse=function(a){var b=new TlvEncoder(256),c=b.getLength();null!=a.getBodyAsControlParameters()&&Tlv0_2WireFormat.encodeControlParameters(a.getBodyAsControlParameters(),b);b.writeBlobTlv(Tlv.NfdCommand_StatusText,(new Blob(a.getStatusText())).buf());b.writeNonNegativeIntegerTlv(Tlv.NfdCommand_StatusCode,a.getStatusCode());b.writeTypeAndLength(Tlv.NfdCommand_ControlResponse,b.getLength()-c);return new Blob(b.getOutput(),!1)};
+Tlv0_2WireFormat.prototype.decodeControlResponse=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);var d=b.readNestedTlvsStart(Tlv.NfdCommand_ControlResponse);a.setStatusCode(b.readNonNegativeIntegerTlv(Tlv.NfdCommand_StatusCode));var e=new Blob(b.readBlobTlv(Tlv.NfdCommand_StatusText),!1);a.setStatusText(e.toString());b.peekType(Tlv.ControlParameters_ControlParameters,d)?(a.setBodyAsControlParameters(new ControlParameters),Tlv0_2WireFormat.decodeControlParameters(a.getBodyAsControlParameters(),
+b,c)):a.setBodyAsControlParameters(null);b.finishNestedTlvs(d)};Tlv0_2WireFormat.prototype.encodeSignatureInfo=function(a){var b=new TlvEncoder(256);Tlv0_2WireFormat.encodeSignatureInfo_(a,b);return new Blob(b.getOutput(),!1)};Tlv0_2WireFormat.SignatureHolder=function(){};Tlv0_2WireFormat.SignatureHolder.prototype.setSignature=function(a){this.signature=a};Tlv0_2WireFormat.SignatureHolder.prototype.getSignature=function(){return this.signature};
+Tlv0_2WireFormat.prototype.decodeSignatureInfoAndValue=function(a,b,c){null==c&&(c=!0);var d=new Tlv0_2WireFormat.SignatureHolder;a=new TlvDecoder(a);Tlv0_2WireFormat.decodeSignatureInfo(d,a,c);a=new TlvDecoder(b);d.getSignature().setSignature(new Blob(a.readBlobTlv(Tlv.SignatureValue),c));return d.getSignature()};Tlv0_2WireFormat.prototype.encodeSignatureValue=function(a){var b=new TlvEncoder(256);b.writeBlobTlv(Tlv.SignatureValue,a.getSignature().buf());return new Blob(b.getOutput(),!1)};
+Tlv0_2WireFormat.prototype.decodeLpPacket=function(a,b,c){null==c&&(c=!0);a.clear();for(var d=new TlvDecoder(b),e=d.readNestedTlvsStart(Tlv.LpPacket_LpPacket);d.getOffset()<e;){var f=d.readVarNumber(),g=d.readVarNumber(),h=d.getOffset()+g;if(h>b.length)throw new DecodingException(Error("TLV length exceeds the buffer length"));if(f==Tlv.LpPacket_Fragment){a.setFragmentWireEncoding(new Blob(d.getSlice(d.getOffset(),h),c));d.seek(h);break}else if(f==Tlv.LpPacket_Nack)g=new NetworkNack,f=d.readOptionalNonNegativeIntegerTlv(Tlv.LpPacket_NackReason,
+h),0>f||f==NetworkNack.Reason.NONE?g.setReason(NetworkNack.Reason.NONE):f==NetworkNack.Reason.CONGESTION||f==NetworkNack.Reason.DUPLICATE||f==NetworkNack.Reason.NO_ROUTE?g.setReason(f):(g.setReason(NetworkNack.Reason.OTHER_CODE),g.setOtherReasonCode(f)),a.addHeaderField(g);else if(f==Tlv.LpPacket_IncomingFaceId)f=new IncomingFaceId,f.setFaceId(d.readNonNegativeInteger(g)),a.addHeaderField(f);else{if(!(f>=Tlv.LpPacket_IGNORE_MIN&&f<=Tlv.LpPacket_IGNORE_MAX&&1===(f&1)))throw new DecodingException(Error("Did not get the expected TLV type"));
+d.seek(h)}d.finishNestedTlvs(h)}d.finishNestedTlvs(e)};Tlv0_2WireFormat.prototype.encodeDelegationSet=function(a){for(var b=new TlvEncoder(256),c=a.size()-1;0<=c;--c){var d=b.getLength();Tlv0_2WireFormat.encodeName(a.get(c).getName(),b);b.writeNonNegativeIntegerTlv(Tlv.Link_Preference,a.get(c).getPreference());b.writeTypeAndLength(Tlv.Link_Delegation,b.getLength()-d)}return new Blob(b.getOutput(),!1)};
+Tlv0_2WireFormat.prototype.decodeDelegationSet=function(a,b,c){null==c&&(c=!0);var d=new TlvDecoder(b);b=b.length;for(a.clear();d.getOffset()<b;){d.readTypeAndLength(Tlv.Link_Delegation);var e=d.readNonNegativeIntegerTlv(Tlv.Link_Preference),f=new Name;Tlv0_2WireFormat.decodeName(f,d,c);a.addUnsorted(e,f)}};
+Tlv0_2WireFormat.prototype.encodeEncryptedContent=function(a){var b=new TlvEncoder(256),c=b.getLength();b.writeBlobTlv(Tlv.Encrypt_EncryptedPayload,a.getPayload().buf());b.writeOptionalBlobTlv(Tlv.Encrypt_InitialVector,a.getInitialVector().buf());b.writeNonNegativeIntegerTlv(Tlv.Encrypt_EncryptionAlgorithm,a.getAlgorithmType());Tlv0_2WireFormat.encodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b);b.writeTypeAndLength(Tlv.Encrypt_EncryptedContent,b.getLength()-c);return new Blob(b.getOutput(),!1)};
+Tlv0_2WireFormat.prototype.decodeEncryptedContent=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);var d=b.readNestedTlvsStart(Tlv.Encrypt_EncryptedContent);Tlv0_2WireFormat.decodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b,c);a.setAlgorithmType(b.readNonNegativeIntegerTlv(Tlv.Encrypt_EncryptionAlgorithm));a.setInitialVector(new Blob(b.readOptionalBlobTlv(Tlv.Encrypt_InitialVector,d),c));a.setPayload(new Blob(b.readBlobTlv(Tlv.Encrypt_EncryptedPayload),c));b.finishNestedTlvs(d)};
+Tlv0_2WireFormat.get=function(){null===Tlv0_2WireFormat.instance&&(Tlv0_2WireFormat.instance=new Tlv0_2WireFormat);return Tlv0_2WireFormat.instance};Tlv0_2WireFormat.encodeNameComponent=function(a,b){var c=a.isImplicitSha256Digest()?Tlv.ImplicitSha256DigestComponent:Tlv.NameComponent;b.writeBlobTlv(c,a.getValue().buf())};
+Tlv0_2WireFormat.decodeNameComponent=function(a,b){null==b&&(b=!0);var c=a.getOffset(),d=a.readVarNumber();a.seek(c);c=new Blob(a.readBlobTlv(d),b);return d===Tlv.ImplicitSha256DigestComponent?Name.Component.fromImplicitSha256Digest(c):new Name.Component(c)};
+Tlv0_2WireFormat.encodeName=function(a,b){for(var c=b.getLength(),d,e=a.size()-1;0<=e;--e)Tlv0_2WireFormat.encodeNameComponent(a.get(e),b),e==a.size()-1&&(d=b.getLength());e=b.getLength();b.writeTypeAndLength(Tlv.Name,b.getLength()-c);c=b.getLength()-e;d=0==a.size()?c:b.getLength()-d;return{signedPortionBeginOffset:c,signedPortionEndOffset:d}};
+Tlv0_2WireFormat.decodeName=function(a,b,c){a.clear();for(var d=b.readNestedTlvsStart(Tlv.Name),e=b.getOffset(),f=e;b.getOffset()<d;)f=b.getOffset(),a.append(Tlv0_2WireFormat.decodeNameComponent(b,c));b.finishNestedTlvs(d);return{signedPortionBeginOffset:e,signedPortionEndOffset:f}};
+Tlv0_2WireFormat.encodeSelectors=function(a,b){var c=b.getLength();a.getMustBeFresh()&&b.writeTypeAndLength(Tlv.MustBeFresh,0);b.writeOptionalNonNegativeIntegerTlv(Tlv.ChildSelector,a.getChildSelector());0<a.getExclude().size()&&Tlv0_2WireFormat.encodeExclude(a.getExclude(),b);null!=a.getKeyLocator().getType()&&Tlv0_2WireFormat.encodeKeyLocator(Tlv.PublisherPublicKeyLocator,a.getKeyLocator(),b);b.writeOptionalNonNegativeIntegerTlv(Tlv.MaxSuffixComponents,a.getMaxSuffixComponents());b.writeOptionalNonNegativeIntegerTlv(Tlv.MinSuffixComponents,
+a.getMinSuffixComponents());b.getLength()!=c&&b.writeTypeAndLength(Tlv.Selectors,b.getLength()-c)};
+Tlv0_2WireFormat.decodeSelectors=function(a,b,c){null==c&&(c=!0);var d=b.readNestedTlvsStart(Tlv.Selectors);a.setMinSuffixComponents(b.readOptionalNonNegativeIntegerTlv(Tlv.MinSuffixComponents,d));a.setMaxSuffixComponents(b.readOptionalNonNegativeIntegerTlv(Tlv.MaxSuffixComponents,d));b.peekType(Tlv.PublisherPublicKeyLocator,d)?Tlv0_2WireFormat.decodeKeyLocator(Tlv.PublisherPublicKeyLocator,a.getKeyLocator(),b,c):a.getKeyLocator().clear();b.peekType(Tlv.Exclude,d)?Tlv0_2WireFormat.decodeExclude(a.getExclude(),
+b,c):a.getExclude().clear();a.setChildSelector(b.readOptionalNonNegativeIntegerTlv(Tlv.ChildSelector,d));a.setMustBeFresh(b.readBooleanTlv(Tlv.MustBeFresh,d));b.finishNestedTlvs(d)};Tlv0_2WireFormat.encodeExclude=function(a,b){for(var c=b.getLength(),d=a.size()-1;0<=d;--d){var e=a.get(d);e==Exclude.ANY?b.writeTypeAndLength(Tlv.Any,0):Tlv0_2WireFormat.encodeNameComponent(e,b)}b.writeTypeAndLength(Tlv.Exclude,b.getLength()-c)};
+Tlv0_2WireFormat.decodeExclude=function(a,b,c){null==c&&(c=!0);var d=b.readNestedTlvsStart(Tlv.Exclude);for(a.clear();b.getOffset()<d;)b.peekType(Tlv.Any,d)?(b.readBooleanTlv(Tlv.Any,d),a.appendAny()):a.appendComponent(Tlv0_2WireFormat.decodeNameComponent(b,c));b.finishNestedTlvs(d)};
+Tlv0_2WireFormat.encodeKeyLocator=function(a,b,c){var d=c.getLength();if(null!=b.getType())if(b.getType()==KeyLocatorType.KEYNAME)Tlv0_2WireFormat.encodeName(b.getKeyName(),c);else if(b.getType()==KeyLocatorType.KEY_LOCATOR_DIGEST&&0<b.getKeyData().size())c.writeBlobTlv(Tlv.KeyLocatorDigest,b.getKeyData().buf());else throw Error("Unrecognized KeyLocatorType "+b.getType());c.writeTypeAndLength(a,c.getLength()-d)};
+Tlv0_2WireFormat.decodeKeyLocator=function(a,b,c,d){null==d&&(d=!0);a=c.readNestedTlvsStart(a);b.clear();if(c.getOffset()!=a){if(c.peekType(Tlv.Name,a))b.setType(KeyLocatorType.KEYNAME),Tlv0_2WireFormat.decodeName(b.getKeyName(),c,d);else if(c.peekType(Tlv.KeyLocatorDigest,a))b.setType(KeyLocatorType.KEY_LOCATOR_DIGEST),b.setKeyData(new Blob(c.readBlobTlv(Tlv.KeyLocatorDigest),d));else throw new DecodingException(Error("decodeKeyLocator: Unrecognized key locator type"));c.finishNestedTlvs(a)}};
+Tlv0_2WireFormat.encodeSignatureInfo_=function(a,b){if(a instanceof GenericSignature){var c=a.getSignatureInfoEncoding();try{var d=new TlvDecoder(c.buf()),e=d.readNestedTlvsStart(Tlv.SignatureInfo);d.readNonNegativeIntegerTlv(Tlv.SignatureType);d.finishNestedTlvs(e)}catch(f){throw Error("The GenericSignature encoding is not a valid NDN-TLV SignatureInfo: "+f.message);}b.writeBuffer(c.buf())}else{c=b.getLength();if(a instanceof Sha256WithRsaSignature)Tlv0_2WireFormat.encodeKeyLocator(Tlv.KeyLocator,
+a.getKeyLocator(),b),b.writeNonNegativeIntegerTlv(Tlv.SignatureType,Tlv.SignatureType_SignatureSha256WithRsa);else if(a instanceof Sha256WithEcdsaSignature)Tlv0_2WireFormat.encodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b),b.writeNonNegativeIntegerTlv(Tlv.SignatureType,Tlv.SignatureType_SignatureSha256WithEcdsa);else if(a instanceof HmacWithSha256Signature)Tlv0_2WireFormat.encodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b),b.writeNonNegativeIntegerTlv(Tlv.SignatureType,Tlv.SignatureType_SignatureHmacWithSha256);
+else if(a instanceof DigestSha256Signature)b.writeNonNegativeIntegerTlv(Tlv.SignatureType,Tlv.SignatureType_DigestSha256);else throw Error("encodeSignatureInfo: Unrecognized Signature object type");b.writeTypeAndLength(Tlv.SignatureInfo,b.getLength()-c)}};
+Tlv0_2WireFormat.decodeSignatureInfo=function(a,b,c){null==c&&(c=!0);var d=b.getOffset(),e=b.readNestedTlvsStart(Tlv.SignatureInfo),f=b.readNonNegativeIntegerTlv(Tlv.SignatureType);f==Tlv.SignatureType_SignatureSha256WithRsa?(a.setSignature(new Sha256WithRsaSignature),a=a.getSignature(),Tlv0_2WireFormat.decodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b,c)):f==Tlv.SignatureType_SignatureSha256WithEcdsa?(a.setSignature(new Sha256WithEcdsaSignature),a=a.getSignature(),Tlv0_2WireFormat.decodeKeyLocator(Tlv.KeyLocator,
+a.getKeyLocator(),b,c)):f==Tlv.SignatureType_SignatureHmacWithSha256?(a.setSignature(new HmacWithSha256Signature),a=a.getSignature(),Tlv0_2WireFormat.decodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b,c)):f==Tlv.SignatureType_DigestSha256?a.setSignature(new DigestSha256Signature):(a.setSignature(new GenericSignature),a=a.getSignature(),a.setSignatureInfoEncoding(new Blob(b.getSlice(d,e),c),f));b.finishNestedTlvs(e)};
+Tlv0_2WireFormat.encodeMetaInfo=function(a,b){var c=b.getLength(),d=a.getFinalBlockId().getValue().buf();null!=d&&0<d.length&&(d=b.getLength(),Tlv0_2WireFormat.encodeNameComponent(a.getFinalBlockId(),b),b.writeTypeAndLength(Tlv.FinalBlockId,b.getLength()-d));b.writeOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod,a.getFreshnessPeriod());if(a.getType()!=ContentType.BLOB)if(a.getType()==ContentType.LINK||a.getType()==ContentType.KEY||a.getType()==ContentType.NACK)b.writeNonNegativeIntegerTlv(Tlv.ContentType,
+a.getType());else if(a.getType()==ContentType.OTHER_CODE)b.writeNonNegativeIntegerTlv(Tlv.ContentType,a.getOtherTypeCode());else throw Error("unrecognized TLV ContentType");b.writeTypeAndLength(Tlv.MetaInfo,b.getLength()-c)};
+Tlv0_2WireFormat.decodeMetaInfo=function(a,b,c){null==c&&(c=!0);var d=b.readNestedTlvsStart(Tlv.MetaInfo),e=b.readOptionalNonNegativeIntegerTlv(Tlv.ContentType,d);null==e||0>e||e===ContentType.BLOB?a.setType(ContentType.BLOB):e===ContentType.LINK||e===ContentType.KEY||e===ContentType.NACK?a.setType(e):(a.setType(ContentType.OTHER_CODE),a.setOtherTypeCode(e));a.setFreshnessPeriod(b.readOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod,d));b.peekType(Tlv.FinalBlockId,d)?(e=b.readNestedTlvsStart(Tlv.FinalBlockId),
+a.setFinalBlockId(Tlv0_2WireFormat.decodeNameComponent(b,c)),b.finishNestedTlvs(e)):a.setFinalBlockId(null);b.finishNestedTlvs(d)};
+Tlv0_2WireFormat.encodeControlParameters=function(a,b){var c=b.getLength();b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_ExpirationPeriod,a.getExpirationPeriod());if(0<a.getStrategy().size()){var d=b.getLength();Tlv0_2WireFormat.encodeName(a.getStrategy(),b);b.writeTypeAndLength(Tlv.ControlParameters_Strategy,b.getLength()-d)}d=a.getForwardingFlags().getNfdForwardingFlags();d!=(new ForwardingFlags).getNfdForwardingFlags()&&b.writeNonNegativeIntegerTlv(Tlv.ControlParameters_Flags,d);b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Cost,
+a.getCost());b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin,a.getOrigin());b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_LocalControlFeature,a.getLocalControlFeature());0!=a.getUri().length&&b.writeBlobTlv(Tlv.ControlParameters_Uri,(new Blob(a.getUri())).buf());b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId,a.getFaceId());null!=a.getName()&&Tlv0_2WireFormat.encodeName(a.getName(),b);b.writeTypeAndLength(Tlv.ControlParameters_ControlParameters,b.getLength()-
+c)};
+Tlv0_2WireFormat.decodeControlParameters=function(a,b,c){null==c&&(c=!0);a.clear();var d=b.readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);if(b.peekType(Tlv.Name,d)){var e=new Name;Tlv0_2WireFormat.decodeName(e,b,c);a.setName(e)}a.setFaceId(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId,d));b.peekType(Tlv.ControlParameters_Uri,d)&&(e=new Blob(b.readOptionalBlobTlv(Tlv.ControlParameters_Uri,d),!1),a.setUri(e.toString()));a.setLocalControlFeature(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_LocalControlFeature,d));
+a.setOrigin(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin,d));a.setCost(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Cost,d));b.peekType(Tlv.ControlParameters_Flags,d)&&(e=new ForwardingFlags,e.setNfdForwardingFlags(b.readNonNegativeIntegerTlv(Tlv.ControlParameters_Flags,d)),a.setForwardingFlags(e));b.peekType(Tlv.ControlParameters_Strategy,d)&&(e=b.readNestedTlvsStart(Tlv.ControlParameters_Strategy),Tlv0_2WireFormat.decodeName(a.getStrategy(),b,c),b.finishNestedTlvs(e));
+a.setExpirationPeriod(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_ExpirationPeriod,d));b.finishNestedTlvs(d)};var Tlv0_2WireFormat=require("./tlv-0_2-wire-format.js").Tlv0_2WireFormat,Tlv0_1_1WireFormat=function(){Tlv0_2WireFormat.call(this)};Tlv0_1_1WireFormat.prototype=new Tlv0_2WireFormat;Tlv0_1_1WireFormat.prototype.name="Tlv0_1_1WireFormat";exports.Tlv0_1_1WireFormat=Tlv0_1_1WireFormat;Tlv0_1_1WireFormat.instance=null;
+Tlv0_1_1WireFormat.get=function(){null===Tlv0_1_1WireFormat.instance&&(Tlv0_1_1WireFormat.instance=new Tlv0_1_1WireFormat);return Tlv0_1_1WireFormat.instance};var WireFormat=require("./wire-format.js").WireFormat,Tlv0_1_1WireFormat=require("./tlv-0_1_1-wire-format.js").Tlv0_1_1WireFormat,Tlv0_1WireFormat=function(){Tlv0_1_1WireFormat.call(this)};Tlv0_1WireFormat.prototype=new Tlv0_1_1WireFormat;Tlv0_1WireFormat.prototype.name="Tlv0_1WireFormat";exports.Tlv0_1WireFormat=Tlv0_1WireFormat;
+Tlv0_1WireFormat.instance=null;Tlv0_1WireFormat.get=function(){null===Tlv0_1WireFormat.instance&&(Tlv0_1WireFormat.instance=new Tlv0_1WireFormat);return Tlv0_1WireFormat.instance};WireFormat=require("./wire-format.js").WireFormat;Tlv0_2WireFormat=require("./tlv-0_2-wire-format.js").Tlv0_2WireFormat;TlvWireFormat=function(){Tlv0_2WireFormat.call(this)};TlvWireFormat.prototype=new Tlv0_2WireFormat;TlvWireFormat.prototype.name="TlvWireFormat";exports.TlvWireFormat=TlvWireFormat;
+TlvWireFormat.instance=null;TlvWireFormat.get=function(){null===TlvWireFormat.instance&&(TlvWireFormat.instance=new TlvWireFormat);return TlvWireFormat.instance};WireFormat.setDefaultWireFormat(TlvWireFormat.get());
+var DataUtils=require("./data-utils.js").DataUtils,KeyLocatorType=require("../key-locator.js").KeyLocatorType,Interest=require("../interest.js").Interest,Data=require("../data.js").Data,Sha256WithRsaSignature=require("../sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("../sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,HmacWithSha256Signature=require("../hmac-with-sha256-signature.js").HmacWithSha256Signature,DigestSha256Signature=require("../digest-sha256-signature.js").DigestSha256Signature,
+ContentType=require("../meta-info.js").ContentType,WireFormat=require("./wire-format.js").WireFormat,EncodingUtils=function(){};exports.EncodingUtils=EncodingUtils;EncodingUtils.encodeToHexInterest=function(a,b){b=b||WireFormat.getDefaultWireFormat();return DataUtils.toHex(a.wireEncode(b).buf())};EncodingUtils.encodeToHexData=function(a,b){b=b||WireFormat.getDefaultWireFormat();return DataUtils.toHex(a.wireEncode(b).buf())};
+EncodingUtils.decodeHexInterest=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=new Interest;c.wireDecode(DataUtils.toNumbers(a),b);return c};EncodingUtils.decodeHexData=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=new Data;c.wireDecode(DataUtils.toNumbers(a),b);return c};
+EncodingUtils.decodeSubjectPublicKeyInfo=function(a){a=DataUtils.toHex(a).toLowerCase();a=_x509_getPublicKeyHexArrayFromCertHex(a,_x509_getSubjectPublicKeyPosFromCertHex(a,0));var b=new RSAKey;b.setPublic(a[0],a[1]);return b};
+EncodingUtils.dataToHtml=function(a){function b(a){a=a.replace(/&/g,"&amp;");a=a.replace(/</g,"&lt;");c+=a;c+="<br/>"}if(-1==a)return"NO CONTENT FOUND";if(-2==a)return"CONTENT NAME IS EMPTY";var c="";b("name: "+a.getName().toUri());0<a.getContent().size()?(b("content (raw): "+a.getContent().buf().toString("binary")),b("content (hex): "+a.getContent().toHex())):b("content: <empty>");a.getMetaInfo().getType()!=ContentType.BLOB&&(a.getMetaInfo().getType()==ContentType.KEY?b("metaInfo.type: KEY"):a.getMetaInfo().getType()==
+ContentType.LINK?b("metaInfo.type: LINK"):a.getMetaInfo().getType()==ContentType.NACK?b("metaInfo.type: NACK"):a.getMetaInfo().getType()==ContentType.OTHER_CODE&&b("metaInfo.type: other code "+a.getMetaInfo().getOtherTypeCode()));b("metaInfo.freshnessPeriod (milliseconds): "+(0<=a.getMetaInfo().getFreshnessPeriod()?""+a.getMetaInfo().getFreshnessPeriod():"<none>"));b("metaInfo.finalBlockId: "+(0<a.getMetaInfo().getFinalBlockId().getValue().size()?a.getMetaInfo().getFinalBlockId().getValue().toHex():
+"<none>"));var d=null,e=a.getSignature();e instanceof Sha256WithRsaSignature?(e=a.getSignature(),b("Sha256WithRsa signature.signature: "+(0<e.getSignature().size()?e.getSignature().toHex():"<none>")),d=e.getKeyLocator()):e instanceof Sha256WithEcdsaSignature?(e=a.getSignature(),b("Sha256WithEcdsa signature.signature: "+(0<e.getSignature().size()?e.getSignature().toHex():"<none>")),d=e.getKeyLocator()):e instanceof HmacWithSha256Signature?(e=a.getSignature(),b("HmacWithSha256 signature.signature: "+
+(0<e.getSignature().size()?e.getSignature().toHex():"<none>")),d=e.getKeyLocator()):e instanceof DigestSha256Signature&&(e=a.getSignature(),b("DigestSha256 signature.signature: "+(0<e.getSignature().size()?e.getSignature().toHex():"<none>")));null!==d&&(null==d.getType()?b("signature.keyLocator: <none>"):d.getType()==KeyLocatorType.KEY_LOCATOR_DIGEST?b("signature.keyLocator: KeyLocatorDigest: "+d.getKeyData().toHex()):d.getType()==KeyLocatorType.KEYNAME?b("signature.keyLocator: KeyName: "+d.getKeyName().toUri()):
+b("signature.keyLocator: <unrecognized ndn_KeyLocatorType>"));return c};var encodeToHexInterest=function(a){return EncodingUtils.encodeToHexInterest(a)},decodeHexInterest=function(a){return EncodingUtils.decodeHexInterest(a)},decodeSubjectPublicKeyInfo=function(a){return EncodingUtils.decodeSubjectPublicKeyInfo(a)};function encodeToBinaryInterest(a){return a.wireEncode().buf()}
+var Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,DecryptKey=require("../decrypt-key.js").DecryptKey,EncryptKey=require("../encrypt-key.js").EncryptKey,EncryptAlgorithmType=require("./encrypt-params.js").EncryptAlgorithmType,UseSubtleCrypto=require("../../use-subtle-crypto-node.js").UseSubtleCrypto,SyncPromise=require("../../util/sync-promise.js").SyncPromise,AesAlgorithm=function(){};exports.AesAlgorithm=AesAlgorithm;
+AesAlgorithm.generateKey=function(a){a=Crypto.randomBytes(a.getKeySize()/8);return new DecryptKey(new Blob(a,!1))};AesAlgorithm.deriveEncryptKey=function(a){return new EncryptKey(a)};
+AesAlgorithm.decryptPromise=function(a,b,c,d){if(UseSubtleCrypto()&&!d&&c.getAlgorithmType()!=EncryptAlgorithmType.AesEcb)return c.getAlgorithmType()==EncryptAlgorithmType.AesCbc?crypto.subtle.importKey("raw",a.buf(),{name:"AES-CBC"},!1,["encrypt","decrypt"]).then(function(a){return crypto.subtle.decrypt({name:"AES-CBC",iv:c.getInitialVector().buf()},a,b.buf())}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!1))}):Promise.reject(Error("unsupported encryption mode"));if(c.getAlgorithmType()==
+EncryptAlgorithmType.AesEcb)try{var e=Crypto.createDecipheriv("aes-128-ecb",a.buf(),"");return SyncPromise.resolve(new Blob(Buffer.concat([e.update(b.buf()),e["final"]()]),!1))}catch(f){return SyncPromise.reject(f)}else if(c.getAlgorithmType()==EncryptAlgorithmType.AesCbc)try{return e=Crypto.createDecipheriv("aes-128-cbc",a.buf(),c.getInitialVector().buf()),SyncPromise.resolve(new Blob(Buffer.concat([e.update(b.buf()),e["final"]()]),!1))}catch(g){return SyncPromise.reject(g)}else return SyncPromise.reject(Error("unsupported encryption mode"))};
+AesAlgorithm.decrypt=function(a,b,c){return SyncPromise.getValue(this.decryptPromise(a,b,c,!0))};
+AesAlgorithm.encryptPromise=function(a,b,c,d){return c.getAlgorithmType()==EncryptAlgorithmType.AesCbc&&c.getInitialVector().size()!=AesAlgorithm.BLOCK_SIZE?SyncPromise.reject(Error("incorrect initial vector size")):UseSubtleCrypto()&&!d&&c.getAlgorithmType()!=EncryptAlgorithmType.AesEcb?c.getAlgorithmType()==EncryptAlgorithmType.AesCbc?crypto.subtle.importKey("raw",a.buf(),{name:"AES-CBC"},!1,["encrypt","decrypt"]).then(function(a){return crypto.subtle.encrypt({name:"AES-CBC",iv:c.getInitialVector().buf()},
+a,b.buf())}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!1))}):Promise.reject(Error("unsupported encryption mode")):c.getAlgorithmType()==EncryptAlgorithmType.AesEcb?(a=Crypto.createCipheriv("aes-128-ecb",a.buf(),""),SyncPromise.resolve(new Blob(Buffer.concat([a.update(b.buf()),a["final"]()]),!1))):c.getAlgorithmType()==EncryptAlgorithmType.AesCbc?(a=Crypto.createCipheriv("aes-128-cbc",a.buf(),c.getInitialVector().buf()),SyncPromise.resolve(new Blob(Buffer.concat([a.update(b.buf()),
+a["final"]()]),!1))):SyncPromise.reject(Error("unsupported encryption mode"))};AesAlgorithm.encrypt=function(a,b,c){return SyncPromise.getValue(this.encryptPromise(a,b,c,!0))};AesAlgorithm.BLOCK_SIZE=16;Crypto=require("../../crypto.js");Blob=require("../../util/blob.js").Blob;EncryptAlgorithmType=function(){};exports.EncryptAlgorithmType=EncryptAlgorithmType;EncryptAlgorithmType.AesEcb=0;EncryptAlgorithmType.AesCbc=1;EncryptAlgorithmType.RsaPkcs=2;EncryptAlgorithmType.RsaOaep=3;
+var EncryptParams=function(a,b){this.algorithmType_=a;if(null!=b&&0<b){var c=Crypto.randomBytes(b);this.initialVector_=new Blob(c,!1)}else this.initialVector_=new Blob};exports.EncryptParams=EncryptParams;EncryptParams.prototype.getAlgorithmType=function(){return this.algorithmType_};EncryptParams.prototype.getInitialVector=function(){return this.initialVector_};EncryptParams.prototype.setAlgorithmType=function(a){this.algorithmType_=a;return this};
+EncryptParams.prototype.setInitialVector=function(a){this.initialVector_="object"===typeof a&&a instanceof Blob?a:new Blob(a);return this};
+var Crypto=require("../../crypto.js"),Name=require("../../name.js").Name,KeyLocator=require("../../key-locator.js").KeyLocator,KeyLocatorType=require("../../key-locator.js").KeyLocatorType,TlvWireFormat=require("../../encoding/tlv-wire-format.js").TlvWireFormat,Blob=require("../../util/blob.js").Blob,AesAlgorithm=require("./aes-algorithm.js").AesAlgorithm,RsaAlgorithm=require("./rsa-algorithm.js").RsaAlgorithm,EncryptParams=require("./encrypt-params.js").EncryptParams,EncryptAlgorithmType=require("./encrypt-params.js").EncryptAlgorithmType,
+EncryptedContent=require("../encrypted-content.js").EncryptedContent,SyncPromise=require("../../util/sync-promise.js").SyncPromise,Encryptor=function(a){};exports.Encryptor=Encryptor;Encryptor.NAME_COMPONENT_FOR=new Name.Component("FOR");Encryptor.NAME_COMPONENT_READ=new Name.Component("READ");Encryptor.NAME_COMPONENT_SAMPLE=new Name.Component("SAMPLE");Encryptor.NAME_COMPONENT_ACCESS=new Name.Component("ACCESS");Encryptor.NAME_COMPONENT_E_KEY=new Name.Component("E-KEY");
+Encryptor.NAME_COMPONENT_D_KEY=new Name.Component("D-KEY");Encryptor.NAME_COMPONENT_C_KEY=new Name.Component("C-KEY");
+Encryptor.encryptDataPromise=function(a,b,c,d,e,f){a.getName().append(Encryptor.NAME_COMPONENT_FOR).append(c);var g=e.getAlgorithmType();return g==EncryptAlgorithmType.AesCbc||g==EncryptAlgorithmType.AesEcb?Encryptor.encryptSymmetricPromise_(b,d,c,e,f).then(function(b){a.setContent(b.wireEncode(TlvWireFormat.get()));return SyncPromise.resolve()}):g==EncryptAlgorithmType.RsaPkcs||g==EncryptAlgorithmType.RsaOaep?Encryptor.encryptAsymmetricPromise_(b,d,c,e,f).then(function(b){a.setContent(b.wireEncode(TlvWireFormat.get()));
+return SyncPromise.resolve()},function(g){if(0>g.message.indexOf("data too large for key size"))throw g;g=Crypto.randomBytes(16);var k=new Blob(g,!1);g=new Name(c);g.append("nonce");var l=new EncryptParams(EncryptAlgorithmType.AesCbc,AesAlgorithm.BLOCK_SIZE),m;return Encryptor.encryptSymmetricPromise_(b,k,g,l,f).then(function(a){m=a;return Encryptor.encryptAsymmetricPromise_(k,d,c,e,f)}).then(function(b){var c=m.wireEncode();b=b.wireEncode();var d=new Buffer(c.size()+b.size());b.buf().copy(d,0);c.buf().copy(d,
+b.size());a.setContent(new Blob(d,!1));return SyncPromise.resolve()})}):SyncPromise.reject(Error("Unsupported encryption method"))};Encryptor.encryptData=function(a,b,c,d,e){return SyncPromise.getValue(Encryptor.encryptDataPromise(a,b,c,d,e,!0))};
+Encryptor.encryptSymmetricPromise_=function(a,b,c,d,e){var f=d.getAlgorithmType(),g=d.getInitialVector(),h=new KeyLocator;h.setType(KeyLocatorType.KEYNAME);h.setKeyName(c);return f==EncryptAlgorithmType.AesCbc||f==EncryptAlgorithmType.AesEcb?f==EncryptAlgorithmType.AesCbc&&g.size()!=AesAlgorithm.BLOCK_SIZE?SyncPromise.reject(Error("incorrect initial vector size")):AesAlgorithm.encryptPromise(b,a,d,e).then(function(a){var b=new EncryptedContent;b.setAlgorithmType(f);b.setKeyLocator(h);b.setPayload(a);
+b.setInitialVector(g);return SyncPromise.resolve(b)}):SyncPromise.reject(Error("Unsupported encryption method"))};
+Encryptor.encryptAsymmetricPromise_=function(a,b,c,d,e){var f=d.getAlgorithmType(),g=new KeyLocator;g.setType(KeyLocatorType.KEYNAME);g.setKeyName(c);return f==EncryptAlgorithmType.RsaPkcs||f==EncryptAlgorithmType.RsaOaep?RsaAlgorithm.encryptPromise(b,a,d,e).then(function(a){var b=new EncryptedContent;b.setAlgorithmType(f);b.setKeyLocator(g);b.setPayload(a);return SyncPromise.resolve(b)}):SyncPromise.reject(Error("Unsupported encryption method"))};
+var constants=require("constants"),Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,DecryptKey=require("../decrypt-key.js").DecryptKey,EncryptKey=require("../encrypt-key.js").EncryptKey,EncryptAlgorithmType=require("./encrypt-params.js").EncryptAlgorithmType,DerNode=require("../../encoding/der/der-node.js").DerNode,OID=require("../../encoding/oid.js").OID,PrivateKeyStorage=require("../../security/identity/private-key-storage.js").PrivateKeyStorage,UseSubtleCrypto=require("../../use-subtle-crypto-node.js").UseSubtleCrypto,
+SyncPromise=require("../../util/sync-promise.js").SyncPromise,rsaKeygen=null;try{rsaKeygen=require("rsa-keygen")}catch(e$$48){}RsaAlgorithm=function(){};exports.RsaAlgorithm=RsaAlgorithm;
+RsaAlgorithm.generateKeyPromise=function(a,b){if(UseSubtleCrypto()&&!b)return crypto.subtle.generateKey({name:"RSASSA-PKCS1-v1_5",modulusLength:a.getKeySize(),publicExponent:new Uint8Array([1,0,1]),hash:{name:"SHA-256"}},!0,["sign","verify"]).then(function(a){return crypto.subtle.exportKey("pkcs8",a.privateKey)}).then(function(a){return Promise.resolve(new DecryptKey(new Blob(new Uint8Array(a),!1)))});if(!rsaKeygen)return SyncPromise.reject(Error("Need to install rsa-keygen: sudo npm install rsa-keygen"));
+try{var c=rsaKeygen.generate(a.getKeySize()).private_key.toString().replace("-----BEGIN RSA PRIVATE KEY-----","").replace("-----END RSA PRIVATE KEY-----",""),d=new Buffer(c,"base64"),e=PrivateKeyStorage.encodePkcs8PrivateKey(d,new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),new DerNode.DerNull).buf();return SyncPromise.resolve(new DecryptKey(e))}catch(f){return SyncPromise.reject(f)}};RsaAlgorithm.generateKey=function(a){return SyncPromise.getValue(this.generateKeyPromise(a,!0))};
+RsaAlgorithm.deriveEncryptKey=function(a){a=RsaAlgorithm.getRsaPrivateKeyDer(a);var b=DerNode.parse(a.buf(),0).getChildren();a=b[1];var b=b[2],c=new DerNode.DerSequence;c.addChild(a);c.addChild(b);a=c.encode();b=new DerNode.DerSequence;b.addChild(new DerNode.DerOid(new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID)));b.addChild(new DerNode.DerNull);c=new DerNode.DerSequence;c.addChild(b);c.addChild(new DerNode.DerBitString(a.buf(),0));return new EncryptKey(c.encode())};
+RsaAlgorithm.decryptPromise=function(a,b,c,d){if(UseSubtleCrypto()&&!d&&c.getAlgorithmType()!=EncryptAlgorithmType.RsaPkcs)return c.getAlgorithmType()==EncryptAlgorithmType.RsaOaep?crypto.subtle.importKey("pkcs8",a.buf(),{name:"RSA-OAEP",hash:{name:"SHA-1"}},!1,["decrypt"]).then(function(a){return crypto.subtle.decrypt({name:"RSA-OAEP"},a,b.buf())}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!1))}):Promise.reject(Error("unsupported padding scheme"));d=RsaAlgorithm.getRsaPrivateKeyDer(a).buf().toString("base64");
+a="-----BEGIN RSA PRIVATE KEY-----\n";for(var e=0;e<d.length;e+=64)a+=d.substr(e,64)+"\n";a+="-----END RSA PRIVATE KEY-----";if(c.getAlgorithmType()==EncryptAlgorithmType.RsaPkcs)c=constants.RSA_PKCS1_PADDING;else if(c.getAlgorithmType()==EncryptAlgorithmType.RsaOaep)c=constants.RSA_PKCS1_OAEP_PADDING;else return SyncPromise.reject(Error("unsupported padding scheme"));try{return SyncPromise.resolve(new Blob(Crypto.privateDecrypt({key:a,padding:c},b.buf()),!1))}catch(f){return SyncPromise.reject(f)}};
+RsaAlgorithm.decrypt=function(a,b,c){return SyncPromise.getValue(this.decryptPromise(a,b,c,!0))};
+RsaAlgorithm.encryptPromise=function(a,b,c,d){if(UseSubtleCrypto()&&!d&&c.getAlgorithmType()!=EncryptAlgorithmType.RsaPkcs)return c.getAlgorithmType()==EncryptAlgorithmType.RsaOaep?crypto.subtle.importKey("spki",a.buf(),{name:"RSA-OAEP",hash:{name:"SHA-1"}},!1,["encrypt"]).then(function(a){return crypto.subtle.encrypt({name:"RSA-OAEP"},a,b.buf())}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!1))}):Promise.reject(Error("unsupported padding scheme"));d=a.buf().toString("base64");
+a="-----BEGIN PUBLIC KEY-----\n";for(var e=0;e<d.length;e+=64)a+=d.substr(e,64)+"\n";a+="-----END PUBLIC KEY-----";if(c.getAlgorithmType()==EncryptAlgorithmType.RsaPkcs)c=constants.RSA_PKCS1_PADDING;else if(c.getAlgorithmType()==EncryptAlgorithmType.RsaOaep)c=constants.RSA_PKCS1_OAEP_PADDING;else return SyncPromise.reject(Error("unsupported padding scheme"));try{return SyncPromise.resolve(new Blob(Crypto.publicEncrypt({key:a,padding:c},b.buf()),!1))}catch(f){return SyncPromise.reject(f)}};
+RsaAlgorithm.encrypt=function(a,b,c){return SyncPromise.getValue(this.encryptPromise(a,b,c,!0))};RsaAlgorithm.getRsaPrivateKeyDer=function(a){a=DerNode.parse(a.buf(),0).getChildren();if(DerNode.getSequence(a,1).getChildren()[0].toVal()!=PrivateKeyStorage.RSA_ENCRYPTION_OID)throw Error("The PKCS #8 private key is not RSA_ENCRYPTION");return a[2].getPayload()};var SyncPromise=require("../util/sync-promise.js").SyncPromise,ConsumerDb=function(){};exports.ConsumerDb=ConsumerDb;
+ConsumerDb.Error=function(a){if(a)return a.__proto__=ConsumerDb.Error.prototype,a};ConsumerDb.Error.prototype=Error();ConsumerDb.Error.prototype.name="ConsumerDbError";ConsumerDb.prototype.getKeyPromise=function(a,b){return SyncPromise.reject(Error("ConsumerDb.getKeyPromise is not implemented"))};ConsumerDb.prototype.addKeyPromise=function(a,b,c){return SyncPromise.reject(Error("ConsumerDb.addKeyPromise is not implemented"))};ConsumerDb.prototype.deleteKeyPromise=function(a,b){return SyncPromise.reject(Error("ConsumerDb.addKeyPromise is not implemented"))};
+var Blob=require("../util/blob.js").Blob,Name=require("../name.js").Name,Interest=require("../interest.js").Interest,NetworkNack=require("../network-nack.js").NetworkNack,Link=require("../link.js").Link,EncryptedContent=require("./encrypted-content.js").EncryptedContent,EncryptError=require("./encrypt-error.js").EncryptError,EncryptParams=require("./algo/encrypt-params.js").EncryptParams,EncryptAlgorithmType=require("./algo/encrypt-params.js").EncryptAlgorithmType,RsaAlgorithm=require("./algo/rsa-algorithm.js").RsaAlgorithm,
+AesAlgorithm=require("./algo/aes-algorithm.js").AesAlgorithm,Encryptor=require("./algo/encryptor.js").Encryptor,SyncPromise=require("../util/sync-promise.js").SyncPromise,NdnCommon=require("../util/ndn-common.js").NdnCommon,Consumer=function Consumer(b,c,d,e,f,g,h){this.database_=f;this.keyChain_=c;this.face_=b;this.groupName_=new Name(d);this.consumerName_=new Name(e);this.cKeyLink_=void 0==g?Consumer.NO_LINK:new Link(g);this.dKeyLink_=void 0==h?Consumer.NO_LINK:new Link(h);this.cKeyMap_={};this.dKeyMap_=
+{}};exports.Consumer=Consumer;Consumer.prototype.consume=function(a,b,c,d){void 0==d&&(d=Consumer.NO_LINK);a=new Interest(a);var e=this;this.sendInterest_(a,1,new Link(d),function(a){e.decryptContent_(a,function(c){try{b(a,c)}catch(d){console.log("Error in onConsumeComplete: "+NdnCommon.getErrorWithStackTrace(d))}},c)},c)};Consumer.prototype.setGroup=function(a){this.groupName_=new Name(a)};
+Consumer.prototype.addDecryptionKeyPromise=function(a,b,c){return this.consumerName_.match(a)?this.database_.addKeyPromise(a,b,c):SyncPromise.reject(Error("addDecryptionKey: The consumer name must be a prefix of the key name"))};Consumer.prototype.addDecryptionKey=function(a,b,c,d){return SyncPromise.complete(c,d,this.addDecryptionKeyPromise(a,b,!c))};Consumer.Error=function(a,b){this.errorCode=a;this.message=b};
+Consumer.Error.callOnError=function(a,b,c){c||(c="");if(b instanceof Consumer.Error)try{a(b.errorCode,b.message)}catch(d){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(d))}else try{a(EncryptError.ErrorCode.General,c+b)}catch(e){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(e))}};
+Consumer.decryptPromise_=function(a,b){return SyncPromise.resolve().then(function(){if("object"==typeof a&&a instanceof Blob){var c=a;a=new EncryptedContent;a.wireDecode(c)}c=a.getPayload();if(a.getAlgorithmType()==EncryptAlgorithmType.AesCbc){var d=new EncryptParams(EncryptAlgorithmType.AesCbc);d.setInitialVector(a.getInitialVector());return AesAlgorithm.decryptPromise(b,c,d)}return a.getAlgorithmType()==EncryptAlgorithmType.RsaOaep?(d=new EncryptParams(EncryptAlgorithmType.RsaOaep),RsaAlgorithm.decryptPromise(b,
+c,d)):SyncPromise.reject(new Consumer.Error(EncryptError.ErrorCode.UnsupportedEncryptionScheme,""+a.getAlgorithmType()))})};Consumer.decrypt_=function(a,b,c,d){Consumer.decryptPromise_(a,b).then(function(a){c(a)},function(a){Consumer.Error.callOnError(d,a)})};
+Consumer.prototype.decryptContent_=function(a,b,c){var d=new EncryptedContent;try{d.wireDecode(a.getContent())}catch(e){Consumer.Error.callOnError(c,e,"Error decoding EncryptedContent: ");return}var f=d.getKeyLocator().getKeyName();if(a=this.cKeyMap_[f.toUri()])this.decrypt_(d,a,b,c);else{a=new Name(f);a.append(Encryptor.NAME_COMPONENT_FOR).append(this.groupName_);a=new Interest(a);var g=this;this.sendInterest_(a,1,this.cKeyLink_,function(a){g.decryptCKey_(a,function(a){g.cKeyMap_[f.toUri()]=a;Consumer.decrypt_(d,
+a,b,c)},c)},c)}};
+Consumer.prototype.decryptCKey_=function(a,b,c){a=a.getContent();var d=new EncryptedContent;try{d.wireDecode(a)}catch(e){Consumer.Error.callOnError(c,e,"Error decoding EncryptedContent: ");return}a=d.getKeyLocator().getKeyName();var f=a.getPrefix(-3);f.append(Encryptor.NAME_COMPONENT_D_KEY).append(a.getSubName(-2));if(a=this.dKeyMap_[f.toUri()])this.decrypt_(d,a,b,c);else{a=new Name(f);a.append(Encryptor.NAME_COMPONENT_FOR).append(this.consumerName_);a=new Interest(a);var g=this;this.sendInterest_(a,
+1,this.dKeyLink_,function(a){g.decryptDKeyPromise_(a).then(function(a){g.dKeyMap_[f.toUri()]=a;Consumer.decrypt_(d,a,b,c)},function(a){Consumer.Error.callOnError(c,a,"decryptDKey error: ")})},c)}};
+Consumer.prototype.decryptDKeyPromise_=function(a){var b,c,d,e=this;return SyncPromise.resolve().then(function(){b=a.getContent();c=new EncryptedContent;c.wireDecode(b);var d=c.getKeyLocator().getKeyName();return e.getDecryptionKeyPromise_(d)}).then(function(a){if(0==a.size())return SyncPromise.reject(new Consumer.Error(EncryptError.ErrorCode.NoDecryptKey,"The desired consumer decryption key in not in the database"));var e=b.buf().slice(c.wireEncode().size());d=new Blob(e,!1);return 0==d.size()?SyncPromise.reject(new Consumer.Error(EncryptError.ErrorCode.InvalidEncryptedFormat,
+"The data packet does not satisfy the D-KEY packet format")):Consumer.decryptPromise_(c,a)}).then(function(a){return Consumer.decryptPromise_(d,a)})};
+Consumer.prototype.sendInterest_=function(a,b,c,d,e){function f(a,b){try{e(EncryptError.ErrorCode.DataRetrievalFailure,a.getName().toUri())}catch(c){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(c))}}var g=this,h=function(a,b){try{g.keyChain_.verifyData(b,d,function(a,b){try{e(EncryptError.ErrorCode.Validation,"verifyData failed. Reason: "+b)}catch(c){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(c))}})}catch(c){Consumer.Error.callOnError(e,c,"verifyData error: ")}},
+k=function(a){0<b?g.sendInterest_(a,b-1,c,d,e):f(a,new NetworkNack)};0!==c.getDelegations().size()&&(a=new Interest(a),a.setLinkWireEncoding(c.wireEncode()));try{this.face_.expressInterest(a,h,k,f)}catch(l){Consumer.Error.callOnError(e,l,"expressInterest error: ")}};Consumer.prototype.getDecryptionKeyPromise_=function(a){return this.database_.getKeyPromise(a)};Consumer.NO_LINK=new Link;Blob=require("../util/blob.js").Blob;
+DecryptKey=function DecryptKey(b){this.keyBits_="object"===typeof b&&b instanceof DecryptKey?b.keyBits_:"object"===typeof b&&b instanceof Blob?b:new Blob(b)};exports.DecryptKey=DecryptKey;DecryptKey.prototype.getKeyBits=function(){return this.keyBits_};EncryptError=function(){};exports.EncryptError=EncryptError;EncryptError.ErrorCode={Timeout:1,Validation:2,UnsupportedEncryptionScheme:32,InvalidEncryptedFormat:33,NoDecryptKey:34,EncryptionFailure:35,DataRetrievalFailure:36,General:100};Blob=require("../util/blob.js").Blob;
+EncryptKey=function EncryptKey(b){this.keyBits_="object"===typeof b&&b instanceof EncryptKey?b.keyBits_:"object"===typeof b&&b instanceof Blob?b:new Blob(b)};exports.EncryptKey=EncryptKey;EncryptKey.prototype.getKeyBits=function(){return this.keyBits_};KeyLocator=require("../key-locator.js").KeyLocator;WireFormat=require("../encoding/wire-format.js").WireFormat;Blob=require("../util/blob.js").Blob;
+EncryptedContent=function EncryptedContent(b){"object"===typeof b&&b instanceof EncryptedContent?(this.algorithmType_=b.algorithmType_,this.keyLocator_=new KeyLocator(b.keyLocator_),this.initialVector_=b.initialVector_,this.payload_=b.payload_):(this.algorithmType_=null,this.keyLocator_=new KeyLocator,this.initialVector_=new Blob,this.payload_=new Blob)};exports.EncryptedContent=EncryptedContent;EncryptedContent.prototype.getAlgorithmType=function(){return this.algorithmType_};
+EncryptedContent.prototype.getKeyLocator=function(){return this.keyLocator_};EncryptedContent.prototype.getInitialVector=function(){return this.initialVector_};EncryptedContent.prototype.getPayload=function(){return this.payload_};EncryptedContent.prototype.setAlgorithmType=function(a){this.algorithmType_=a;return this};EncryptedContent.prototype.setKeyLocator=function(a){this.keyLocator_="object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator;return this};
+EncryptedContent.prototype.setInitialVector=function(a){this.initialVector_="object"===typeof a&&a instanceof Blob?a:new Blob(a);return this};EncryptedContent.prototype.setPayload=function(a){this.payload_="object"===typeof a&&a instanceof Blob?a:new Blob(a);return this};EncryptedContent.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeEncryptedContent(this)};
+EncryptedContent.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeEncryptedContent(this,a.buf(),!1):b.decodeEncryptedContent(this,a,!0)};var SyncPromise=require("../util/sync-promise.js").SyncPromise,GroupManagerDb=function(){};exports.GroupManagerDb=GroupManagerDb;GroupManagerDb.Error=function(a){if(a)return a.__proto__=GroupManagerDb.Error.prototype,a};GroupManagerDb.Error.prototype=Error();
+GroupManagerDb.Error.prototype.name="GroupManagerDbError";GroupManagerDb.prototype.hasSchedulePromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.hasSchedulePromise is not implemented"))};GroupManagerDb.prototype.listAllScheduleNamesPromise=function(a){return SyncPromise.reject(Error("GroupManagerDb.listAllScheduleNamesPromise is not implemented"))};GroupManagerDb.prototype.getSchedulePromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.getSchedulePromise is not implemented"))};
+GroupManagerDb.prototype.getScheduleMembersPromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.getScheduleMembersPromise is not implemented"))};GroupManagerDb.prototype.addSchedulePromise=function(a,b,c){return SyncPromise.reject(Error("GroupManagerDb.addSchedulePromise is not implemented"))};GroupManagerDb.prototype.deleteSchedulePromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.deleteSchedulePromise is not implemented"))};
+GroupManagerDb.prototype.renameSchedulePromise=function(a,b,c){return SyncPromise.reject(Error("GroupManagerDb.renameSchedulePromise is not implemented"))};GroupManagerDb.prototype.updateSchedulePromise=function(a,b,c){return SyncPromise.reject(Error("GroupManagerDb.updateSchedulePromise is not implemented"))};GroupManagerDb.prototype.hasMemberPromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.hasMemberPromise is not implemented"))};
+GroupManagerDb.prototype.listAllMembersPromise=function(a){return SyncPromise.reject(Error("GroupManagerDb.listAllMembersPromise is not implemented"))};GroupManagerDb.prototype.getMemberSchedulePromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.getMemberSchedulePromise is not implemented"))};GroupManagerDb.prototype.addMemberPromise=function(a,b,c,d){return SyncPromise.reject(Error("GroupManagerDb.addMemberPromise is not implemented"))};
+GroupManagerDb.prototype.updateMemberSchedulePromise=function(a,b,c){return SyncPromise.reject(Error("GroupManagerDb.updateMemberSchedulePromise is not implemented"))};GroupManagerDb.prototype.deleteMemberPromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.deleteMemberPromise is not implemented"))};
+var Name=require("../name.js").Name,Data=require("../data.js").Data,SyncPromise=require("../util/sync-promise.js").SyncPromise,IdentityCertificate=require("../security/certificate/identity-certificate.js").IdentityCertificate,SecurityException=require("../security/security-exception.js").SecurityException,RsaKeyParams=require("../security/key-params.js").RsaKeyParams,EncryptParams=require("./algo/encrypt-params.js").EncryptParams,EncryptAlgorithmType=require("./algo/encrypt-params.js").EncryptAlgorithmType,
+Encryptor=require("./algo/encryptor.js").Encryptor,RsaAlgorithm=require("./algo/rsa-algorithm.js").RsaAlgorithm,Interval=require("./interval.js").Interval,Schedule=require("./schedule.js").Schedule,GroupManager=function(a,b,c,d,e,f){this.namespace_=(new Name(a)).append(Encryptor.NAME_COMPONENT_READ).append(b);this.database_=c;this.keySize_=d;this.freshnessHours_=e;this.keyChain_=f};exports.GroupManager=GroupManager;
+GroupManager.prototype.getGroupKeyPromise=function(a,b){var c=[],d=[],e=this,f,g,h,k;return this.calculateIntervalPromise_(a,c,b).then(function(a){if(!1==a.isValid())return SyncPromise.resolve(d);h=Schedule.toIsoString(a.getStartTime());k=Schedule.toIsoString(a.getEndTime());return e.generateKeyPairPromise_(b).then(function(a){f=a.privateKeyBlob;g=a.publicKeyBlob;return e.createEKeyDataPromise_(h,k,g,b)}).then(function(a){function g(a){return a>=c.length?SyncPromise.resolve():e.createDKeyDataPromise_(h,
+k,c[a].keyName,f,c[a].publicKey,b).then(function(b){d.push(b);return g(a+1)})}d.push(a);return g(0)}).then(function(){return SyncPromise.resolve(d)})})};GroupManager.prototype.addSchedulePromise=function(a,b,c){return this.database_.addSchedulePromise(a,b,c)};GroupManager.prototype.deleteSchedulePromise=function(a,b){return this.database_.deleteSchedulePromise(a,b)};GroupManager.prototype.updateSchedulePromise=function(a,b,c){return this.database_.updateSchedulePromise(b,schedule,c)};
+GroupManager.prototype.addMemberPromise=function(a,b,c){b=new IdentityCertificate(b);return this.database_.addMemberPromise(a,b.getPublicKeyName(),b.getPublicKeyInfo().getKeyDer(),c)};GroupManager.prototype.removeMemberPromise=function(a,b){return this.database_.deleteMemberPromise(a,b)};GroupManager.prototype.updateMemberSchedulePromise=function(a,b,c){return this.database_.updateMemberSchedulePromise(a,b,c)};
+GroupManager.prototype.calculateIntervalPromise_=function(a,b,c){var d=new Interval,e=new Interval;b.splice(0,b.length);var f=this;return this.database_.listAllScheduleNamesPromise(c).then(function(g){function h(k){if(k>=g.length)return SyncPromise.resolve();var l=g[k];return f.database_.getSchedulePromise(l,c).then(function(g){g=g.getCoveringInterval(a);var q=g.interval;if(g.isPositive)return d.isValid()||(d=q),d.intersectWith(q),f.database_.getScheduleMembersPromise(l,c).then(function(a){for(var c=
+0;c<a.length;++c)GroupManager.memberKeysAdd_(b,a[c]);return h(k+1)});e.isValid()||(e=q);e.intersectWith(q);return h(k+1)})}return h(0)}).then(function(){if(!d.isValid())return SyncPromise.resolve(new Interval(!1));var a;a=e.isValid()?d.intersectWith(e):d;return SyncPromise.resolve(a)})};GroupManager.memberKeysAdd_=function(a,b){for(var c=0;c<a.length;){var d=a[c].keyName.compare(b.keyName);if(0==d)return;if(0<d)break;c+=1}a.splice(c,0,b)};
+GroupManager.prototype.generateKeyPairPromise_=function(a){a=new RsaKeyParams(this.keySize_);return RsaAlgorithm.generateKeyPromise(a).then(function(a){a=a.getKeyBits();var c=RsaAlgorithm.deriveEncryptKey(a).getKeyBits();return SyncPromise.resolve({privateKeyBlob:a,publicKeyBlob:c})})};
+GroupManager.prototype.createEKeyDataPromise_=function(a,b,c,d){d=new Name(this.namespace_);d.append(Encryptor.NAME_COMPONENT_E_KEY).append(a).append(b);a=new Data(d);a.getMetaInfo().setFreshnessPeriod(this.freshnessHours_*GroupManager.MILLISECONDS_IN_HOUR);a.setContent(c);return this.keyChain_.signPromise(a)};
+GroupManager.prototype.createDKeyDataPromise_=function(a,b,c,d,e,f){var g=new Name(this.namespace_);g.append(Encryptor.NAME_COMPONENT_D_KEY);g.append(a).append(b);var h=new Data(g);h.getMetaInfo().setFreshnessPeriod(this.freshnessHours_*GroupManager.MILLISECONDS_IN_HOUR);a=new EncryptParams(EncryptAlgorithmType.RsaOaep);var k=this;return Encryptor.encryptDataPromise(h,d,c,e,a,f)["catch"](function(a){return SyncPromise.reject(SecurityException(Error("createDKeyData: Error in encryptData: "+a)))}).then(function(){return k.keyChain_.signPromise(h)})};
+GroupManager.MILLISECONDS_IN_HOUR=36E5;Interval=function Interval(b,c){if("object"===typeof b&&b instanceof Interval)this.startTime_=b.startTime_,this.endTime_=b.endTime_,this.isValid_=b.isValid_;else if("number"===typeof b){if(!(b<c))throw Error("Interval start time must be less than the end time");this.startTime_=b;this.endTime_=c;this.isValid_=!0}else this.startTime_=-Number.MAX_VALUE,this.endTime_=-Number.MAX_VALUE,this.isValid_=b?!0:!1};exports.Interval=Interval;
+Interval.prototype.set=function(a){this.startTime_=a.startTime_;this.endTime_=a.endTime_;this.isValid_=a.isValid_};Interval.prototype.covers=function(a){if(!this.isValid_)throw Error("Interval.covers: This Interval is invalid");return this.isEmpty()?!1:this.startTime_<=a&&a<this.endTime_};
+Interval.prototype.intersectWith=function(a){if(!this.isValid_)throw Error("Interval.intersectWith: This Interval is invalid");if(!a.isValid_)throw Error("Interval.intersectWith: The other Interval is invalid");if(this.isEmpty()||a.isEmpty()||this.startTime_>=a.endTime_||this.endTime_<=a.startTime_)return this.startTime_=this.endTime_,this;this.startTime_<=a.startTime_&&(this.startTime_=a.startTime_);this.endTime_>a.endTime_&&(this.endTime_=a.endTime_);return this};
+Interval.prototype.unionWith=function(a){if(!this.isValid_)throw Error("Interval.intersectWith: This Interval is invalid");if(!a.isValid_)throw Error("Interval.intersectWith: The other Interval is invalid");if(this.isEmpty())return this.startTime_=a.startTime_,this.endTime_=a.endTime_,this;if(a.isEmpty())return this;if(this.startTime_>=a.endTime_||this.endTime_<=a.startTime_)throw Error("Interval.unionWith: The two intervals do not have an intersection");this.startTime_>a.startTime_&&(this.startTime_=
+a.startTime_);this.endTime_<a.endTime_&&(this.endTime_=a.endTime_);return this};Interval.prototype.getStartTime=function(){if(!this.isValid_)throw Error("Interval.getStartTime: This Interval is invalid");return this.startTime_};Interval.prototype.getEndTime=function(){if(!this.isValid_)throw Error("Interval.getEndTime: This Interval is invalid");return this.endTime_};Interval.prototype.isValid=function(){return this.isValid_};
+Interval.prototype.isEmpty=function(){if(!this.isValid_)throw Error("Interval.isEmpty: This Interval is invalid");return this.startTime_==this.endTime_};var SyncPromise=require("../util/sync-promise.js").SyncPromise,ProducerDb=function(){};exports.ProducerDb=ProducerDb;ProducerDb.Error=function(a){if(a)return a.__proto__=ProducerDb.Error.prototype,a};ProducerDb.Error.prototype=Error();ProducerDb.Error.prototype.name="ProducerDbError";ProducerDb.prototype.hasContentKeyPromise=function(a,b){return SyncPromise.reject(Error("ProducerDb.hasContentKeyPromise is not implemented"))};
+ProducerDb.prototype.getContentKeyPromise=function(a,b){return SyncPromise.reject(Error("ProducerDb.getContentKeyPromise is not implemented"))};ProducerDb.prototype.addContentKeyPromise=function(a,b,c){return SyncPromise.reject(Error("ProducerDb.addContentKeyPromise is not implemented"))};ProducerDb.prototype.deleteContentKeyPromise=function(a,b){return SyncPromise.reject(Error("ProducerDb.deleteContentKeyPromise is not implemented"))};
+ProducerDb.getFixedTimeSlot=function(a){return Math.floor(Math.round(a)/36E5)};
+var Name=require("../name.js").Name,Interest=require("../interest.js").Interest,Data=require("../data.js").Data,Link=require("../link.js").Link,NetworkNack=require("../network-nack.js").NetworkNack,Exclude=require("../exclude.js").Exclude,Encryptor=require("./algo/encryptor.js").Encryptor,EncryptParams=require("./algo/encrypt-params.js").EncryptParams,EncryptAlgorithmType=require("./algo/encrypt-params.js").EncryptAlgorithmType,AesKeyParams=require("../security/key-params.js").AesKeyParams,AesAlgorithm=
+require("./algo/aes-algorithm.js").AesAlgorithm,Schedule=require("./schedule.js").Schedule,EncryptError=require("./encrypt-error.js").EncryptError,NdnCommon=require("../util/ndn-common.js").NdnCommon,SyncPromise=require("../util/sync-promise.js").SyncPromise,Producer=function Producer(b,c,d,e,f,g,h){this.face_=d;this.keyChain_=e;this.database_=f;this.maxRepeatAttempts_=void 0==g?3:g;this.keyRetrievalLink_=void 0==h?Producer.NO_LINK:new Link(h);this.eKeyInfo_={};this.keyRequests_={};d=new Name(b);
+e=new Name(c);for(d.append(Encryptor.NAME_COMPONENT_READ);0<e.size();)f=new Name(d),f.append(e),f.append(Encryptor.NAME_COMPONENT_E_KEY),this.eKeyInfo_[f.toUri()]={keyName:f,keyInfo:new Producer.KeyInfo_},e=e.getPrefix(-1);d.append(c);this.namespace_=new Name(b);this.namespace_.append(Encryptor.NAME_COMPONENT_SAMPLE);this.namespace_.append(c)};exports.Producer=Producer;
+Producer.prototype.createContentKey=function(a,b,c,d){d||(d=Producer.defaultOnError);var e=Producer.getRoundedTimeSlot_(a),f=new Name(this.namespace_);f.append(Encryptor.NAME_COMPONENT_C_KEY);f.append(Schedule.toIsoString(e));var g,h=this;this.database_.hasContentKeyPromise(a).then(function(e){e?null!=c&&c(f):(e=new AesKeyParams(128),g=AesAlgorithm.generateKey(e).getKeyBits(),h.database_.addContentKeyPromise(a,g).then(function(){var e=Math.round(a);h.keyRequests_[e]=new Producer.KeyRequest_(h.getEKeyInfoSize_());
+var e=h.keyRequests_[e],g=new Exclude;Producer.excludeAfter(g,new Name.Component(Schedule.toIsoString(a)));for(var k in h.eKeyInfo_){var p=h.eKeyInfo_[k],s=p.keyInfo;a<s.beginTimeSlot||a>=s.endTimeSlot?(e.repeatAttempts[k]=0,h.sendKeyInterest_((new Interest(p.keyName)).setExclude(g).setChildSelector(1),a,b,d)):(p=new Name(p.keyName),p.append(Schedule.toIsoString(s.beginTimeSlot)),p.append(Schedule.toIsoString(s.endTimeSlot)),h.encryptContentKeyPromise_(s.keyBits,p,a,b,d))}null!=c&&c(f)}))})};
+Producer.prototype.produce=function(a,b,c,d,e){e||(e=Producer.defaultOnError);var f=this;this.createContentKey(b,null,function(g){f.database_.getContentKeyPromise(b).then(function(d){var e=new Name(f.namespace_);e.append(Schedule.toIsoString(b));a.setName(e);e=new EncryptParams(EncryptAlgorithmType.AesCbc,16);return Encryptor.encryptData(a,c,g,d,e)}).then(function(){return f.keyChain_.signPromise(a)}).then(function(){try{d()}catch(a){console.log("Error in onComplete: "+NdnCommon.getErrorWithStackTrace(a))}},
+function(a){try{e(EncryptError.ErrorCode.General,""+a)}catch(b){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(b))}})},e)};Producer.defaultOnError=function(a,b){};Producer.KeyInfo_=function(){this.endTimeSlot=this.beginTimeSlot=0;this.keyBits=null};Producer.KeyRequest_=function(a){this.interestCount=a;this.repeatAttempts={};this.encryptedKeys=[]};Producer.getRoundedTimeSlot_=function(a){return Math.round(36E5*Math.floor(Math.round(a)/36E5))};
+Producer.prototype.sendKeyInterest_=function(a,b,c,d){var e=this;0!==this.keyRetrievalLink_.getDelegations().size()&&(a=new Interest(a),a.setLinkWireEncoding(this.keyRetrievalLink_.wireEncode()));this.face_.expressInterest(a,function(a,g){e.handleCoveringKey_(a,g,b,c,d)},function(a){e.handleTimeout_(a,b,c,d)},function(a,g){e.handleNetworkNack_(a,g,b,c,d)})};
+Producer.prototype.handleTimeout_=function(a,b,c,d){var e=Math.round(b),e=this.keyRequests_[e],f=a.getName().toUri();e.repeatAttempts[f]<this.maxRepeatAttempts_?(++e.repeatAttempts[f],this.sendKeyInterest_(a,b,c,d)):this.handleNetworkNack_(a,new NetworkNack,b,c,d)};Producer.prototype.handleNetworkNack_=function(a,b,c,d,e){a=Math.round(c);this.updateKeyRequest_(this.keyRequests_[a],a,d)};
+Producer.prototype.updateKeyRequest_=function(a,b,c){--a.interestCount;if(0==a.interestCount&&null!=c){try{c(a.encryptedKeys)}catch(d){console.log("Error in onEncryptedKeys: "+NdnCommon.getErrorWithStackTrace(d))}delete this.keyRequests_[b]}};
+Producer.prototype.handleCoveringKey_=function(a,b,c,d,e){var f=Math.round(c),f=this.keyRequests_[f],g=a.getName(),h=g.toUri(),k=b.getName(),l=Schedule.fromIsoString(k.get(Producer.START_TIME_STAMP_INDEX).getValue().toString()),m=Schedule.fromIsoString(k.get(Producer.END_TIME_STAMP_INDEX).getValue().toString());if(c>=m)a=new Exclude(a.getExclude()),Producer.excludeBefore(a,k.get(Producer.START_TIME_STAMP_INDEX)),f.repeatAttempts[h]=0,this.sendKeyInterest_((new Interest(g)).setExclude(a).setChildSelector(1),
+c,d,e);else{var q=b.getContent(),p=this;this.encryptContentKeyPromise_(q,k,c,d,e).then(function(a){a&&(a=p.eKeyInfo_[h].keyInfo,a.beginTimeSlot=l,a.endTimeSlot=m,a.keyBits=q)})}};
+Producer.prototype.encryptContentKeyPromise_=function(a,b,c,d,e){var f=Math.round(c),g=this.keyRequests_[f],h=new Name(this.namespace_);h.append(Encryptor.NAME_COMPONENT_C_KEY);h.append(Schedule.toIsoString(Producer.getRoundedTimeSlot_(c)));var k,l=this;return this.database_.getContentKeyPromise(c).then(function(c){k=new Data;k.setName(h);var d=new EncryptParams(EncryptAlgorithmType.RsaOaep);return Encryptor.encryptDataPromise(k,c,b,a,d)}).then(function(){return SyncPromise.resolve(!0)},function(a){try{e(EncryptError.ErrorCode.EncryptionFailure,
+"encryptData failed: "+a)}catch(b){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(b))}return SyncPromise.resolve(!1)}).then(function(a){return a?l.keyChain_.signPromise(k).then(function(){g.encryptedKeys.push(k);l.updateKeyRequest_(g,f,d);return SyncPromise.resolve(!0)}):SyncPromise.resolve(!1)})};Producer.prototype.getEKeyInfoSize_=function(){var a=0;for(key in this.eKeyInfo_)this.eKeyInfo_.hasOwnProperty(key)&&++a;return a};
+Producer.ExcludeEntry=function(a,b){this.component_=a;this.anyFollowsComponent_=b};Producer.getExcludeEntries=function(a){for(var b=[],c=0;c<a.size();++c)a.get(c)==Exclude.ANY?0==b.length?b.push(new Producer.ExcludeEntry(new Name.Component,!0)):b[b.length-1].anyFollowsComponent_=!0:b.push(new Producer.ExcludeEntry(a.get(c),!1));return b};
+Producer.setExcludeEntries=function(a,b){a.clear();for(var c=0;c<b.length;++c){var d=b[c];0==c&&0==d.component_.getValue().size()&&d.anyFollowsComponent_?a.appendAny():(a.appendComponent(d.component_),d.anyFollowsComponent_&&a.appendAny())}};Producer.findEntryBeforeOrAt=function(a,b){for(var c=a.length-1;0<=c&&!(0>=a[c].component_.compare(b));)--c;return c};
+Producer.excludeAfter=function(a,b){var c=Producer.getExcludeEntries(a),d;d=Producer.findEntryBeforeOrAt(c,b);if(0>d)c.splice(0,0,new Producer.ExcludeEntry(b,!0)),d=0;else{var e=c[d];e.anyFollowsComponent_||(e.component_.equals(b)?e.anyFollowsComponent_=!0:(c.splice(d+1,0,new Producer.ExcludeEntry(b,!0)),d+=1))}d+=1;c.splice(d,c.length-d);Producer.setExcludeEntries(a,c)};Producer.excludeBefore=function(a,b){Producer.excludeRange(a,new Name.Component,b)};
+Producer.excludeRange=function(a,b,c){if(0<=b.compare(c)){if(0==b.compare(c))throw Error("excludeRange: from == to. To exclude a single component, sue excludeOne.");throw Error("excludeRange: from must be less than to. Invalid range: ["+b.toEscapedString()+", "+c.toEscapedString()+"]");}var d=Producer.getExcludeEntries(a),e=Producer.findEntryBeforeOrAt(d,b);if(0>e)d.splice(0,0,new Producer.ExcludeEntry(b,!0)),b=0;else{var f=d[e];f.anyFollowsComponent_?b=e:f.component_.equals(b)?(f.anyFollowsComponent_=
+!0,b=e):(d.splice(e+1,0,new Producer.ExcludeEntry(b,!0)),b=e+1)}e=Producer.findEntryBeforeOrAt(d,c);f=d[e];e==b?d.splice(b+1,0,new Producer.ExcludeEntry(c,!1)):(f.anyFollowsComponent_?c=e+1:f.component_.equals(c)?c=e:(d.splice(e+1,0,new Producer.ExcludeEntry(c,!1)),c=e+1),b+=1,d.splice(b,c-b));Producer.setExcludeEntries(a,d)};Producer.START_TIME_STAMP_INDEX=-2;Producer.END_TIME_STAMP_INDEX=-1;Producer.NO_LINK=new Link;
+var Interval=require("./interval.js").Interval,RepetitiveInterval=function RepetitiveInterval(b,c,d,e,f,g){if("object"===typeof b&&b instanceof RepetitiveInterval)repetitiveInterval=b,this.startDate_=repetitiveInterval.startDate_,this.endDate_=repetitiveInterval.endDate_,this.intervalStartHour_=repetitiveInterval.intervalStartHour_,this.intervalEndHour_=repetitiveInterval.intervalEndHour_,this.nRepeats_=repetitiveInterval.nRepeats_,this.repeatUnit_=repetitiveInterval.repeatUnit_;else if("number"===
+typeof b){void 0==f&&(f=0);void 0==g&&(g=RepetitiveInterval.RepeatUnit.NONE);this.startDate_=RepetitiveInterval.toDateOnlyMilliseconds_(b);this.endDate_=RepetitiveInterval.toDateOnlyMilliseconds_(c);this.intervalStartHour_=Math.round(d);this.intervalEndHour_=Math.round(e);this.nRepeats_=Math.round(f);this.repeatUnit_=g;if(!(this.intervalStartHour_<this.intervalEndHour_))throw Error("ReptitiveInterval: startHour must be less than endHour");if(!(this.startDate_<=this.endDate_))throw Error("ReptitiveInterval: startDate must be earlier than or same as endDate");
+if(!(0<=this.intervalStartHour_))throw Error("ReptitiveInterval: intervalStartHour must be non-negative");if(!(1<=this.intervalEndHour_&&24>=this.intervalEndHour_))throw Error("ReptitiveInterval: intervalEndHour must be from 1 to 24");if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.NONE&&this.startDate_!=this.endDate_)throw Error("ReptitiveInterval: With RepeatUnit.NONE, startDate must equal endDate");}else this.startDate_=-Number.MAX_VALUE,this.endDate_=-Number.MAX_VALUE,this.intervalStartHour_=
+0,this.intervalEndHour_=24,this.nRepeats_=0,this.repeatUnit_=RepetitiveInterval.RepeatUnit.NONE};exports.RepetitiveInterval=RepetitiveInterval;RepetitiveInterval.RepeatUnit={NONE:0,DAY:1,MONTH:2,YEAR:3};
+RepetitiveInterval.prototype.getInterval=function(a){var b,c;this.hasIntervalOnDate_(a)?(b=RepetitiveInterval.toDateOnlyMilliseconds_(a)+this.intervalStartHour_*RepetitiveInterval.MILLISECONDS_IN_HOUR,c=RepetitiveInterval.toDateOnlyMilliseconds_(a)+this.intervalEndHour_*RepetitiveInterval.MILLISECONDS_IN_HOUR,a<b?(c=b,b=RepetitiveInterval.toDateOnlyMilliseconds_(a),a=!1):a>c?(b=c,c=RepetitiveInterval.toDateOnlyMilliseconds_(a)+RepetitiveInterval.MILLISECONDS_IN_DAY,a=!1):a=!0):(b=RepetitiveInterval.toDateOnlyMilliseconds_(a),
+c=RepetitiveInterval.toDateOnlyMilliseconds_(a)+24*RepetitiveInterval.MILLISECONDS_IN_HOUR,a=!1);return{isPositive:a,interval:new Interval(b,c)}};
+RepetitiveInterval.prototype.compare=function(a){return this.startDate_<a.startDate_?-1:this.startDate_>a.startDate_?1:this.endDate_<a.endDate_?-1:this.endDate_>a.endDate_?1:this.intervalStartHour_<a.intervalStartHour_?-1:this.intervalStartHour_>a.intervalStartHour_?1:this.intervalEndHour_<a.intervalEndHour_?-1:this.intervalEndHour_>a.intervalEndHour_?1:this.nRepeats_<a.nRepeats_?-1:this.nRepeats_>a.nRepeats_?1:this.repeatUnit_<a.repeatUnit_?-1:this.repeatUnit_>a.repeatUnit_?1:0};
+RepetitiveInterval.prototype.getStartDate=function(){return this.startDate_};RepetitiveInterval.prototype.getEndDate=function(){return this.endDate_};RepetitiveInterval.prototype.getIntervalStartHour=function(){return this.intervalStartHour_};RepetitiveInterval.prototype.getIntervalEndHour=function(){return this.intervalEndHour_};RepetitiveInterval.prototype.getNRepeats=function(){return this.nRepeats_};RepetitiveInterval.prototype.getRepeatUnit=function(){return this.repeatUnit_};
+RepetitiveInterval.prototype.hasIntervalOnDate_=function(a){a=RepetitiveInterval.toDateOnlyMilliseconds_(a);if(a<this.startDate_||a>this.endDate_)return!1;if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.NONE)return!0;if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.DAY){if(0==(a-this.startDate_)/RepetitiveInterval.MILLISECONDS_IN_DAY%this.nRepeats_)return!0}else{a=new Date(a);var b=new Date(this.startDate_);if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.MONTH&&a.getUTCDate()==b.getUTCDate()){if(0==
+(12*(a.getUTCFullYear()-b.getUTCFullYear())+a.getUTCMonth()-b.getUTCMonth())%this.nRepeats_)return!0}else if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.YEAR&&a.getUTCDate()==b.getUTCDate()&&a.getUTCMonth()==b.getUTCMonth()&&0==(a.getUTCFullYear()-b.getUTCFullYear())%this.nRepeats_)return!0}return!1};RepetitiveInterval.toDateOnlyMilliseconds_=function(a){a=Math.round(a);return a-=a%RepetitiveInterval.MILLISECONDS_IN_DAY};RepetitiveInterval.MILLISECONDS_IN_HOUR=36E5;
+RepetitiveInterval.MILLISECONDS_IN_DAY=864E5;Interval=require("./interval.js").Interval;RepetitiveInterval=require("./repetitive-interval.js").RepetitiveInterval;Tlv=require("../encoding/tlv/tlv.js").Tlv;TlvEncoder=require("../encoding/tlv/tlv-encoder.js").TlvEncoder;TlvDecoder=require("../encoding/tlv/tlv-decoder.js").TlvDecoder;Blob=require("../util/blob.js").Blob;
+Schedule=function Schedule(b){"object"===typeof b&&b instanceof Schedule?(this.whiteIntervalList_=b.whiteIntervalList_.slice(0),this.blackIntervalList_=b.blackIntervalList_.slice(0)):(this.whiteIntervalList_=[],this.blackIntervalList_=[])};exports.Schedule=Schedule;Schedule.prototype.addWhiteInterval=function(a){Schedule.sortedSetAdd_(this.whiteIntervalList_,a);return this};Schedule.prototype.addBlackInterval=function(a){Schedule.sortedSetAdd_(this.blackIntervalList_,a);return this};
+Schedule.prototype.getCoveringInterval=function(a){var b=new Interval(!0),c=new Interval(!0),d=new Interval,e=new Interval;Schedule.calculateIntervalResult_(this.blackIntervalList_,a,b,d);if(!b.isEmpty())return{isPositive:!1,interval:b};Schedule.calculateIntervalResult_(this.whiteIntervalList_,a,c,e);return c.isEmpty()&&!e.isValid()?(a=RepetitiveInterval.toDateOnlyMilliseconds_(a),{isPositive:!1,interval:new Interval(a,a+RepetitiveInterval.MILLISECONDS_IN_DAY)}):c.isEmpty()?{isPositive:!1,interval:e}:
+d.isValid()?{isPositive:!0,interval:c.intersectWith(d)}:{isPositive:!0,interval:c}};
+Schedule.prototype.wireEncode=function(){for(var a=new TlvEncoder(256),b=a.getLength(),c=a.getLength(),d=this.blackIntervalList_.length-1;0<=d;d--)Schedule.encodeRepetitiveInterval_(this.blackIntervalList_[d],a);a.writeTypeAndLength(Tlv.Encrypt_BlackIntervalList,a.getLength()-c);c=a.getLength();for(d=this.whiteIntervalList_.length-1;0<=d;d--)Schedule.encodeRepetitiveInterval_(this.whiteIntervalList_[d],a);a.writeTypeAndLength(Tlv.Encrypt_WhiteIntervalList,a.getLength()-c);a.writeTypeAndLength(Tlv.Encrypt_Schedule,
+a.getLength()-b);return new Blob(a.getOutput(),!1)};
+Schedule.prototype.wireDecode=function(a){a="object"===typeof a&&a instanceof Blob?a.buf():a;a=new TlvDecoder(a);var b=a.readNestedTlvsStart(Tlv.Encrypt_Schedule);this.whiteIntervalList_=[];for(var c=a.readNestedTlvsStart(Tlv.Encrypt_WhiteIntervalList);a.getOffset()<c;)Schedule.sortedSetAdd_(this.whiteIntervalList_,Schedule.decodeRepetitiveInterval_(a));a.finishNestedTlvs(c);this.blackIntervalList_=[];for(c=a.readNestedTlvsStart(Tlv.Encrypt_BlackIntervalList);a.getOffset()<c;)Schedule.sortedSetAdd_(this.blackIntervalList_,
+Schedule.decodeRepetitiveInterval_(a));a.finishNestedTlvs(c);a.finishNestedTlvs(b)};Schedule.sortedSetAdd_=function(a,b){for(var c=0;c<a.length;){var d=a[c].compare(b);if(0==d)return;if(!(0>d))break;++c}a.splice(c,0,b)};
+Schedule.encodeRepetitiveInterval_=function(a,b){var c=b.getLength();b.writeNonNegativeIntegerTlv(Tlv.Encrypt_RepeatUnit,a.getRepeatUnit());b.writeNonNegativeIntegerTlv(Tlv.Encrypt_NRepeats,a.getNRepeats());b.writeNonNegativeIntegerTlv(Tlv.Encrypt_IntervalEndHour,a.getIntervalEndHour());b.writeNonNegativeIntegerTlv(Tlv.Encrypt_IntervalStartHour,a.getIntervalStartHour());b.writeBlobTlv(Tlv.Encrypt_EndDate,(new Blob(Schedule.toIsoString(a.getEndDate()))).buf());b.writeBlobTlv(Tlv.Encrypt_StartDate,
+(new Blob(Schedule.toIsoString(a.getStartDate()))).buf());b.writeTypeAndLength(Tlv.Encrypt_RepetitiveInterval,b.getLength()-c)};
+Schedule.decodeRepetitiveInterval_=function(a){var b=a.readNestedTlvsStart(Tlv.Encrypt_RepetitiveInterval),c=Schedule.fromIsoString((new Blob(a.readBlobTlv(Tlv.Encrypt_StartDate),!0)).toString()),d=Schedule.fromIsoString((new Blob(a.readBlobTlv(Tlv.Encrypt_EndDate),!0)).toString()),e=a.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalStartHour),f=a.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalEndHour),g=a.readNonNegativeIntegerTlv(Tlv.Encrypt_NRepeats),h=a.readNonNegativeIntegerTlv(Tlv.Encrypt_RepeatUnit);
+a.finishNestedTlvs(b);return new RepetitiveInterval(c,d,e,f,g,h)};Schedule.calculateIntervalResult_=function(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e].getInterval(b),g=f.interval;!0==f.isPositive?c.unionWith(g):d.isValid()?d.intersectWith(g):d.set(g)}};
+Schedule.toIsoString=function(a){a=new Date(Math.round(a));return a.getUTCFullYear()+Schedule.to2DigitString(a.getUTCMonth()+1)+Schedule.to2DigitString(a.getUTCDate())+"T"+Schedule.to2DigitString(a.getUTCHours())+Schedule.to2DigitString(a.getUTCMinutes())+Schedule.to2DigitString(a.getUTCSeconds())};Schedule.to2DigitString=function(a){a=a.toString();return 1===a.length?"0"+a:a};
+Schedule.fromIsoString=function(a){if(15!=a.length||"T"!=a.substr(8,1))throw Error("fromIsoString: Format is not the expected yyyymmddThhmmss");return Date.UTC(parseInt(a.substr(0,4)),parseInt(a.substr(4,2)-1),parseInt(a.substr(6,2)),parseInt(a.substr(9,2)),parseInt(a.substr(11,2)),parseInt(a.substr(13,2)))};var IndexedDbConsumerDb=function(a){ConsumerDb.call(this);this.database=new Dexie(a);this.database.version(1).stores({decryptionKeys:"keyName"});this.database.open()};
+IndexedDbConsumerDb.prototype=new ConsumerDb;IndexedDbConsumerDb.prototype.name="IndexedDbConsumerDb";
+IndexedDbConsumerDb.prototype.getKeyPromise=function(a,b){return b?Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.getKeyPromise is only supported for async"))):this.database.decryptionKeys.get(a.toUri()).then(function(a){return a?Promise.resolve(new Blob(a.key)):Promise.resolve(new Blob)})["catch"](function(a){return Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.getKeyPromise: Error: "+a)))})};
+IndexedDbConsumerDb.prototype.addKeyPromise=function(a,b,c){return c?Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.addKeyPromise is only supported for async"))):this.database.decryptionKeys.add({keyName:a.toUri(),key:b.buf()})["catch"](function(a){return Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.addKeyPromise: Error: "+a)))})};
+IndexedDbConsumerDb.prototype.deleteKeyPromise=function(a,b){return b?Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.deleteKeyPromise is only supported for async"))):this.database.decryptionKeys["delete"](a.toUri())["catch"](function(a){return Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.deleteKeyPromise: Error: "+a)))})};
+var IndexedDbGroupManagerDb=function(a){GroupManagerDb.call(this);this.database=new Dexie(a);this.database.version(1).stores({schedules:"++scheduleId, &scheduleName",members:"memberNameUri, scheduleId"});this.database.open()};IndexedDbGroupManagerDb.prototype=new GroupManagerDb;IndexedDbGroupManagerDb.prototype.name="IndexedDbGroupManagerDb";
+IndexedDbGroupManagerDb.prototype.hasSchedulePromise=function(a,b){return b?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.hasSchedulePromise is only supported for async"))):this.getScheduleIdPromise_(a).then(function(a){return Promise.resolve(-1!=a)})};
+IndexedDbGroupManagerDb.prototype.listAllScheduleNamesPromise=function(a){if(a)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllScheduleNamesPromise is only supported for async")));var b=[];return this.database.schedules.each(function(a){b.push(a.scheduleName)}).then(function(){return Promise.resolve(b)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllScheduleNamesPromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.getSchedulePromise=function(a,b){if(b)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getSchedulePromise is only supported for async")));var c=this;return this.getScheduleIdPromise_(a).then(function(a){return-1!=a?c.database.schedules.get(a).then(function(a){var b=new Schedule;b.wireDecode(new Blob(a.schedule,!1));return Promise.resolve(b)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getSchedulePromise: Error: "+
+a)))}):Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getSchedulePromise: Cannot get the result from the database")))})};
+IndexedDbGroupManagerDb.prototype.getScheduleMembersPromise=function(a,b){if(b)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleMembersPromise is only supported for async")));var c=[],d=this;return this.getScheduleIdPromise_(a).then(function(a){if(-1==a)return Promise.resolve(c);var b=null;return d.database.members.where("scheduleId").equals(a).each(function(a){try{var d=new Name;d.wireDecode(new Blob(a.keyName,!1),TlvWireFormat.get());c.push({keyName:d,publicKey:new Blob(a.publicKey,
+!1)})}catch(e){b=new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error decoding name: "+e))}}).then(function(){return b?Promise.reject(b):Promise.resolve(c)},function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error: "+a)))})})};
+IndexedDbGroupManagerDb.prototype.addSchedulePromise=function(a,b,c){return c?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addSchedulePromise is only supported for async"))):0==a.length?Promise.reject(new GroupManagerDb.Error("IndexedDbGroupManagerDb.addSchedulePromise: The schedule name cannot be empty")):this.database.schedules.add({scheduleName:a,schedule:b.wireEncode().buf()})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addContentKeyPromise: Error: "+
+a)))})};
+IndexedDbGroupManagerDb.prototype.deleteSchedulePromise=function(a,b){if(b)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.deleteSchedulePromise is only supported for async")));var c,d=this;return this.getScheduleIdPromise_(a).then(function(a){c=a;return d.database.members.where("scheduleId").equals(c).toArray()}).then(function(a){a=a.map(function(a){return d.database.members["delete"](a.memberNameUri)});return Promise.all(a)}).then(function(){return d.database.schedules["delete"](c)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.deleteSchedulePromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.renameSchedulePromise=function(a,b,c){if(c)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.renameSchedulePromise is only supported for async")));if(0==b.length)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.renameSchedule: The schedule newName cannot be empty")));var d=this;return this.getScheduleIdPromise_(a).then(function(a){return-1==a?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.renameSchedule: The schedule oldName does not exist"))):
+d.database.schedules.update(a,{scheduleName:b})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.renameSchedulePromise: Error: "+a)))})})};
+IndexedDbGroupManagerDb.prototype.updateSchedulePromise=function(a,b,c){if(c)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateSchedulePromise is only supported for async")));var d=this;return this.getScheduleIdPromise_(a).then(function(c){return-1==c?d.addSchedulePromise(a,b):d.database.schedules.update(c,{schedule:b.wireEncode().buf()})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateSchedulePromise: Error: "+
+a)))})})};IndexedDbGroupManagerDb.prototype.hasMemberPromise=function(a,b){return b?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.hasMemberPromise is only supported for async"))):this.database.members.get(a.toUri()).then(function(a){return Promise.resolve(void 0!=a)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.hasMemberPromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.listAllMembersPromise=function(a){if(a)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllMembersPromise is only supported for async")));var b=[],c=null;return this.database.members.each(function(a){try{var e=new Name;e.wireDecode(new Blob(a.memberName,!1),TlvWireFormat.get());b.push(e)}catch(f){c=new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllMembersPromise: Error decoding name: "+f))}}).then(function(){return c?
+Promise.reject(c):Promise.resolve(b)},function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllMembersPromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.getMemberSchedulePromise=function(a,b){if(b)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getMemberSchedulePromise is only supported for async")));var c=this;return this.database.members.get(a.toUri()).then(function(a){if(!a)throw Error("The member identity name does not exist in the database");return c.database.schedules.get(a.scheduleId)}).then(function(a){if(!a)throw Error("The schedule ID for the member identity name does not exist in the database");
+return Promise.resolve(a.scheduleName)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.addMemberPromise=function(a,b,c,d){if(d)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addMemberPromise is only supported for async")));var e=this;return this.getScheduleIdPromise_(a).then(function(a){if(-1==a)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addMemberPromise: The schedule does not exist")));var d=b.getPrefix(-1);return e.database.members.add({memberNameUri:d.toUri(),memberName:d.wireEncode(TlvWireFormat.get()).buf(),
+scheduleId:a,keyName:b.wireEncode(TlvWireFormat.get()).buf(),publicKey:c.buf()})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addMemberPromise: Error: "+a)))})})};
+IndexedDbGroupManagerDb.prototype.updateMemberSchedulePromise=function(a,b,c){if(c)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateMemberSchedulePromise is only supported for async")));var d=this;return this.getScheduleIdPromise_(b).then(function(b){return-1==b?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateMemberSchedulePromise: The schedule does not exist"))):d.database.members.update(a.toUri(),{scheduleId:b})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateMemberSchedulePromise: Error: "+
+a)))})})};IndexedDbGroupManagerDb.prototype.deleteMemberPromise=function(a,b){return b?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.deleteMemberPromise is only supported for async"))):this.database.members["delete"](a.toUri())["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.deleteMemberPromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.getScheduleIdPromise_=function(a){var b=-1;return this.database.schedules.where("scheduleName").equals(a).each(function(a){b=a.scheduleId}).then(function(){return Promise.resolve(b)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: "+a)))})};var IndexedDbProducerDb=function(a){ProducerDb.call(this);this.database=new Dexie(a);this.database.version(1).stores({contentKeys:"timeSlot"});this.database.open()};
+IndexedDbProducerDb.prototype=new ProducerDb;IndexedDbProducerDb.prototype.name="IndexedDbProducerDb";
+IndexedDbProducerDb.prototype.hasContentKeyPromise=function(a,b){if(b)return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.hasContentKeyPromise is only supported for async")));var c=ProducerDb.getFixedTimeSlot(a);return this.database.contentKeys.get(c).then(function(a){return Promise.resolve(void 0!=a)})["catch"](function(a){return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.hasContentKeyPromise: Error: "+a)))})};
+IndexedDbProducerDb.prototype.getContentKeyPromise=function(a,b){if(b)return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.getContentKeyPromise is only supported for async")));var c=ProducerDb.getFixedTimeSlot(a);return this.database.contentKeys.get(c).then(function(a){return a?Promise.resolve(new Blob(a.key)):Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.getContentKeyPromise: Cannot get the key from the database")))},function(a){return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.getContentKeyPromise: Error: "+
+a)))})};IndexedDbProducerDb.prototype.addContentKeyPromise=function(a,b,c){if(c)return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.addContentKeyPromise is only supported for async")));a=ProducerDb.getFixedTimeSlot(a);return this.database.contentKeys.add({timeSlot:a,key:b.buf()})["catch"](function(a){return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.addContentKeyPromise: Error: "+a)))})};
+IndexedDbProducerDb.prototype.deleteContentKeyPromise=function(a,b){if(b)return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.deleteContentKeyPromise is only supported for async")));var c=ProducerDb.getFixedTimeSlot(a);return this.database.contentKeys["delete"](c)["catch"](function(a){return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.deleteContentKeyPromise: Error: "+a)))})};
+var DigestTree=require("./digest-tree.js").DigestTree,Interest=require("../interest.js").Interest,Data=require("../data.js").Data,Name=require("../name.js").Name,Blob=require("../util/blob.js").Blob,MemoryContentCache=require("../util/memory-content-cache.js").MemoryContentCache,SyncStateProto=require("./sync-state.js").SyncStateProto,NdnCommon=require("../util/ndn-common.js").NdnCommon,ChronoSync2013=function ChronoSync2013(b,c,d,e,f,g,h,k,l,m){this.onReceivedSyncState=b;this.onInitialized=c;this.applicationDataPrefixUri=
+d.toUri();this.applicationBroadcastPrefix=e;this.session=f;this.face=g;this.keyChain=h;this.certificateName=k;this.sync_lifetime=l;this.usrseq=-1;this.digest_tree=new DigestTree;this.contentCache=new MemoryContentCache(g);this.digest_log=[];this.digest_log.push(new ChronoSync2013.DigestLogEntry("00",[]));this.contentCache.registerPrefix(this.applicationBroadcastPrefix,m,this.onInterest.bind(this));this.enabled=!0;b=new Interest(this.applicationBroadcastPrefix);b.getName().append("00");b.setInterestLifetimeMilliseconds(1E3);
+var q;try{q=dcodeIO.ProtoBuf.newBuilder()["import"](SyncStateProto).build("Sync")}catch(p){q=require("protobufjs").newBuilder()["import"](SyncStateProto).build("Sync")}this.SyncStateMsg=q.SyncStateMsg;this.SyncState=q.SyncState;this.face.expressInterest(b,this.onData.bind(this),this.initialTimeOut.bind(this))};exports.ChronoSync2013=ChronoSync2013;ChronoSync2013.prototype.getProducerSequenceNo=function(a,b){var c=this.digest_tree.find(a,b);return 0>c?-1:this.digest_tree.get(c).getSequenceNo()};
+ChronoSync2013.prototype.publishNextSequenceNo=function(){this.usrseq++;var a=[new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:this.usrseq,session:this.session}})],b=new this.SyncStateMsg({ss:a});this.broadcastSyncState(this.digest_tree.getRoot(),b);this.update(a)||console.log("Warning: ChronoSync: update did not create a new digest log entry");a=new Interest(this.applicationBroadcastPrefix);a.getName().append(this.digest_tree.getRoot());a.setInterestLifetimeMilliseconds(this.sync_lifetime);
+this.face.expressInterest(a,this.onData.bind(this),this.syncTimeout.bind(this))};ChronoSync2013.prototype.getSequenceNo=function(){return this.usrseq};ChronoSync2013.DigestLogEntry=function(a,b){this.digest=a;this.data=b};ChronoSync2013.DigestLogEntry.prototype.getDigest=function(){return this.digest};ChronoSync2013.DigestLogEntry.prototype.getData=function(){return this.data};ChronoSync2013.prototype.shutdown=function(){this.enabled=!1;this.contentCache.unregisterAll()};
+ChronoSync2013.SyncState=function(a,b,c){this.dataPrefixUri_=a;this.sessionNo_=b;this.sequenceNo_=c};ChronoSync2013.SyncState.prototype.getDataPrefix=function(){return this.dataPrefixUri_};ChronoSync2013.SyncState.prototype.getSessionNo=function(){return this.sessionNo_};ChronoSync2013.SyncState.prototype.getSequenceNo=function(){return this.sequenceNo_};
+ChronoSync2013.prototype.broadcastSyncState=function(a,b){var c=new Uint8Array(b.toArrayBuffer()),d=new Data(this.applicationBroadcastPrefix);d.getName().append(a);d.setContent(new Blob(c,!1));var e=this;this.keyChain.sign(d,this.certificateName,function(){e.contentCache.add(d)})};
+ChronoSync2013.prototype.update=function(a){for(var b=0;b<a.length;b++)0==a[b].type&&this.digest_tree.update(a[b].name,a[b].seqno.session,a[b].seqno.seq)&&this.applicationDataPrefixUri==a[b].name&&(this.usrseq=a[b].seqno.seq);return-1==this.logfind(this.digest_tree.getRoot())?(a=new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(),a),this.digest_log.push(a),!0):!1};
+ChronoSync2013.prototype.logfind=function(a){for(var b=0;b<this.digest_log.length;b++)if(a==this.digest_log[b].digest)return b;return-1};
+ChronoSync2013.prototype.onInterest=function(a,b,c,d,e){this.enabled&&(a=b.getName().get(this.applicationBroadcastPrefix.size()).toEscapedString(),b.getName().size()==this.applicationBroadcastPrefix.size()+2&&(a=b.getName().get(this.applicationBroadcastPrefix.size()+1).toEscapedString()),b.getName().size()==this.applicationBroadcastPrefix.size()+2||"00"==a?this.processRecoveryInst(b,a,c):(this.contentCache.storePendingInterest(b,c),a!=this.digest_tree.getRoot()&&(b=this.logfind(a),-1==b?(b=new Interest(new Name("/local/timeout")),
+b.setInterestLifetimeMilliseconds(2E3),this.face.expressInterest(b,this.dummyOnData,this.judgeRecovery.bind(this,b,a,c))):this.processSyncInst(b,a,c))))};
+ChronoSync2013.prototype.onData=function(a,b){if(this.enabled){var c=new Uint8Array(b.getContent().size());c.set(b.getContent().buf());var c=this.SyncStateMsg.decode(c.buffer).ss,d=!1;"00"==this.digest_tree.getRoot()?(d=!0,this.initialOndata(c)):(this.update(c),d=a.getName().size()==this.applicationBroadcastPrefix.size()+2?!0:!1);for(var e=[],f=0;f<c.length;f++)0==c[f].type&&e.push(new ChronoSync2013.SyncState(c[f].name,c[f].seqno.session,c[f].seqno.seq));try{this.onReceivedSyncState(e,d)}catch(g){console.log("Error in onReceivedSyncState: "+
+NdnCommon.getErrorWithStackTrace(g))}c=new Name(this.applicationBroadcastPrefix);c.append(this.digest_tree.getRoot());a=new Interest(c);a.setInterestLifetimeMilliseconds(this.sync_lifetime);this.face.expressInterest(a,this.onData.bind(this),this.syncTimeout.bind(this))}};
+ChronoSync2013.prototype.initialTimeOut=function(a){if(this.enabled){console.log("no other people");this.usrseq++;try{this.onInitialized()}catch(b){console.log("Error in onInitialized: "+NdnCommon.getErrorWithStackTrace(b))}a=[new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:this.usrseq,session:this.session}})];this.update(a);a=new Name(this.applicationBroadcastPrefix);a.append(this.digest_tree.getRoot());a=new Interest(a);a.setInterestLifetimeMilliseconds(this.sync_lifetime);
+this.face.expressInterest(a,this.onData.bind(this),this.syncTimeout.bind(this))}};
+ChronoSync2013.prototype.processRecoveryInst=function(a,b,c){if(-1!=this.logfind(b)){b=[];for(var d=0;d<this.digest_tree.digestnode.length;d++)b[d]=new this.SyncState({name:this.digest_tree.digestnode[d].getDataPrefix(),type:"UPDATE",seqno:{seq:this.digest_tree.digestnode[d].getSequenceNo(),session:this.digest_tree.digestnode[d].getSessionNo()}});if(0!=b.length){b=new this.SyncStateMsg({ss:b});b=new Uint8Array(b.toArrayBuffer());var e=new Data(a.getName());e.setContent(new Blob(b,!1));"00"==a.getName().get(-1).toEscapedString()&&
+e.getMetaInfo().setFreshnessPeriod(1E3);this.keyChain.sign(e,this.certificateName,function(){try{c.putData(e)}catch(a){console.log(a.toString())}})}}};
+ChronoSync2013.prototype.processSyncInst=function(a,b,c){for(var d=[],e=[],f=[],g=[],h=a+1;h<this.digest_log.length;h++)for(var k=this.digest_log[h].getData(),l=0;l<k.length;l++)0==k[l].type&&-1!=this.digest_tree.find(k[l].name,k[l].seqno.session)&&(a=e.indexOf(k[l].name),-1==a?(e.push(k[l].name),f.push(k[l].seqno.seq),g.push(k[l].seqno.session)):(f[a]=k[l].seqno.seq,g[a]=k[l].seqno.session));for(l=0;l<e.length;l++)d[l]=new this.SyncState({name:e[l],type:"UPDATE",seqno:{seq:f[l],session:g[l]}});if(0!=
+d.length){d=new this.SyncStateMsg({ss:d});d=new Uint8Array(d.toArrayBuffer());a=new Name(this.prefix);a.append(this.chatroom).append(b);var m=new Data(a);m.setContent(new Blob(d,!1));this.keyChain.sign(m,this.certificateName,function(){try{c.putData(m)}catch(a){console.log(a.toString())}})}};
+ChronoSync2013.prototype.sendRecovery=function(a){var b=new Name(this.applicationBroadcastPrefix);b.append("recovery").append(a);a=new Interest(b);a.setInterestLifetimeMilliseconds(this.sync_lifetime);this.face.expressInterest(a,this.onData.bind(this),this.syncTimeout.bind(this))};ChronoSync2013.prototype.judgeRecovery=function(a,b,c){a=this.logfind(b);-1!=a?b!=this.digest_tree.root&&this.processSyncInst(a,b,c):this.sendRecovery(b)};
+ChronoSync2013.prototype.syncTimeout=function(a){if(this.enabled&&a.getName().get(4).toEscapedString()==this.digest_tree.root){var b=new Name(a.getName()),b=new Interest(b);a.setInterestLifetimeMilliseconds(this.sync_lifetime);this.face.expressInterest(b,this.onData.bind(this),this.syncTimeout.bind(this))}};
+ChronoSync2013.prototype.initialOndata=function(a){this.update(a);for(var b=this.digest_tree.getRoot(),c=0;c<a.length;c++)if(a[c].name==this.applicationDataPrefixUri&&a[c].seqno.session==this.session){var d=[new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:a[c].seqno.seq+1,session:this.session}})];if(this.update(d)){d=new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(),d);this.digest_log.push(d);try{this.onInitialized()}catch(e){console.log("Error in onInitialized: "+
+NdnCommon.getErrorWithStackTrace(e))}}}d=0<=this.usrseq?new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:this.usrseq,session:this.session}}):new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:0,session:this.session}});a=new this.SyncStateMsg({ss:d});this.broadcastSyncState(b,a);if(-1==this.digest_tree.find(this.applicationDataPrefixUri,this.session)&&(this.usrseq++,a=[new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:this.usrseq,
+session:this.session}})],this.update(a)))try{this.onInitialized()}catch(f){console.log("Error in onInitialized: "+NdnCommon.getErrorWithStackTrace(f))}};ChronoSync2013.prototype.dummyOnData=function(a,b){console.log("*** dummyOnData called. ***")};Crypto=require("../crypto.js");DigestTree=function(){this.root="00";this.digestnode=[]};exports.DigestTree=DigestTree;DigestTree.Node=function(a,b,c){this.dataPrefix=a;this.seqno_session=b;this.seqno_seq=c;this.recomputeDigest()};
+DigestTree.Node.prototype.getDataPrefix=function(){return this.dataPrefix};DigestTree.Node.prototype.getSessionNo=function(){return this.seqno_session};DigestTree.Node.prototype.getSequenceNo=function(){return this.seqno_seq};DigestTree.Node.prototype.getDigest=function(){return this.digest};DigestTree.Node.prototype.setSequenceNo=function(a){this.seqno_seq=a;this.recomputeDigest()};
+DigestTree.Node.prototype.Int32ToBuffer=function(a){for(var b=new Buffer(4),c=0;4>c;c++)b[c]=a%256,a=Math.floor(a/256);return b};DigestTree.Node.prototype.recomputeDigest=function(){var a=Crypto.createHash("sha256");a.update(this.Int32ToBuffer(this.seqno_session));a.update(this.Int32ToBuffer(this.seqno_seq));var a=a.digest(),b=Crypto.createHash("sha256");b.update(this.dataPrefix);var b=b.digest(),c=Crypto.createHash("sha256");c.update(b);c.update(a);this.digest=c.digest("hex")};
+DigestTree.Node.Compare=function(a,b){return a.dataPrefix!=b.dataPrefix?a.dataPrefix<b.dataPrefix:a.seqno_session<b.seqno_session};DigestTree.prototype.update=function(a,b,c){var d=this.find(a,b);if(0<=d)if(this.digestnode[d].getSequenceNo()<c)this.digestnode[d].setSequenceNo(c);else return!1;else a=new DigestTree.Node(a,b,c),this.digestnode.push(a),this.digestnode.sort(this.sortNodes);this.recomputeRoot();return!0};
+DigestTree.prototype.sortNodes=function(){for(var a,b=this.digestnode.length;0<b;b--)for(var c=0;c<b-1;c++)this.digestnode[c].getDataPrefix()>this.digestnode[c+1].getDataPrefix()&&(a=this.digestnode[c],this.digestnode[c]=this.digestnode[c+1],this.digestnode[c+1]=a)};
+DigestTree.prototype.sortNodes=function(a,b){return a.getDataPrefix()==b.getDataPrefix()&&a.getSessionNo()==b.getSessionNo()?0:a.getDataPrefix()>b.getDataPrefix()||a.getDataPrefix()==b.getDataPrefix()&&a.getSessionNo()>b.getSessionNo()?1:-1};DigestTree.prototype.find=function(a,b){for(var c=0;c<this.digestnode.length;++c)if(this.digestnode[c].getDataPrefix()==a&&this.digestnode[c].getSessionNo()==b)return c;return-1};DigestTree.prototype.size=function(){return this.digestnode.size()};
+DigestTree.prototype.get=function(a){return this.digestnode[a]};DigestTree.prototype.getRoot=function(){return this.root};DigestTree.prototype.recomputeRoot=function(){for(var a=Crypto.createHash("sha256"),b=0;b<this.digestnode.length;b++)a.update(new Buffer(this.digestnode[b].digest,"hex"));this.root=a.digest("hex")};
+SyncStateProto={"package":"Sync",messages:[{name:"SyncState",fields:[{rule:"required",type:"string",name:"name",id:1,options:{}},{rule:"required",type:"ActionType",name:"type",id:2,options:{}},{rule:"optional",type:"SeqNo",name:"seqno",id:3,options:{}}],enums:[{name:"ActionType",values:[{name:"UPDATE",id:0},{name:"DELETE",id:1},{name:"OTHER",id:2}],options:{}}],messages:[{name:"SeqNo",fields:[{rule:"required",type:"uint32",name:"seq",id:1,options:{}},{rule:"required",type:"uint32",name:"session",
+id:2,options:{}}],enums:[],messages:[],options:{}}],options:{}},{name:"SyncStateMsg",fields:[{rule:"repeated",type:"SyncState",name:"ss",id:1,options:{}}],enums:[],messages:[],options:{}}],enums:[],imports:[],options:{}};exports.SyncStateProto=SyncStateProto;
+var Crypto=require("../crypto.js"),WireFormat=require("../encoding/wire-format.js").WireFormat,TlvEncoder=require("../encoding/tlv/tlv-encoder.js").TlvEncoder,Blob=require("./blob.js").Blob,CommandInterestGenerator=function(){this.lastTimestamp=Math.round((new Date).getTime())};exports.CommandInterestGenerator=CommandInterestGenerator;
+CommandInterestGenerator.prototype.generate=function(a,b,c,d,e){e="function"===typeof d?d:e;d="function"!==typeof d&&d?d:WireFormat.getDefaultWireFormat();for(var f=Math.round((new Date).getTime());f<=this.lastTimestamp;)f+=1;var g=new TlvEncoder(8);g.writeNonNegativeInteger(f);a.getName().append(new Blob(g.getOutput(),!1));a.getName().append(new Blob(Crypto.randomBytes(8),!1));this.lastTimestamp=f;b.sign(a,c,d,function(){(null==a.getInterestLifetimeMilliseconds()||0>a.getInterestLifetimeMilliseconds())&&
+a.setInterestLifetimeMilliseconds(1E3);e&&e()})};var LOG=require("../log.js").Log.LOG,InterestFilterTable=function(){this.table_=[]};exports.InterestFilterTable=InterestFilterTable;InterestFilterTable.Entry=function(a,b,c,d){this.interestFilterId_=a;this.filter_=b;this.onInterest_=c;this.face_=d};InterestFilterTable.Entry.prototype.getInterestFilterId=function(){return this.interestFilterId_};InterestFilterTable.Entry.prototype.getFilter=function(){return this.filter_};
+InterestFilterTable.Entry.prototype.getOnInterest=function(){return this.onInterest_};InterestFilterTable.Entry.prototype.getFace=function(){return this.face_};InterestFilterTable.prototype.setInterestFilter=function(a,b,c,d){this.table_.push(new InterestFilterTable.Entry(a,b,c,d))};InterestFilterTable.prototype.getMatchedFilters=function(a,b){for(var c=0;c<this.table_.length;++c){var d=this.table_[c];d.getFilter().doesMatch(a.getName())&&b.push(d)}};
+InterestFilterTable.prototype.unsetInterestFilter=function(a){for(var b=0,c=this.table_.length-1;0<=c;--c)this.table_[c].getInterestFilterId()==a&&(++b,this.table_.splice(c,1));0===b&&0<LOG&&console.log("unsetInterestFilter: Didn't find interestFilterId "+a)};var NdnCommon=require("../util/ndn-common.js").NdnCommon,LOG=require("../log.js").Log.LOG,PendingInterestTable=function(){this.table_=[];this.removeRequests_=[]};exports.PendingInterestTable=PendingInterestTable;
+PendingInterestTable.Entry=function(a,b,c,d,e){this.pendingInterestId_=a;this.interest_=b;this.onData_=c;this.onTimeout_=d;this.onNetworkNack_=e;this.timerId_=-1};PendingInterestTable.Entry.prototype.getPendingInterestId=function(){return this.pendingInterestId_};PendingInterestTable.Entry.prototype.getInterest=function(){return this.interest_};PendingInterestTable.Entry.prototype.getOnData=function(){return this.onData_};PendingInterestTable.Entry.prototype.getOnNetworkNack=function(){return this.onNetworkNack_};
+PendingInterestTable.Entry.prototype.callTimeout=function(){if(this.onTimeout_)try{this.onTimeout_(this.interest_)}catch(a){console.log("Error in onTimeout: "+NdnCommon.getErrorWithStackTrace(a))}};PendingInterestTable.Entry.prototype.setTimeout=function(a,b){-1===this.timerId_&&(this.timerId_=setTimeout(a,b))};PendingInterestTable.Entry.prototype.clearTimeout=function(){-1!==this.timerId_&&(clearTimeout(this.timerId_),this.timerId_=-1)};
+PendingInterestTable.prototype.add=function(a,b,c,d,e){var f=this.removeRequests_.indexOf(a);if(0<=f)return this.removeRequests_.splice(f,1),null;var g=new PendingInterestTable.Entry(a,b,c,d,e);this.table_.push(g);a=b.getInterestLifetimeMilliseconds()||4E3;var h=this;g.setTimeout(function(){1<LOG&&console.log("Interest time out: "+b.getName().toUri());var a=h.table_.indexOf(g);0<=a&&h.table_.splice(a,1);g.callTimeout()},a);return g};
+PendingInterestTable.prototype.extractEntriesForExpressedInterest=function(a,b){for(var c=this.table_.length-1;0<=c;--c){var d=this.table_[c];d.getInterest().matchesData(a)&&(d.clearTimeout(),b.push(d),this.table_.splice(c,1))}};PendingInterestTable.prototype.extractEntriesForNackInterest=function(a,b){for(var c=a.wireEncode(),d=this.table_.length-1;0<=d;--d){var e=this.table_[d];null!=e.getOnNetworkNack()&&e.getInterest().wireEncode().equals(c)&&(e.clearTimeout(),b.push(e),this.table_.splice(d,1))}};
+PendingInterestTable.prototype.removePendingInterest=function(a){if(null!=a){for(var b=0,c=this.table_.length-1;0<=c;--c){var d=this.table_[c];d.getPendingInterestId()==a&&(d.clearTimeout(),this.table_.splice(c,1),++b)}0===b&&0<LOG&&console.log("removePendingInterest: Didn't find pendingInterestId "+a);0===b&&0>this.removeRequests_.indexOf(a)&&this.removeRequests_.push(a)}};
+var LOG=require("../log.js").Log.LOG,RegisteredPrefixTable=function(a){this.interestFilterTable_=a;this.table_=[];this.removeRequests_=[]};exports.RegisteredPrefixTable=RegisteredPrefixTable;RegisteredPrefixTable.prototype.add=function(a,b,c){var d=this.removeRequests_.indexOf(a);if(0<=d)return this.removeRequests_.splice(d,1),!1;this.table_.push(new RegisteredPrefixTable._Entry(a,b,c));return!0};
+RegisteredPrefixTable.prototype.removeRegisteredPrefix=function(a){for(var b=0,c=this.table_.length-1;0<=c;--c){var d=this.table_[c];d.getRegisteredPrefixId()==a&&(++b,0<d.getRelatedInterestFilterId()&&this.interestFilterTable_.unsetInterestFilter(d.getRelatedInterestFilterId()),this.table_.splice(c,1))}0===b&&0<LOG&&console.log("removeRegisteredPrefix: Didn't find registeredPrefixId "+a);0===b&&0>this.removeRequests_.indexOf(a)&&this.removeRequests_.push(a)};
+RegisteredPrefixTable._Entry=function(a,b,c){this.registeredPrefixId_=a;this.prefix_=b;this.relatedInterestFilterId_=c};RegisteredPrefixTable._Entry.prototype.getRegisteredPrefixId=function(){return this.registeredPrefixId};RegisteredPrefixTable._Entry.prototype.getPrefix=function(){return this.prefix};RegisteredPrefixTable._Entry.prototype.getRelatedInterestFilterId=function(){return this.relatedInterestFilterId};IncomingFaceId=function(){this.faceId_=null};exports.IncomingFaceId=IncomingFaceId;
+IncomingFaceId.prototype.getFaceId=function(){return this.faceId_};IncomingFaceId.prototype.setFaceId=function(a){this.faceId_=a};IncomingFaceId.getFirstHeader=function(a){for(var b=0;b<a.countHeaderFields();++b){var c=a.getHeaderField(b);if(c instanceof IncomingFaceId)return c}return null};var Blob=require("../util/blob.js").Blob,LpPacket=function(){this.headerFields_=[];this.fragmentWireEncoding_=new Blob};exports.LpPacket=LpPacket;LpPacket.prototype.getFragmentWireEncoding=function(){return this.fragmentWireEncoding_};
+LpPacket.prototype.countHeaderFields=function(){return this.headerFields_.length};LpPacket.prototype.getHeaderField=function(a){return this.headerFields_[a]};LpPacket.prototype.clear=function(){this.headerFields_=[];this.fragmentWireEncoding_=new Blob};LpPacket.prototype.setFragmentWireEncoding=function(a){this.fragmentWireEncoding_="object"===typeof a&&a instanceof Blob?a:new Blob(a)};LpPacket.prototype.addHeaderField=function(a){this.headerFields_.push(a)};
+var DataUtils=require("./encoding/data-utils.js").DataUtils,Name=require("./name.js").Name,Interest=require("./interest.js").Interest,Data=require("./data.js").Data,ControlParameters=require("./control-parameters.js").ControlParameters,ControlResponse=require("./control-response.js").ControlResponse,InterestFilter=require("./interest-filter.js").InterestFilter,WireFormat=require("./encoding/wire-format.js").WireFormat,TlvWireFormat=require("./encoding/tlv-wire-format.js").TlvWireFormat,Tlv=require("./encoding/tlv/tlv.js").Tlv,
+TlvDecoder=require("./encoding/tlv/tlv-decoder.js").TlvDecoder,ForwardingFlags=require("./forwarding-flags.js").ForwardingFlags,Transport=require("./transport/transport.js").Transport,TcpTransport=require("./transport/tcp-transport.js").TcpTransport,UnixTransport=require("./transport/unix-transport.js").UnixTransport,CommandInterestGenerator=require("./util/command-interest-generator.js").CommandInterestGenerator,Blob=require("./util/blob.js").Blob,NdnCommon=require("./util/ndn-common.js").NdnCommon,
+NetworkNack=require("./network-nack.js").NetworkNack,LpPacket=require("./lp/lp-packet.js").LpPacket,InterestFilterTable=require("./impl/interest-filter-table.js").InterestFilterTable,PendingInterestTable=require("./impl/pending-interest-table.js").PendingInterestTable,RegisteredPrefixTable=require("./impl/registered-prefix-table.js").RegisteredPrefixTable,fs=require("fs"),LOG=require("./log.js").Log.LOG;
+Face=function Face(b,c){if(!Face.supported)throw Error("The necessary JavaScript support is not available on this platform.");var d;if("object"==typeof b&&b instanceof Transport){if(this.getConnectionInfo=null,this.transport=b,this.connectionInfo=c||null,d={},null==this.connectionInfo&&this.transport&&this.transport.__proto__&&"UnixTransport"==this.transport.__proto__.name){var e=Face.getUnixSocketFilePathForLocalhost();null!=e?this.connectionInfo=new UnixTransport.ConnectionInfo(e):console.log("Face constructor: Cannot determine the default Unix socket file path for UnixTransport");
+0<LOG&&console.log("Using "+this.connectionInfo.toString())}}else d=b||{},this.transport=(d.getTransport||function(){return new TcpTransport})(),this.getConnectionInfo=d.getConnectionInfo||this.transport.defaultGetConnectionInfo,this.connectionInfo=d.connectionInfo||null,null==this.connectionInfo&&(e=void 0!==d.host?d.host:null,this.transport&&this.transport.__proto__&&"UnixTransport"==this.transport.__proto__.name?null!=e?this.connectionInfo=new UnixTransport.ConnectionInfo(e):null==this.getConnectionInfo&&
+(e=Face.getUnixSocketFilePathForLocalhost(),null!=e?this.connectionInfo=new UnixTransport.ConnectionInfo(e):console.log("Face constructor: Cannot determine the default Unix socket file path for UnixTransport")):null!=e&&(this.connectionInfo="undefined"!=typeof WebSocketTransport?new WebSocketTransport.ConnectionInfo(e,d.port||9696):new TcpTransport.ConnectionInfo(e,d.port||6363)));null==this.connectionInfo?this.host=this.host=null:(this.host=this.connectionInfo.host,this.host=this.connectionInfo.port);
+this.readyStatus=Face.UNOPEN;this.onopen=d.onopen||function(){3<LOG&&console.log("Face connection established.")};this.onclose=d.onclose||function(){3<LOG&&console.log("Face connection closed.")};this.onConnectedCallbacks=[];this.commandKeyChain=null;this.commandCertificateName=new Name;this.commandInterestGenerator=new CommandInterestGenerator;this.timeoutPrefix=new Name("/local/timeout");this.pendingInterestTable_=new PendingInterestTable;this.interestFilterTable_=new InterestFilterTable;this.registeredPrefixTable_=
+new RegisteredPrefixTable(this.interestFilterTable_);this.lastEntryId=0};exports.Face=Face;Face.UNOPEN=0;Face.OPEN_REQUESTED=1;Face.OPENED=2;Face.CLOSED=3;TcpTransport.importFace(Face);Face.getUnixSocketFilePathForLocalhost=function(){var a="/var/run/nfd.sock";if(fs.existsSync(a))return a;a="/tmp/.ndnd.sock";return fs.existsSync(a)?a:""};Face.getSupported=function(){try{(new Buffer(1)).slice(0,1)}catch(a){return console.log("NDN not available: Buffer not supported. "+a),!1}return!0};
+Face.supported=Face.getSupported();Face.prototype.createRoute=function(a,b){this.connectionInfo=a instanceof Transport.ConnectionInfo?a:new TcpTransport.ConnectionInfo(a,b);this.host=this.connectionInfo.host;this.host=this.connectionInfo.port};Face.prototype.close=function(){this.readyStatus==Face.OPENED&&(this.readyStatus=Face.CLOSED,this.transport.close())};Face.prototype.getNextEntryId=function(){return++this.lastEntryId};
+Face.makeShuffledHostGetConnectionInfo=function(a,b,c){a=a.slice(0,a.length);DataUtils.shuffle(a);return function(){return 0==a.length?null:c(a.splice(0,1)[0],b)}};
+Face.prototype.expressInterest=function(a,b,c,d,e,f){var g;"object"===typeof a&&a instanceof Interest?g=new Interest(a):b&&"object"===typeof b&&b instanceof Interest?(g=new Interest(b),g.setName(a),b=c,c=d,d=e,e=f):(g=new Interest(a),g.setInterestLifetimeMilliseconds(4E3));var h=b,k,l,m;k="function"===typeof c?c:function(){};l="function"===typeof d?d:null;m=c instanceof WireFormat?c:d instanceof WireFormat?d:e instanceof WireFormat?e:WireFormat.getDefaultWireFormat();var q=this.getNextEntryId();g.setNonce(Face.nonceTemplate_);
+g.refreshNonce();if(null==this.connectionInfo)if(null==this.getConnectionInfo)console.log("ERROR: connectionInfo is NOT SET");else{var p=this;this.connectAndExecute(function(){p.reconnectAndExpressInterest(q,g,h,k,l,m)})}else this.reconnectAndExpressInterest(q,g,h,k,l,m);return q};
+Face.prototype.reconnectAndExpressInterest=function(a,b,c,d,e,f){var g=this;if(this.connectionInfo.equals(this.transport.connectionInfo)&&this.readyStatus!==Face.UNOPEN)if(this.readyStatus===Face.OPEN_REQUESTED)this.onConnectedCallbacks.push(function(){g.expressInterestHelper(a,b,c,d,e,f)});else if(this.readyStatus===Face.OPENED)this.expressInterestHelper(a,b,c,d,e,f);else throw Error("reconnectAndExpressInterest: unexpected connection is not opened");else this.readyStatus=Face.OPEN_REQUESTED,this.onConnectedCallbacks.push(function(){g.expressInterestHelper(a,
+b,c,d,e,f)}),this.transport.connect(this.connectionInfo,this,function(){for(g.readyStatus=Face.OPENED;0<g.onConnectedCallbacks.length;)try{g.onConnectedCallbacks.shift()()}catch(a){console.log("Face.reconnectAndExpressInterest: ignoring exception from onConnectedCallbacks: "+a)}if(g.onopen)g.onopen()},function(){g.closeByTransport()})};
+Face.prototype.expressInterestHelper=function(a,b,c,d,e,f){if(null!=this.pendingInterestTable_.add(a,b,c,d,e)&&!this.timeoutPrefix.match(b.getName())){a=b.wireEncode(f);if(a.size()>Face.getMaxNdnPacketSize())throw Error("The encoded interest size exceeds the maximum limit getMaxNdnPacketSize()");this.transport.send(a.buf())}};Face.prototype.removePendingInterest=function(a){this.pendingInterestTable_.removePendingInterest(a)};
+Face.prototype.setCommandSigningInfo=function(a,b){this.commandKeyChain=a;this.commandCertificateName=new Name(b)};Face.prototype.setCommandCertificateName=function(a){this.commandCertificateName=new Name(a)};Face.prototype.makeCommandInterest=function(a,b,c){c="function"===typeof b?b:c;b="function"!==typeof b&&b?b:WireFormat.getDefaultWireFormat();this.nodeMakeCommandInterest(a,this.commandKeyChain,this.commandCertificateName,b,c)};
+Face.prototype.nodeMakeCommandInterest=function(a,b,c,d,e){this.commandInterestGenerator.generate(a,b,c,d,e)};
+Face.prototype.registerPrefix=function(a,b,c,d,e,f){var g=d,h=e,k=f;d="function"===typeof g?g:null;e=g instanceof ForwardingFlags?g:h instanceof ForwardingFlags?h:new ForwardingFlags;f=g instanceof WireFormat?g:h instanceof WireFormat?h:k instanceof WireFormat?k:WireFormat.getDefaultWireFormat();c||(c=function(){});var l=this.getNextEntryId(),m=this,g=function(){m.nfdRegisterPrefix(l,a,b,e,c,d,m.commandKeyChain,m.commandCertificateName,f)};null==this.connectionInfo?null==this.getConnectionInfo?console.log("ERROR: connectionInfo is NOT SET"):
+this.connectAndExecute(g):g();return l};Face.getMaxNdnPacketSize=function(){return NdnCommon.MAX_NDN_PACKET_SIZE};Face.RegisterResponse=function(a,b,c,d,e,f){this.prefix=a;this.onRegisterFailed=b;this.onRegisterSuccess=c;this.registeredPrefixId=d;this.parent=e;this.onInterest=f};
+Face.RegisterResponse.prototype.onData=function(a,b){var c=new ControlResponse;try{c.wireDecode(b.getContent(),TlvWireFormat.get())}catch(d){0<LOG&&console.log("Register prefix failed: Error decoding the NFD response: "+d);if(this.onRegisterFailed)try{this.onRegisterFailed(this.prefix)}catch(e){console.log("Error in onRegisterFailed: "+NdnCommon.getErrorWithStackTrace(e))}return}if(200!=c.getStatusCode()){if(0<LOG&&console.log("Register prefix failed: Expected NFD status code 200, got: "+c.getStatusCode()),
+this.onRegisterFailed)try{this.onRegisterFailed(this.prefix)}catch(f){console.log("Error in onRegisterFailed: "+NdnCommon.getErrorWithStackTrace(f))}}else{if(0!=this.registeredPrefixId&&(c=0,null!=this.onInterest&&(c=this.parent.setInterestFilter(new InterestFilter(this.prefix),this.onInterest)),!this.parent.registeredPrefixTable_.add(this.registeredPrefixId,this.prefix,c))){0<c&&this.parent.unsetInterestFilter(c);return}2<LOG&&console.log("Register prefix succeeded with the NFD forwarder for prefix "+
+this.prefix.toUri());if(null!=this.onRegisterSuccess)try{this.onRegisterSuccess(this.prefix,this.registeredPrefixId)}catch(g){console.log("Error in onRegisterSuccess: "+NdnCommon.getErrorWithStackTrace(g))}}};Face.RegisterResponse.prototype.onTimeout=function(a){2<LOG&&console.log("Timeout for NFD register prefix command.");if(this.onRegisterFailed)try{this.onRegisterFailed(this.prefix)}catch(b){console.log("Error in onRegisterFailed: "+NdnCommon.getErrorWithStackTrace(b))}};
+Face.prototype.nfdRegisterPrefix=function(a,b,c,d,e,f,g,h,k){if(null==g)throw Error("registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo.");if(0==h.size())throw Error("registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo.");var l=new ControlParameters;l.setName(b);l.setForwardingFlags(d);var m=this;this.isLocal(function(d){var p=new Interest;d?(p.setName(new Name("/localhost/nfd/rib/register")),p.setInterestLifetimeMilliseconds(2E3)):
+(p.setName(new Name("/localhop/nfd/rib/register")),p.setInterestLifetimeMilliseconds(4E3));p.getName().append(l.wireEncode(TlvWireFormat.get()));m.nodeMakeCommandInterest(p,g,h,TlvWireFormat.get(),function(){var d=new Face.RegisterResponse(b,e,f,a,m,c);m.reconnectAndExpressInterest(null,p,d.onData.bind(d),d.onTimeout.bind(d),null,k)})},function(a){0<LOG&&console.log("Error in Transport.isLocal: "+a);if(e)try{e(b)}catch(c){console.log("Error in onRegisterFailed: "+NdnCommon.getErrorWithStackTrace(c))}})};
+Face.prototype.removeRegisteredPrefix=function(a){this.registeredPrefixTable_.removeRegisteredPrefix(a)};Face.prototype.setInterestFilter=function(a,b){var c=this.getNextEntryId();this.interestFilterTable_.setInterestFilter(c,new InterestFilter(a),b,this);return c};Face.prototype.unsetInterestFilter=function(a){this.interestFilterTable_.unsetInterestFilter(a)};
+Face.prototype.putData=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=a.wireEncode(b);if(c.size()>Face.getMaxNdnPacketSize())throw Error("The encoded Data packet size exceeds the maximum limit getMaxNdnPacketSize()");this.transport.send(c.buf())};Face.prototype.send=function(a){if(a.length>Face.getMaxNdnPacketSize())throw Error("The encoded packet size exceeds the maximum limit getMaxNdnPacketSize()");this.transport.send(a)};
+Face.prototype.isLocal=function(a,b){null==this.connectionInfo?a(!1):this.transport.isLocal(this.connectionInfo,a,b)};
+Face.prototype.onReceivedElement=function(a){3<LOG&&console.log("Complete element received. Length "+a.length+". Start decoding.");var b=null;a[0]==Tlv.LpPacket_LpPacket&&(b=new LpPacket,TlvWireFormat.get().decodeLpPacket(b,a,!1),a=b.getFragmentWireEncoding().buf());var c=null,d=null;if(a[0]==Tlv.Interest||a[0]==Tlv.Data){var e=new TlvDecoder(a);e.peekType(Tlv.Interest,a.length)?(c=new Interest,c.wireDecode(a,TlvWireFormat.get()),null!=b&&c.setLpPacket(b)):e.peekType(Tlv.Data,a.length)&&(d=new Data,
+d.wireDecode(a,TlvWireFormat.get()),null!=b&&d.setLpPacket(b))}if(null!==b&&(b.setFragmentWireEncoding(new Blob),b=NetworkNack.getFirstHeader(b),null!=b)){if(null==c)return;d=[];this.pendingInterestTable_.extractEntriesForNackInterest(c,d);for(a=0;a<d.length;++a){c=d[a];try{c.getOnNetworkNack()(c.getInterest(),b)}catch(f){console.log("Error in onNetworkNack: "+NdnCommon.getErrorWithStackTrace(f))}}return}if(null!==c)for(3<LOG&&console.log("Interest packet received."),d=[],this.interestFilterTable_.getMatchedFilters(c,
+d),a=0;a<d.length;++a){b=d[a];3<LOG&&console.log("Found interest filter for "+c.getName().toUri());try{b.getOnInterest()(b.getFilter().getPrefix(),c,this,b.getInterestFilterId(),b.getFilter())}catch(g){console.log("Error in onInterest: "+NdnCommon.getErrorWithStackTrace(g))}}else if(null!==d)for(3<LOG&&console.log("Data packet received."),b=[],this.pendingInterestTable_.extractEntriesForExpressedInterest(d,b),a=0;a<b.length;++a){c=b[a];try{c.getOnData()(c.getInterest(),d)}catch(h){console.log("Error in onData: "+
+NdnCommon.getErrorWithStackTrace(h))}}};
+Face.prototype.connectAndExecute=function(a){var b=this.getConnectionInfo();if(null==b)console.log("ERROR: No more connectionInfo from getConnectionInfo"),this.host=this.host=this.connectionInfo=null;else if(b.equals(this.connectionInfo))console.log("ERROR: The host returned by getConnectionInfo is not alive: "+this.connectionInfo.toString());else{this.connectionInfo=b;0<LOG&&console.log("connectAndExecute: trying host from getConnectionInfo: "+this.connectionInfo.toString());this.host=this.connectionInfo.host;
+this.host=this.connectionInfo.port;b=new Interest(new Name("/"));b.setInterestLifetimeMilliseconds(4E3);var c=this,d=setTimeout(function(){0<LOG&&console.log("connectAndExecute: timeout waiting for host "+c.host);c.connectAndExecute(a)},3E3);this.reconnectAndExpressInterest(null,b,function(b,f){clearTimeout(d);0<LOG&&console.log("connectAndExecute: connected to host "+c.host);a()},function(a){},null,WireFormat.getDefaultWireFormat())}};
+Face.prototype.closeByTransport=function(){this.readyStatus=Face.CLOSED;this.onclose()};Face.nonceTemplate_=new Blob(new Buffer(4),!1);
+(function(a,b,c){function d(a,b){return"object"!=typeof b&&(b=b()),Object.keys(b).forEach(function(c){a[c]=b[c]}),a}function e(a){return{from:function(b){return a.prototype=Object.create(b.prototype),a.prototype.constructor=a,{extend:function(c){d(a.prototype,"object"!=typeof c?c(b.prototype):c)}}}}}function f(a,b){return b(a)}function g(a,b){function u(a){this._cfg={version:a,storesSource:null,dbschema:{},tables:{},contentUpgrade:null};this.stores({})}function m(a,b,d,e){var g,h,da,k,ra;if(0===a)Object.keys(F).forEach(function(a){W(b,
+a,F[a].primKey,F[a].indexes)}),g=v._createTransaction(H,R,F),g.idbtrans=b,g.idbtrans.onerror=G(d,["populating database"]),g.on("error").subscribe(d),r.newPSD(function(){r.PSD.trans=g;try{v.on("populate").fire(g)}catch(a){e.onerror=b.onerror=function(a){a.preventDefault()};try{b.abort()}catch(c){}b.db.close();d(a)}});else{if(h=[],da=S.filter(function(b){return b._cfg.version===a})[0],!da)throw new y("Dexie specification of currently installed DB version is missing");F=v._dbSchema=da._cfg.dbschema;
+k=!1;da=S.filter(function(b){return b._cfg.version>a});da.forEach(function(a){var e=F,g=a._cfg.dbschema;sa(e,b);sa(g,b);F=v._dbSchema=g;e=ja(e,g);e.add.forEach(function(a){h.push(function(b,c){W(b,a[0],a[1].primKey,a[1].indexes);c()})});e.change.forEach(function(a){if(a.recreate)throw new y("Not yet support for changing primary key");h.push(function(b,c){var d=b.objectStore(a.name);a.add.forEach(function(a){A(d,a)});a.change.forEach(function(a){d.deleteIndex(a.name);A(d,a)});a.del.forEach(function(a){d.deleteIndex(a)});
+c()})});a._cfg.contentUpgrade&&h.push(function(b,c){var e,h;k=!0;e=v._createTransaction(H,[].slice.call(b.db.objectStoreNames,0),g);e.idbtrans=b;h=0;e._promise=f(e._promise,function(a){return function(b,d,e){function f(a){return function(){a.apply(this,arguments);0==--h&&c()}}return++h,a.call(this,b,function(a,b){arguments[0]=f(a);arguments[1]=f(b);d.apply(this,arguments)},e)}});b.onerror=G(d,["running upgrader function for version",a._cfg.version]);e.on("error").subscribe(d);a._cfg.contentUpgrade(e);
+0===h&&c()});k&&(0<=navigator.userAgent.indexOf("Trident")||0<=navigator.userAgent.indexOf("MSIE"))||h.push(function(a,b){for(var d,e=0;e<a.db.objectStoreNames.length;++e)d=a.db.objectStoreNames[e],null!==g[d]&&g[d]!==c||a.db.deleteObjectStore(d);b()})});ra=function(){try{h.length?h.shift()(b,ra):s(F,b)}catch(a){e.onerror=b.onerror=function(a){a.preventDefault()};try{b.abort()}catch(c){}b.db.close();d(a)}};ra()}}function ja(a,b){var c={del:[],add:[],change:[]},d,e,f,g,h,k,n,u;for(d in a)b[d]||c.del.push(d);
+for(d in b)if(e=a[d],f=b[d],e)if(g={name:d,def:b[d],recreate:!1,del:[],add:[],change:[]},e.primKey.src!==f.primKey.src)g.recreate=!0,c.change.push(g);else{h=e.indexes.reduce(function(a,b){return a[b.name]=b,a},{});f=f.indexes.reduce(function(a,b){return a[b.name]=b,a},{});for(k in h)f[k]||g.del.push(k);for(k in f)n=h[k],u=f[k],n?n.src!==u.src&&g.change.push(u):g.add.push(u);(g.recreate||0<g.del.length||0<g.add.length||0<g.change.length)&&c.change.push(g)}else c.add.push([d,f]);return c}function W(a,
+b,c,d){var e=a.db.createObjectStore(b,c.keyPath?{keyPath:c.keyPath,autoIncrement:c.auto}:{autoIncrement:c.auto});return d.forEach(function(a){A(e,a)}),e}function s(a,b){Object.keys(a).forEach(function(c){b.db.objectStoreNames.contains(c)||W(b,c,a[c].primKey,a[c].indexes)})}function A(a,b){a.createIndex(b.name,b.keyPath,{unique:b.unique,multiEntry:b.multi})}function Ha(a,b){throw new y("Table "+b[0]+" not part of transaction. Original Scope Function Source: "+g.Promise.PSD.trans.scopeFunc.toString());
+}function T(a,b,c,d){this.name=a;this.schema=c;this.hook=N[a]?N[a].hook:K(null,{creating:[q,h],reading:[l,k],updating:[p,h],deleting:[M,h]});this._tpf=b;this._collClass=d||X}function ta(a,b,c,d){T.call(this,a,b,c,d||ua)}function va(a,b,c,d){function e(a,b,c,d){return f._promise(a,c,d)}var f=this,g,h;this.db=v;this.mode=a;this.storeNames=b;this.idbtrans=null;this.on=K(this,["complete","error"],"abort");this._reculock=0;this._blockedFuncs=[];this._psd=null;this.active=!0;this._dbschema=c;d&&(this.parent=
+d);this._tpf=e;this.tables=Object.create(wa);for(d=b.length-1;-1!==d;--d)g=b[d],h=v._tableFactory(a,c[g],e),this.tables[g]=h,this[g]||(this[g]=h)}function Y(a,b,c){this._ctx={table:a,index:":id"===b?null:b,collClass:a._collClass,or:c}}function X(a,b){var c=null,d=null,e;if(b)try{c=b()}catch(f){d=f}e=a._ctx;this._ctx={table:e.table,index:e.index,isPrimKey:!e.index||e.table.schema.primKey.keyPath&&e.index===e.table.schema.primKey.name,range:c,op:"openCursor",dir:"next",unique:"",algorithm:null,filter:null,
+isMatch:null,offset:0,limit:Infinity,error:d,or:e.or}}function ua(){X.apply(this,arguments)}function Ia(a,b){return a._cfg.version-b._cfg.version}function U(a,b,c,d,e,f){c.forEach(function(c){var g=v._tableFactory(d,e[c],b);a.forEach(function(a){a[c]||(f?Object.defineProperty(a,c,{configurable:!0,enumerable:!0,get:function(){var a=r.PSD&&r.PSD.trans;return a&&a.db===v?a.tables[c]:g}}):a[c]=g)})})}function ea(a){a.forEach(function(a){for(var b in a)a[b]instanceof T&&delete a[b]})}function ka(a,b,c,
+d,e,f){var g=r.PSD;f=f||k;a.onerror||(a.onerror=G(e));a.onsuccess=b?I(function(){var g=a.result,h;g?(h=function(){g["continue"]()},b(g,function(a){h=a},d,e)&&c(f(g.value),g,function(a){h=a}),h()):d()},e,g):I(function(){var b=a.result,e;b?(e=function(){b["continue"]()},c(f(b.value),b,function(a){e=a}),e()):d()},e,g)}function fa(a){var b=[];return a.split(",").forEach(function(a){a=a.trim();var c=a.replace("&","").replace("++","").replace("*",""),d=0!==c.indexOf("[")?c:a.substring(a.indexOf("[")+1,
+a.indexOf("]")).split("+");b.push(new Z(c,d||null,-1!==a.indexOf("&"),-1!==a.indexOf("*"),-1!==a.indexOf("++"),Array.isArray(d),-1!==d.indexOf(".")))}),b}function la(a,b){return a<b?-1:a>b?1:0}function Da(a,b){return a<b?1:a>b?-1:0}function Ea(a){return function(b,c){for(var d=0,e;;){if(e=a(b[d],c[d]),0!==e)return e;if(++d,d===b.length||d===c.length)return a(b.length,c.length)}}}function ma(a,b){return a?b?function(){return a.apply(this,arguments)&&b.apply(this,arguments)}:a:b}function Ja(){if(v.verno=
+D.version/10,v._dbSchema=F={},R=[].slice.call(D.objectStoreNames,0),0!==R.length){var a=D.transaction(xa(R),"readonly");R.forEach(function(b){for(var c,d=a.objectStore(b),e=d.keyPath,f=e&&"string"==typeof e&&-1!==e.indexOf("."),g=new Z(e,e||"",!1,!1,!!d.autoIncrement,e&&"string"!=typeof e,f),h=[],k=0;k<d.indexNames.length;++k)c=d.index(d.indexNames[k]),f=(e=c.keyPath)&&"string"==typeof e&&-1!==e.indexOf("."),c=new Z(c.name,e,!!c.unique,!!c.multiEntry,!1,e&&"string"!=typeof e,f),h.push(c);F[b]=new ya(b,
+g,h,{})});U([N],v._transPromiseFactory,Object.keys(F),H,F)}}function sa(a,b){for(var c,d,e,f,g=b.db.objectStoreNames,h=0;h<g.length;++h)for(c=g[h],d=b.objectStore(c),e=0;e<d.indexNames.length;++e){var k=d.indexNames[e],n=d.index(k).keyPath,n="string"==typeof n?n:"["+[].slice.call(n).join("+")+"]";a[c]&&(f=a[c].idxByName[n],f&&(f.name=k))}}var ca=b&&b.addons||g.addons,na=g.dependencies,ga=na.indexedDB,L=na.IDBKeyRange,oa=na.TypeError,y=na.Error,F=this._dbSchema={},S=[],R=[],N={},wa={},D=null,$=!0,
+V=null,ha=!1,H="readwrite",v=this,Q=[],aa=!1,ia=!!Fa();this.version=function(a){if(D)throw new y("Cannot add version when database is open");this.verno=Math.max(this.verno,a);var b=S.filter(function(b){return b._cfg.version===a})[0];return b?b:(b=new u(a),S.push(b),S.sort(Ia),b)};d(u.prototype,{stores:function(a){var b,c;return this._cfg.storesSource=this._cfg.storesSource?d(this._cfg.storesSource,a):a,b={},S.forEach(function(a){d(b,a._cfg.storesSource)}),c=this._cfg.dbschema={},this._parseStoresSpec(b,
+c),F=v._dbSchema=c,ea([N,v,wa]),U([wa],Ha,Object.keys(c),H,c),U([N,v,this._cfg.tables],v._transPromiseFactory,Object.keys(c),H,c,!0),R=Object.keys(c),this},upgrade:function(a){var b=this;return B(function(){a(v._createTransaction(H,Object.keys(b._cfg.dbschema),b._cfg.dbschema))}),this._cfg.contentUpgrade=a,this},_parseStoresSpec:function(a,b){Object.keys(a).forEach(function(c){if(null!==a[c]){var d={},e=fa(a[c]),f=e.shift();if(f.multi)throw new y("Primary key cannot be multi-valued");f.keyPath&&f.auto&&
+J(d,f.keyPath,0);e.forEach(function(a){if(a.auto)throw new y("Only primary key can be marked as autoIncrement (++)");if(!a.keyPath)throw new y("Index must have a name and cannot be an empty string");J(d,a.keyPath,a.compound?a.keyPath.map(function(){return""}):"")});b[c]=new ya(c,f,e,d)}})}});this._allTables=N;this._tableFactory=function(a,b,c){return"readonly"===a?new T(b.name,c,b,X):new ta(b.name,c,b)};this._createTransaction=function(a,b,c,d){return new va(a,b,c,d)};this._transPromiseFactory=function(a,
+b,c){var d,e;return!$||r.PSD&&r.PSD.letThrough?(e=v._createTransaction(a,b,F),e._promise(a,function(a,b){e.error(function(a){v.on("error").fire(a)});c(function(b){e.complete(function(){a(b)})},b,e)})):d=new r(function(e,f){Q.push({resume:function(){var g=v._transPromiseFactory(a,b,c);d.onuncatched=g.onuncatched;g.then(e,f)}})})};this._whenReady=function(a){return!$||r.PSD&&r.PSD.letThrough?new r(a):new r(function(b,c){B(function(){new r(function(){a(b,c)})});Q.push({resume:function(){a(b,c)}})})};
+this.verno=0;this.open=function(){return new r(function(b,c){function d(a){try{e.transaction.abort()}catch(b){}ha=!1;V=a;$=!1;c(V);Q.forEach(function(a){a.resume()});Q=[]}if(D||ha)throw new y("Database already opened or being opened");var e;try{if(V=null,ha=!0,0===S.length&&(aa=!0),!ga)throw new y("indexedDB API not found. If using IE10+, make sure to run your code on a server URL (not locally). If using Safari, make sure to include indexedDB polyfill.");e=aa?ga.open(a):ga.open(a,Math.round(10*v.verno));
+e.onerror=G(d,["opening database",a]);e.onblocked=function(a){v.on("blocked").fire(a)};e.onupgradeneeded=I(function(b){var c,f;aa&&!v._allowEmptyDB?(e.onerror=function(a){a.preventDefault()},e.transaction.abort(),e.result.close(),c=ga.deleteDatabase(a),c.onsuccess=c.onerror=function(){d(new y("Database '"+a+"' doesnt exist"))}):(e.transaction.onerror=G(d),f=b.oldVersion>Math.pow(2,62)?0:b.oldVersion,m(f/10,e.transaction,d,e))},d);e.onsuccess=I(function(){ha=!1;D=e.result;aa?Ja():0<D.objectStoreNames.length&&
+sa(F,D.transaction(xa(D.objectStoreNames),"readonly"));D.onversionchange=v.on("versionchange").fire;ia||za(function(b){if(-1===b.indexOf(a))return b.push(a)});r.newPSD(function(){function a(){$=!1;Q.forEach(function(a){a.resume()});Q=[];b()}r.PSD.letThrough=!0;try{var c=v.on.ready.fire();c&&"function"==typeof c.then?c.then(a,function(a){D.close();D=null;d(a)}):x(a)}catch(e){d(e)}})},d)}catch(f){d(f)}})};this.close=function(){D&&(D.close(),D=null,$=!0,V=null)};this["delete"]=function(){var b=arguments;
+return new r(function(c,d){function e(){v.close();var b=ga.deleteDatabase(a);b.onsuccess=function(){ia||za(function(b){var c=b.indexOf(a);if(0<=c)return b.splice(c,1)});c()};b.onerror=G(d,["deleting",a]);b.onblocked=function(){v.on("blocked").fire()}}if(0<b.length)throw new y("Arguments not allowed in db.delete()");ha?Q.push({resume:e}):e()})};this.backendDB=function(){return D};this.isOpen=function(){return null!==D};this.hasFailed=function(){return null!==V};this.dynamicallyOpened=function(){return aa};
+this.name=a;Object.defineProperty(this,"tables",{get:function(){return Object.keys(N).map(function(a){return N[a]})}});this.on=K(this,"error","populate","blocked",{ready:[O,h],versionchange:[w,h]});this.on.ready.subscribe=f(this.on.ready.subscribe,function(a){return function(b,c){function d(){return c||v.on.ready.unsubscribe(d),b.apply(this,arguments)}a.call(this,d);v.isOpen()&&($?Q.push({resume:d}):d())}});B(function(){v.on("populate").fire(v._createTransaction(H,R,F));v.on("error").fire(new y)});
+this.transaction=function(a,b,c){function d(b,g){var n=null,u,l,E;try{if(h)throw h;n=v._createTransaction(a,k,F,e);u=k.map(function(a){return n.tables[a]});u.push(n);E=0;r.newPSD(function(){r.PSD.trans=n;n.scopeFunc=c;e&&(n.idbtrans=e.idbtrans,n._promise=f(n._promise,function(a){return function(b,c,d){function e(a){return function(b){var c;return r._rootExec(function(){c=a(b);r._tickFinalize(function(){0==--E&&n.active&&(n.active=!1,n.on.complete.fire())})}),c}}return++E,a.call(this,b,function(a,
+b,d){return c(e(a),e(b),d)},d)}}));n.complete(function(){b(l)});n.error(function(a){n.idbtrans&&(n.idbtrans.onerror=Ga);try{n.abort()}catch(b){}e&&(e.active=!1,e.on.error.fire(a));var c=g(a);e||c||v.on.error.fire(a)});r._rootExec(function(){l=c.apply(n,u)})});(!n.idbtrans||e&&0===E)&&n._nop()}catch(m){n&&n.idbtrans&&(n.idbtrans.onerror=Ga),n&&n.abort(),e&&e.on.error.fire(m),x(function(){g(m)||v.on("error").fire(m)})}}var e,g;b=[].slice.call(arguments,1,arguments.length-1);c=arguments[arguments.length-
+1];(e=r.PSD&&r.PSD.trans)&&e.db===v&&-1===a.indexOf("!")||(e=null);g=-1!==a.indexOf("?");a=a.replace("!","").replace("?","");var h=null,k=(Array.isArray(b[0])?b.reduce(function(a,b){return a.concat(b)}):b).map(function(a){return"string"==typeof a?a:(a instanceof T||(h=h||new oa("Invalid type. Arguments following mode must be instances of Table or String")),a.name)});return"r"==a||"readonly"==a?a="readonly":"rw"==a||a==H?a=H:h=new y("Invalid transaction mode: "+a),e&&(h||(e&&"readonly"===e.mode&&a===
+H&&(g?e=null:h=h||new y("Cannot enter a sub-transaction with READWRITE mode when parent transaction is READONLY")),e&&k.forEach(function(a){e.tables.hasOwnProperty(a)||(g?e=null:h=h||new y("Table "+a+" not included in parent transaction. Parent Transaction function: "+e.scopeFunc.toString()))}))),e?e._promise(a,d,"lock"):v._whenReady(d)};this.table=function(a){if(!aa&&!N.hasOwnProperty(a))throw new y("Table does not exist");return N[a]};d(T.prototype,function(){function a(){throw new y("Current Transaction is READONLY");
+}return{_trans:function(a,b,c){return this._tpf(a,[this.name],b,c)},_idbstore:function(a,b,c){var d=this;return this._tpf(a,[this.name],function(a,c,e){b(a,c,e.idbtrans.objectStore(d.name),e)},c)},get:function(a,b){var c=this;return B(function(){b(c.schema.instanceTemplate)}),this._idbstore("readonly",function(b,d,e){var f=e.get(a);f.onerror=G(d,["getting",a,"from",c.name]);f.onsuccess=function(){b(c.hook.reading.fire(f.result))}}).then(b)},where:function(a){return new Y(this,a)},count:function(a){return this.toCollection().count(a)},
+offset:function(a){return this.toCollection().offset(a)},limit:function(a){return this.toCollection().limit(a)},reverse:function(){return this.toCollection().reverse()},filter:function(a){return this.toCollection().and(a)},each:function(a){var b=this;return B(function(){a(b.schema.instanceTemplate)}),this._idbstore("readonly",function(c,d,e){e=e.openCursor();e.onerror=G(d,["calling","Table.each()","on",b.name]);ka(e,null,a,c,d,b.hook.reading.fire)})},toArray:function(a){var b=this;return B(function(){a([b.schema.instanceTemplate])}),
+this._idbstore("readonly",function(a,c,d){var e=[];d=d.openCursor();d.onerror=G(c,["calling","Table.toArray()","on",b.name]);ka(d,null,function(a){e.push(a)},function(){a(e)},c,b.hook.reading.fire)}).then(a)},orderBy:function(a){return new this._collClass(new Y(this,a))},toCollection:function(){return new this._collClass(new Y(this))},mapToClass:function(a,b){var c,d;return this.schema.mappedClass=a,c=Object.create(a.prototype),this.schema.primKey.keyPath&&(J(c,this.schema.primKey.keyPath,this.schema.primKey.auto?
+0:""),Ba(a.prototype,this.schema.primKey.keyPath)),b&&Aa(c,b),this.schema.instanceTemplate=c,d=Object.setPrototypeOf?function(b){return b?(Object.setPrototypeOf(b,a.prototype),b):b}:function(b){var c,d;if(!b)return b;c=Object.create(a.prototype);for(d in b)b.hasOwnProperty(d)&&(c[d]=b[d]);return c},this.schema.readHook&&this.hook.reading.unsubscribe(this.schema.readHook),this.schema.readHook=d,this.hook("reading",d),a},defineClass:function(a){return this.mapToClass(g.defineClass(a),a)},add:a,put:a,
+"delete":a,clear:a,update:a}});e(ta).from(T).extend(function(){return{add:function(a,b){var d=this,e=this.hook.creating.fire;return this._idbstore(H,function(f,g,k,n){var u={},l,E,m;e!==h&&(l=b||(k.keyPath?P(a,k.keyPath):c),E=e.call(u,l,a,n),l===c&&E!==c&&(k.keyPath?J(a,k.keyPath,E):b=E));m=b?k.add(a,b):k.add(a);m.onerror=G(function(a){if(u.onerror)u.onerror(a);return g(a)},["adding",a,"into",d.name]);m.onsuccess=function(b){var c=k.keyPath;if(c&&J(a,c,b.target.result),u.onsuccess)u.onsuccess(b.target.result);
+f(m.result)}})},put:function(a,b){var d=this,e=this.hook.updating.fire;return this.hook.creating.fire!==h||e!==h?this._trans(H,function(e,f,g){var h=b||d.schema.primKey.keyPath&&P(a,d.schema.primKey.keyPath);h===c?g.tables[d.name].add(a).then(e,f):(g._lock(),a=ba(a),g.tables[d.name].where(":id").equals(h).modify(function(){this.value=a}).then(function(c){return 0===c?g.tables[d.name].add(a,b):h})["finally"](function(){g._unlock()}).then(e,f))}):this._idbstore(H,function(c,e,f){var g=b?f.put(a,b):
+f.put(a);g.onerror=G(e,["putting",a,"into",d.name]);g.onsuccess=function(b){var d=f.keyPath;d&&J(a,d,b.target.result);c(g.result)}})},"delete":function(a){return this.hook.deleting.subscribers.length?this.where(":id").equals(a)["delete"]():this._idbstore(H,function(b,c,d){var e=d["delete"](a);e.onerror=G(c,["deleting",a,"from",d.name]);e.onsuccess=function(){b(e.result)}})},clear:function(){return this.hook.deleting.subscribers.length?this.toCollection()["delete"]():this._idbstore(H,function(a,b,
+c){var d=c.clear();d.onerror=G(b,["clearing",c.name]);d.onsuccess=function(){a(d.result)}})},update:function(a,b){if("object"!=typeof b||Array.isArray(b))throw new y("db.update(keyOrObject, modifications). modifications must be an object.");if("object"!=typeof a||Array.isArray(a))return this.where(":id").equals(a).modify(b);Object.keys(b).forEach(function(c){J(a,c,b[c])});var d=P(a,this.schema.primKey.keyPath);return d===c&&r.reject(new y("Object does not contain its primary key")),this.where(":id").equals(d).modify(b)}}});
+d(va.prototype,{_lock:function(){return++this._reculock,1===this._reculock&&r.PSD&&(r.PSD.lockOwnerFor=this),this},_unlock:function(){if(0==--this._reculock)for(r.PSD&&(r.PSD.lockOwnerFor=null);0<this._blockedFuncs.length&&!this._locked();){var a=this._blockedFuncs.shift();try{a()}catch(b){}}return this},_locked:function(){return this._reculock&&(!r.PSD||r.PSD.lockOwnerFor!==this)},_nop:function(a){this.tables[this.storeNames[0]].get(0).then(a)},_promise:function(a,b,c){var d=this;return r.newPSD(function(){var e;
+return d._locked()?e=new r(function(e,f){d._blockedFuncs.push(function(){d._promise(a,b,c).then(e,f)})}):(e=d.active?new r(function(e,f){if(!d.idbtrans&&a){if(!D)throw V?new y("Database not open. Following error in populate, ready or upgrade function made Dexie.open() fail: "+V):new y("Database not open");var h=d.idbtrans=D.transaction(xa(d.storeNames),d.mode);h.onerror=function(a){d.on("error").fire(a&&a.target.error);a.preventDefault();d.abort()};h.onabort=function(a){d.active=!1;d.on("abort").fire(a)};
+h.oncomplete=function(a){d.active=!1;d.on("complete").fire(a)}}c&&d._lock();try{b(e,f,d)}catch(k){g.ignoreTransaction(function(){d.on("error").fire(k)}),d.abort(),f(k)}}):r.reject(Ka(new y("Transaction is inactive. Original Scope Function Source: "+d.scopeFunc.toString()))),d.active&&c&&e["finally"](function(){d._unlock()})),e.onuncatched=function(a){g.ignoreTransaction(function(){d.on("error").fire(a)});d.abort()},e})},complete:function(a){return this.on("complete",a)},error:function(a){return this.on("error",
+a)},abort:function(){if(this.idbtrans&&this.active)try{this.active=!1,this.idbtrans.abort(),this.on.error.fire(new y("Transaction Aborted"))}catch(a){}},table:function(a){if(!this.tables.hasOwnProperty(a))throw new y("Table "+a+" not in transaction");return this.tables[a]}});d(Y.prototype,function(){function a(b,c){try{throw c;}catch(d){b._ctx.error=d}return b}function b(a){return Array.prototype.slice.call(1===a.length&&Array.isArray(a[0])?a[0]:a)}function c(a){return"next"===a?function(a){return a.toUpperCase()}:
+function(a){return a.toLowerCase()}}function d(a){return"next"===a?function(a){return a.toLowerCase()}:function(a){return a.toUpperCase()}}function e(a,b,c,d,f,g){for(var h,k=Math.min(a.length,d.length),n=-1,u=0;u<k;++u){if(h=b[u],h!==d[u])return 0>f(a[u],c[u])?a.substr(0,u)+c[u]+c.substr(u+1):0>f(a[u],d[u])?a.substr(0,u)+d[u]+c.substr(u+1):0<=n?a.substr(0,n)+b[n]+c.substr(n+1):null;0>f(a[u],h)&&(n=u)}return k<d.length&&"next"===g?a+c.substr(a.length):k<a.length&&"prev"===g?a.substr(0,c.length):0>
+n?null:a.substr(0,n)+d[n]+c.substr(n+1)}function f(a,b,g){function h(a){k=c(a);n=d(a);u="next"===a?la:Da;l=k(g);E=n(g);m=a}var k,n,u,l,E,m;h("next");a._ondirectionchange=function(a){h(a)};a._addAlgorithm(function(a,c,d){var f=a.key,g,h;return"string"!=typeof f?!1:(g=n(f),b(g,E)?(c(function(){a["continue"]()}),!0):(h=e(f,g,l,E,u,m),h?c(function(){a["continue"](h)}):c(d),!1))})}return{between:function(a,b,c,d){return(c=!1!==c,d=!0===d,a>b||a===b&&!(!c&&!d||c&&d))?(new this._ctx.collClass(this,function(){return L.only(a)})).limit(0):
+new this._ctx.collClass(this,function(){return L.bound(a,b,!c,!d)})},equals:function(a){return new this._ctx.collClass(this,function(){return L.only(a)})},above:function(a){return new this._ctx.collClass(this,function(){return L.lowerBound(a,!0)})},aboveOrEqual:function(a){return new this._ctx.collClass(this,function(){return L.lowerBound(a)})},below:function(a){return new this._ctx.collClass(this,function(){return L.upperBound(a,!0)})},belowOrEqual:function(a){return new this._ctx.collClass(this,
+function(){return L.upperBound(a)})},startsWith:function(b){return"string"!=typeof b?a(new this._ctx.collClass(this),new oa("String expected")):this.between(b,b+String.fromCharCode(65535),!0,!0)},startsWithIgnoreCase:function(b){if("string"!=typeof b)return a(new this._ctx.collClass(this),new oa("String expected"));if(""===b)return this.startsWith(b);var c=new this._ctx.collClass(this,function(){return L.bound(b.toUpperCase(),b.toLowerCase()+String.fromCharCode(65535))});return f(c,function(a,b){return 0===
+a.indexOf(b)},b),c._ondirectionchange=function(){a(c,new y("reverse() not supported with WhereClause.startsWithIgnoreCase()"))},c},equalsIgnoreCase:function(b){if("string"!=typeof b)return a(new this._ctx.collClass(this),new oa("String expected"));var c=new this._ctx.collClass(this,function(){return L.bound(b.toUpperCase(),b.toLowerCase())});return f(c,function(a,b){return a===b},b),c},anyOf:function(){var a=this._ctx,c=a.table.schema,d=(a=a.index?c.idxByName[a.index]:c.primKey)&&a.compound,e=b(arguments),
+f=d?Ea(la):la,g,h;return(e.sort(f),0===e.length)?(new this._ctx.collClass(this,function(){return L.only("")})).limit(0):(g=new this._ctx.collClass(this,function(){return L.bound(e[0],e[e.length-1])}),g._ondirectionchange=function(a){f="next"===a?la:Da;d&&(f=Ea(f));e.sort(f)},h=0,g._addAlgorithm(function(a,b,c){for(var d=a.key;0<f(d,e[h]);)if(++h,h===e.length)return b(c),!1;return 0===f(d,e[h])?(b(function(){a["continue"]()}),!0):(b(function(){a["continue"](e[h])}),!1)}),g)}}});d(X.prototype,function(){function a(b,
+c){b.filter=ma(b.filter,c)}function b(a,c){a.isMatch=ma(a.isMatch,c)}function c(a,b){if(a.isPrimKey)return b;var d=a.table.schema.idxByName[a.index];if(!d)throw new y("KeyPath "+a.index+" on object store "+b.name+" is not indexed");return a.isPrimKey?b:b.index(d.name)}function d(a,b){return c(a,b)[a.op](a.range||null,a.dir+a.unique)}function e(a,b,c,f,g){a.or?function(){function e(){2==++u&&c()}function h(a,c,d){if(!k||k(c,d,e,f)){var g=c.primaryKey.toString();n.hasOwnProperty(g)||(n[g]=!0,b(a,c,
+d))}}var k=a.filter,n={},u=0;a.or._iterate(h,e,f,g);ka(d(a,g),a.algorithm,h,e,f,a.table.hook.reading.fire)}():ka(d(a,g),ma(a.algorithm,a.filter),b,c,f,a.table.hook.reading.fire)}function f(a){return a.table.schema.instanceTemplate}return{_read:function(a,b){var c=this._ctx;return c.error?c.table._trans(null,function(a,b){b(c.error)}):c.table._idbstore("readonly",a).then(b)},_write:function(a){var b=this._ctx;return b.error?b.table._trans(null,function(a,c){c(b.error)}):b.table._idbstore(H,a,"locked")},
+_addAlgorithm:function(a){var b=this._ctx;b.algorithm=ma(b.algorithm,a)},_iterate:function(a,b,c,d){return e(this._ctx,a,b,c,d)},each:function(a){var b=this._ctx;return B(function(){a(f(b))}),this._read(function(c,d,f){e(b,a,c,d,f)})},count:function(a){var b,d,f;return B(function(){a(0)}),b=this,d=this._ctx,d.filter||d.algorithm||d.or?(f=0,this._read(function(a,b,c){e(d,function(){return++f,!1},function(){a(f)},b,c)},a)):this._read(function(a,e,f){f=c(d,f);f=d.range?f.count(d.range):f.count();f.onerror=
+G(e,["calling","count()","on",b.name]);f.onsuccess=function(b){a(Math.min(b.target.result,Math.max(0,d.limit-d.offset)))}},a)},sortBy:function(a,b){function c(a,b){return b?c(a[h[b]],b-1):a[k]}function d(a,b){var e=c(a,n),f=c(b,n);return e<f?-g:e>f?g:0}var e=this._ctx,g;B(function(){b([f(e)])});var h=a.split(".").reverse(),k=h[0],n=h.length-1;return g="next"===this._ctx.dir?1:-1,this.toArray(function(a){return a.sort(d)}).then(b)},toArray:function(a){var b=this._ctx;return B(function(){a([f(b)])}),
+this._read(function(a,c,d){var f=[];e(b,function(a){f.push(a)},function(){a(f)},c,d)},a)},offset:function(b){var c=this._ctx;return 0>=b?this:(c.offset+=b,c.or||c.algorithm||c.filter?a(c,function(){return 0>--b}):a(c,function(a,c){return 0===b?!0:1===b?(--b,!1):(c(function(){a.advance(b);b=0}),!1)}),this)},limit:function(b){return this._ctx.limit=Math.min(this._ctx.limit,b),a(this._ctx,function(a,c,d){return 0>=--b&&c(d),0<=b}),this},until:function(b,c){var d=this._ctx;return B(function(){b(f(d))}),
+a(this._ctx,function(a,d,e){return b(a.value)?(d(e),c):!0}),this},first:function(a){var b=this;return B(function(){a(f(b._ctx))}),this.limit(1).toArray(function(a){return a[0]}).then(a)},last:function(a){return this.reverse().first(a)},and:function(c){var d=this;return B(function(){c(f(d._ctx))}),a(this._ctx,function(a){return c(a.value)}),b(this._ctx,c),this},or:function(a){return new Y(this._ctx.table,a,this)},reverse:function(){return this._ctx.dir="prev"===this._ctx.dir?"next":"prev",this._ondirectionchange&&
+this._ondirectionchange(this._ctx.dir),this},desc:function(){return this.reverse()},eachKey:function(a){var b=this,c=this._ctx;return B(function(){a(f(b._ctx)[b._ctx.index])}),c.isPrimKey||(c.op="openKeyCursor"),this.each(function(b,c){a(c.key,c)})},eachUniqueKey:function(a){return this._ctx.unique="unique",this.eachKey(a)},keys:function(a){var b,c,d;return B(function(){a([f(c)[b._ctx.index]])}),b=this,c=this._ctx,c.isPrimKey||(c.op="openKeyCursor"),d=[],this.each(function(a,b){d.push(b.key)}).then(function(){return d}).then(a)},
+uniqueKeys:function(a){return this._ctx.unique="unique",this.keys(a)},firstKey:function(a){return this.limit(1).keys(function(a){return a[0]}).then(a)},lastKey:function(a){return this.reverse().firstKey(a)},distinct:function(){var b={};return a(this._ctx,function(a){a=a.primaryKey.toString();var c=b.hasOwnProperty(a);return b[a]=!0,!c}),this}}});e(ua).from(X).extend({modify:function(a){var b=this,c=this._ctx,e=c.table.hook,f=e.updating.fire,g=e.deleting.fire;return B(function(){"function"==typeof a&&
+a.call({value:c.table.schema.instanceTemplate},c.table.schema.instanceTemplate)}),this._write(function(e,k,n,u){function l(a){return a&&(r.push(a),fa.push(W)),k(new pa("Error modifying one or more objects",r,p,fa))}function E(){ja&&p+r.length===q&&(0<r.length?l():e(p))}var m,U,Ca,ea;"function"==typeof a?m=f===h&&g===h?a:function(b){var c=ba(b),d,e;if(!1===a.call(this,b))return!1;this.hasOwnProperty("value")?(d=La(c,this.value),e=f.call(this,d,this.primKey,c,u),e&&(b=this.value,Object.keys(e).forEach(function(a){J(b,
+a,e[a])}))):g.call(this,this.primKey,b,u)}:f===h?(U=Object.keys(a),Ca=U.length,m=function(b){for(var c,d,e=!1,f=0;f<Ca;++f)c=U[f],d=a[c],P(b,c)!==d&&(J(b,c,d),e=!0);return e}):(ea=a,a=qa(ea),m=function(b){var c=!1,e=f.call(this,a,this.primKey,ba(b),u);return e&&d(a,e),Object.keys(a).forEach(function(d){var e=a[d];P(b,d)!==e&&(J(b,d,e),c=!0)}),e&&(a=qa(ea)),c});var q=0,p=0,ja=!1,r=[],fa=[],W=null;b._iterate(function(a,b){var d,e,f;if(W=b.primaryKey,d={primKey:b.primaryKey,value:a},!1!==m.call(d,a))f=
+(e=!d.hasOwnProperty("value"))?b["delete"]():b.update(d.value),++q,f.onerror=G(function(a){if(r.push(a),fa.push(d.primKey),d.onerror)d.onerror(a);return E(),!0},e?["deleting",a,"from",c.table.name]:["modifying",a,"on",c.table.name]),f.onsuccess=function(){if(d.onsuccess)d.onsuccess(d.value);++p;E()};else if(d.onsuccess)d.onsuccess(d.value)},function(){ja=!0;E()},l,n)})},"delete":function(){return this.modify(function(){delete this.value})}});d(this,{Collection:X,Table:T,Transaction:va,Version:u,WhereClause:Y,
+WriteableCollection:ua,WriteableTable:ta});(function(){v.on("versionchange",function(){v.close();v.on("error").fire(new y("Database version changed by other database connection."))})})();ca.forEach(function(a){a(v)})}function h(){}function k(a){return a}function l(a,b){return a===k?b:function(c){return b(a(c))}}function m(a,b){return function(){a.apply(this,arguments);b.apply(this,arguments)}}function q(a,b){return a===h?b:function(){var d=a.apply(this,arguments),e,f,g;return d!==c&&(arguments[0]=
+d),e=this.onsuccess,f=this.onerror,delete this.onsuccess,delete this.onerror,g=b.apply(this,arguments),e&&(this.onsuccess=this.onsuccess?m(e,this.onsuccess):e),f&&(this.onerror=this.onerror?m(f,this.onerror):f),g!==c?g:d}}function p(a,b){return a===h?b:function(){var e=a.apply(this,arguments),f,g,h;return e!==c&&d(arguments[0],e),f=this.onsuccess,g=this.onerror,delete this.onsuccess,delete this.onerror,h=b.apply(this,arguments),f&&(this.onsuccess=this.onsuccess?m(f,this.onsuccess):f),g&&(this.onerror=
+this.onerror?m(g,this.onerror):g),e===c?h===c?c:h:h===c?e:d(e,h)}}function s(a,b){return a===h?b:function(){return!1===a.apply(this,arguments)?!1:b.apply(this,arguments)}}function w(a,b){return a===h?b:function(){return!1===b.apply(this,arguments)?!1:a.apply(this,arguments)}}function M(a,b){return a===h?b:function(){a.apply(this,arguments);b.apply(this,arguments)}}function O(a,b){return a===h?b:function(){var c=a.apply(this,arguments),d,e;return c&&"function"==typeof c.then?(d=this,e=arguments,c.then(function(){return b.apply(d,
+e)})):b.apply(this,arguments)}}function K(b){function c(a,b,f){if(Array.isArray(a))return e(a);if("object"==typeof a)return d(a);b||(b=s);f||(f=h);var n={subscribers:[],fire:f,subscribe:function(a){n.subscribers.push(a);n.fire=b(n.fire,a)},unsubscribe:function(a){n.subscribers=n.subscribers.filter(function(b){return b!==a});n.fire=n.subscribers.reduce(b,f)}};return g[a]=k[a]=n,n}function d(b){Object.keys(b).forEach(function(d){var e=b[d],f;if(Array.isArray(e))c(d,b[d][0],b[d][1]);else if("asap"===
+e)f=c(d,null,function(){var b=arguments;f.subscribers.forEach(function(c){x(function(){c.apply(a,b)})})}),f.subscribe=function(a){-1===f.subscribers.indexOf(a)&&f.subscribers.push(a)},f.unsubscribe=function(a){a=f.subscribers.indexOf(a);-1!==a&&f.subscribers.splice(a,1)};else throw Error("Invalid event config");})}function e(a){function b(){if(d)return!1;d=!0}var d=!1;a.forEach(function(a){c(a).subscribe(b)})}var f=arguments,g={},k=function(a,c){if(c){var d=[].slice.call(arguments,1),e=g[a];return e.subscribe.apply(e,
+d),b}if("string"==typeof a)return g[a]},l,m;k.addEventType=c;l=1;for(m=f.length;l<m;++l)c(f[l]);return k}function x(b){a.setImmediate?setImmediate(b):setTimeout(b,0)}function A(a){a=setTimeout(a,1E3);clearTimeout(a)}function I(a,b,c){return function(){var d=r.PSD;r.PSD=c;try{a.apply(this,arguments)}catch(e){b(e)}finally{r.PSD=d}}}function P(a,b){var d,e,f,g;if(a.hasOwnProperty(b))return a[b];if(!b)return a;if("string"!=typeof b){d=[];e=0;for(f=b.length;e<f;++e)g=P(a,b[e]),d.push(g);return d}return(d=
+b.indexOf("."),-1!==d)?(e=a[b.substr(0,d)],e===c?c:P(e,b.substr(d+1))):c}function J(a,b,d){var e,f,g,h;if(a&&b!==c)if("string"!=typeof b&&"length"in b){if(!("string"!=typeof d&&"length"in d))throw Error("Assertion failed");e=0;for(f=b.length;e<f;++e)J(a,b[e],d[e])}else e=b.indexOf("."),-1!==e?(f=b.substr(0,e),g=b.substr(e+1),""===g?d===c?delete a[f]:a[f]=d:(h=a[f],h||(h=a[f]={}),J(h,g,d))):d===c?delete a[b]:a[b]=d}function Ba(a,b){J(a,b,c)}function qa(a){var b={},c;for(c in a)a.hasOwnProperty(c)&&
+(b[c]=a[c]);return b}function ba(a){var b,c,d;if(!a||"object"!=typeof a)return a;if(Array.isArray(a))for(b=[],c=0,d=a.length;c<d;++c)b.push(ba(a[c]));else if(a instanceof Date)b=new Date,b.setTime(a.getTime());else for(c in b=a.constructor?Object.create(a.constructor.prototype):{},a)a.hasOwnProperty(c)&&(b[c]=ba(a[c]));return b}function La(a,b){var d={},e;for(e in a)a.hasOwnProperty(e)&&(b.hasOwnProperty(e)?a[e]!==b[e]&&JSON.stringify(a[e])!=JSON.stringify(b[e])&&(d[e]=b[e]):d[e]=c);for(e in b)b.hasOwnProperty(e)&&
+!a.hasOwnProperty(e)&&(d[e]=b[e]);return d}function ia(a){if("function"==typeof a)return new a;if(Array.isArray(a))return[ia(a[0])];if(a&&"object"==typeof a){var b={};return Aa(b,a),b}return a}function Aa(a,b){Object.keys(b).forEach(function(c){var d=ia(b[c]);a[c]=d})}function G(a,b){return function(c){var d=c&&c.target.error||Error(),e;return b&&(e=" occurred when "+b.map(function(a){switch(typeof a){case "function":return a();case "string":return a;default:return JSON.stringify(a)}}).join(" "),
+d.name?d.toString=function(){return d.name+e+(d.message?". "+d.message:"")}:d+=e),a(d),c&&(c.stopPropagation&&c.stopPropagation(),c.preventDefault&&c.preventDefault()),!1}}function Ka(a){try{throw a;}catch(b){return b}}function Ga(a){a.preventDefault()}function za(a){var b,c=g.dependencies.localStorage;if(!c)return a([]);try{b=JSON.parse(c.getItem("Dexie.DatabaseNames")||"[]")}catch(d){b=[]}a(b)&&c.setItem("Dexie.DatabaseNames",JSON.stringify(b))}function Z(a,b,c,d,e,f,g){this.name=a;this.keyPath=
+b;this.unique=c;this.multi=d;this.auto=e;this.compound=f;this.dotted=g;a="string"==typeof b?b:b&&"["+[].join.call(b,"+")+"]";this.src=(c?"&":"")+(d?"*":"")+(e?"++":"")+a}function ya(a,b,c,d){this.name=a;this.primKey=b||new Z;this.indexes=c||[new Z];this.instanceTemplate=d;this.mappedClass=null;this.idxByName=c.reduce(function(a,b){return a[b.name]=b,a},{})}function pa(a,b,c,d){this.name="ModifyError";this.failures=b;this.failedKeys=d;this.successCount=c;this.message=b.join("\n")}function xa(a){return 1===
+a.length?a[0]:a}function Fa(){var a=g.dependencies.indexedDB,b=a&&(a.getDatabaseNames||a.webkitGetDatabaseNames);return b&&b.bind(a)}var r=function(){function b(a){x.push([a,p.call(arguments,1)])}function c(){var b=x,d,e,f;x=[];d=0;for(e=b.length;d<e;++d)f=b[d],f[0].apply(a,f[1])}function d(a){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof a)throw new TypeError("not a function");this._value=this._state=null;this._deferreds=[];this._catched=
+!1;var b=this,c=!0;this._PSD=d.PSD;try{q(this,a,function(a){c?s(g,b,a):g(b,a)},function(a){return c?(s(k,b,a),!1):k(b,a)})}finally{c=!1}}function e(a,g){var h,k,l,m,q,p;if(null===a._state)a._deferreds.push(g);else{if(h=a._state?g.onFulfilled:g.onRejected,null===h)return(a._state?g.resolve:g.reject)(a._value);l=w;w=!1;s=b;try{m=d.PSD,d.PSD=a._PSD,k=h(a._value),a._state||k&&"function"==typeof k.then&&!1===k._state||f(a),g.resolve(k)}catch(B){if(q=g.reject(B),!q&&a.onuncatched)try{a.onuncatched(B)}catch(G){}}finally{if(d.PSD=
+m,l){do{for(;0<x.length;)c();if(p=A.pop(),p)try{p()}catch(I){}}while(0<A.length||0<x.length);s=r;w=!0}}}}function f(a){a._catched=!0;a._parent&&f(a._parent)}function g(a,b){var c=d.PSD;d.PSD=a._PSD;try{if(b===a)throw new TypeError("A promise cannot be resolved with itself.");!b||"object"!=typeof b&&"function"!=typeof b||"function"!=typeof b.then?(a._state=!0,a._value=b,l.call(a)):q(a,function(a,c){b.then(a,c)},function(b){g(a,b)},function(b){k(a,b)})}catch(e){k(e)}finally{d.PSD=c}}function k(a,b){var c=
+d.PSD;if(d.PSD=a._PSD,a._state=!1,a._value=b,l.call(a),!a._catched)try{if(a.onuncatched)a.onuncatched(a._value);d.on.error.fire(a._value)}catch(e){}return d.PSD=c,a._catched}function l(){for(var a=0,b=this._deferreds.length;a<b;a++)e(this,this._deferreds[a]);this._deferreds=[]}function m(a,b,c,d){this.onFulfilled="function"==typeof a?a:null;this.onRejected="function"==typeof b?b:null;this.resolve=c;this.reject=d}function q(a,b,c,d){var e=!1;try{b(function(a){e||(e=!0,c(a))},function(b){return e?a._catched:
+(e=!0,d(b))})}catch(f){return e?void 0:d(f)}}var p=[].slice,r="undefined"==typeof setImmediate?function(b){var c=arguments;setTimeout(function(){b.apply(a,p.call(c,1))},0)}:setImmediate,s=r,w=!0,x=[],A=[];return d.on=K(null,"error"),d.all=function(){var a=Array.prototype.slice.call(1===arguments.length&&Array.isArray(arguments[0])?arguments[0]:arguments);return new d(function(b,c){function d(f,g){try{if(g&&("object"==typeof g||"function"==typeof g)){var h=g.then;if("function"==typeof h){h.call(g,
+function(a){d(f,a)},c);return}}a[f]=g;0==--e&&b(a)}catch(k){c(k)}}var e,f;if(0===a.length)return b([]);e=a.length;for(f=0;f<a.length;f++)d(f,a[f])})},d.prototype.then=function(a,b){var c=this,f=new d(function(d,f){null===c._state?e(c,new m(a,b,d,f)):s(e,c,new m(a,b,d,f))});return f._PSD=this._PSD,f.onuncatched=this.onuncatched,f._parent=this,f},d.prototype._then=function(a,b){e(this,new m(a,b,h,h))},d.prototype["catch"]=function(a){if(1===arguments.length)return this.then(null,a);var b=arguments[0],
+c=arguments[1];return"function"==typeof b?this.then(null,function(a){return a instanceof b?c(a):d.reject(a)}):this.then(null,function(a){return a&&a.name===b?c(a):d.reject(a)})},d.prototype["finally"]=function(a){return this.then(function(b){return a(),b},function(b){return a(),d.reject(b)})},d.prototype.onuncatched=null,d.resolve=function(a){var b=new d(function(){});return b._state=!0,b._value=a,b},d.reject=function(a){var b=new d(function(){});return b._state=!1,b._value=a,b},d.race=function(a){return new d(function(b,
+c){a.map(function(a){a.then(b,c)})})},d.PSD=null,d.newPSD=function(a){var b=d.PSD;d.PSD=b?Object.create(b):{};try{return a()}finally{d.PSD=b}},d._rootExec=function(a){var d=w,e;w=!1;s=b;try{a()}finally{if(d){do{for(;0<x.length;)c();if(e=A.pop(),e)try{e()}catch(f){}}while(0<A.length||0<x.length);s=r;w=!0}}},d._tickFinalize=function(a){if(w)throw Error("Not in a virtual tick");A.push(a)},d}(),B=function(){},ca;e(pa).from(Error);g["delete"]=function(a){var b=new g(a);a=b["delete"]();return a.onblocked=
+function(a){b.on("blocked",a);return this},a};g.getDatabaseNames=function(a){return(new r(function(a,b){var c=Fa(),d;c?(d=c(),d.onsuccess=function(b){a([].slice.call(b.target.result,0))},d.onerror=G(b)):za(function(b){return a(b),!1})})).then(a)};g.defineClass=function(a){function b(a){a&&d(this,a)}return Aa(b.prototype,a),b};g.ignoreTransaction=function(a){return r.newPSD(function(){return r.PSD.trans=null,a()})};g.spawn=function(){return a.console&&console.warn("Dexie.spawn() is deprecated. Use Dexie.ignoreTransaction() instead."),
+g.ignoreTransaction.apply(this,arguments)};g.vip=function(a){return r.newPSD(function(){return r.PSD.letThrough=!0,a()})};Object.defineProperty(g,"currentTransaction",{get:function(){return r.PSD&&r.PSD.trans||null}});g.Promise=r;g.derive=e;g.extend=d;g.override=f;g.events=K;g.getByKeyPath=P;g.setByKeyPath=J;g.delByKeyPath=Ba;g.shallowClone=qa;g.deepClone=ba;g.addons=[];g.fakeAutoComplete=B;g.asap=x;g.ModifyError=pa;g.MultiModifyError=pa;g.IndexSpec=Z;g.TableSchema=ya;ca=a.idbModules&&a.idbModules.shimIndexedDB?
+a.idbModules:{};g.dependencies={indexedDB:ca.shimIndexedDB||a.indexedDB||a.mozIndexedDB||a.webkitIndexedDB||a.msIndexedDB,IDBKeyRange:ca.IDBKeyRange||a.IDBKeyRange||a.webkitIDBKeyRange,IDBTransaction:ca.IDBTransaction||a.IDBTransaction||a.webkitIDBTransaction,Error:a.Error||String,SyntaxError:a.SyntaxError||String,TypeError:a.TypeError||String,DOMError:a.DOMError||String,localStorage:null!=("undefined"!=typeof chrome&&null!==chrome?chrome.storage:void 0)?null:a.localStorage};g.version=1.1;b("Dexie",
+g);A(function(){B=A})}).apply(null,"function"==typeof define&&define.amd?[self||window,function(a,b){define(a,function(){return b})}]:"undefined"!=typeof global&&"undefined"!=typeof module&&module.exports?[global,function(a,b){module.exports=b}]:[self||window,function(a,b){(self||window)[a]=b}]);
