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
