diff --git a/gui/html/chronoshare-helpers.js b/gui/html/chronoshare-helpers.js
index f1e9aa1..b727c6c 100644
--- a/gui/html/chronoshare-helpers.js
+++ b/gui/html/chronoshare-helpers.js
@@ -99,7 +99,7 @@
 
 
 openHistoryForItem = function(fileName) {
-  url = new HistoryClosure(null).base_no_item_url("fileHistory")
+  url = new HistoryDisplay(null).base_no_item_url("fileHistory")
   url += "&item=" + encodeURIComponent(encodeURIComponent(fileName));
   document.location = url;
 };
@@ -161,4 +161,4 @@
       }
     }
   });
-}
\ No newline at end of file
+}
diff --git a/gui/html/chronoshare-navigation.js b/gui/html/chronoshare-navigation.js
index 8fdd12b..81b07cd 100644
--- a/gui/html/chronoshare-navigation.js
+++ b/gui/html/chronoshare-navigation.js
@@ -26,7 +26,7 @@
     //     URIPARAMS = aurl[1];
 
     //     if (CHRONOSHARE) {
-    //         CHRONOSHARE.run ();
+    //         CHRONOSHARE.run();
     //     }
     // }
     // else if (aurl[1] != URIPARAMS)
@@ -35,7 +35,7 @@
     //     URIPARAMS = aurl[1];
 
     //     if (CHRONOSHARE) {
-    //         CHRONOSHARE.run ();
+    //         CHRONOSHARE.run();
     //     }
     // }
 
diff --git a/gui/html/chronoshare.js b/gui/html/chronoshare.js
index 38743ad..916b092 100644
--- a/gui/html/chronoshare.js
+++ b/gui/html/chronoshare.js
@@ -1,10 +1,22 @@
+info_actions_collection = [];
+info_actions_counter = 0;
+info_files_collection = [];
+info_files_counter = 0;
+lastSegmentRequested = -1;
+file_data = "";
+file_segments = 0;
+file_callback = file_onData;
+restore_callback = file_onData;
+
+face = null;
+
 $.Class("ChronoShare", {}, {
   init: function(username, foldername) {
     $("#folder-name").text(foldername);
     $("#user-name").text(username);
 
     this.username = new Name(username);
-    this.files = new Name("/localhost")
+    this.files = new Name("/localhop")
                    .add(this.username)
                    .add("chronoshare")
                    .add(foldername)
@@ -12,14 +24,14 @@
                    .add("files")
                    .add("folder");
 
-    this.actions = new Name("/localhost")
+    this.actions = new Name("/localhop")
                      .add(this.username)
                      .add("chronoshare")
                      .add(foldername)
                      .add("info")
                      .add("actions");
 
-    this.restore = new Name("/localhost")
+    this.restore = new Name("/localhop")
                      .add(this.username)
                      .add("chronoshare")
                      .add(foldername)
@@ -27,8 +39,15 @@
                      .add("restore")
                      .add("file");
 
-    this.ndn = new NDN({host: "127.0.0.1"});
-    this.ndn.verify = false; // disable content verification, works WAAAAY faster
+
+    $("#json").empty();
+
+    if (face == null) {
+      var host = "localhost";
+      // Connect to the forwarder with a WebSocket.
+      face = new Face({host: host});
+      console.log("Init Face OK!");
+    }
   },
 
   run: function() {
@@ -38,30 +57,20 @@
 
     cmd = {};
     if (PAGE == "fileList") {
+      info_files_collection = [];
+      info_files_counter = 0;
       cmd = this.info_files(PARAMS.item);
     }
     else if (PAGE == "folderHistory") {
+      info_actions_collection = [];
+      info_actions_counter = 0;
       cmd = this.info_actions("folder", PARAMS.item);
     }
     else if (PAGE == "fileHistory") {
+      info_actions_collection = [];
+      info_actions_counter = 0;
       cmd = this.info_actions("file", PARAMS.item);
     }
-
-    if (cmd.request && cmd.callback) {
-      console.log(cmd.request.to_uri());
-      this.ndn.expressInterest(cmd.request, cmd.callback);
-    }
-    else {
-      $("#loader").fadeOut(500); // ("hidden");
-      $("#content").empty();
-      if (cmd.error) {
-        $("#error").html(cmd.error);
-      }
-      else {
-        $("#error").html("Unknown error with " + PAGE);
-      }
-      $("#error").removeClass("hidden");
-    }
   },
 
   info_files: function(folder) {
@@ -69,7 +78,8 @@
                 .add(this.files)
                 ./*add (folder_in_question).*/ addSegment(
                   PARAMS.offset ? PARAMS.offset : 0);
-    return {request: request, callback: new FilesClosure(this)};
+    face.expressInterest(request, info_files_onData, on_Timeout);
+    console.log("Express OK: " + request.to_uri());
   },
 
   info_actions: function(type /*"file" or "folder"*/,
@@ -83,7 +93,9 @@
       request.add(fileOrFolder);
     }
     request.addSegment(PARAMS.offset ? PARAMS.offset : 0);
-    return {request: request, callback: new HistoryClosure(this)};
+
+    face.expressInterest(request, info_actions_onData, on_Timeout);
+    console.log("Express OK: " + request.to_uri());
   },
 
   cmd_restore_file:
@@ -92,8 +104,9 @@
       request =
         new Name().add(this.restore).add(filename).addSegment(version).add(hash);
       console.log(request.to_uri());
-      this.ndn.expressInterest(request,
-                               new CmdRestoreFileClosure(this, callback));
+
+      restore_callback = callback;
+      face.expressInterest(request, restore_onData, on_Timeout);
     },
 
   get_file:
@@ -101,10 +114,144 @@
              callback /*function (bool <- data received, data <- returned data)*/) {
       baseName = new Name(modifiedBy).add("chronoshare").add("file").add(hash);
 
-      new FileGetter(this.ndn, baseName, segments, callback).start();
-    }
+      lastSegmentRequested = 0;
+      file_data = "";
+      file_segments = segments;
+      file_callback = callback;
+
+      request = new Name().add(baseName).addSegment(lastSegmentRequested);
+      console.log("Express get_file Name: ", request.to_uri());
+      console.log("Total Segments: ", file_segments);
+      face.expressInterest(request, file_onData, on_Timeout);
+
+    },
+
 });
 
+function restore_onData(interest, upcallInfo)
+{
+  convertedData = upcallInfo.getContent().buf().toString('binary');
+  console.log("restore_onData");
+  console.log(convertedData);
+  restore_callback(true, convertedData);
+};
+
+function file_onData(interest, upcallInfo)
+{
+  convertedData = upcallInfo.getContent().buf().toString('binary');
+  console.log("file_onData");
+  console.log(convertedData);
+  file_data += convertedData;
+  if (lastSegmentRequested + 1 == file_segments) {
+    file_callback(true, file_data);
+  }
+  else {
+    lastSegmentRequested++;
+    nextSegment =
+      interest.getName().getPrefix(-1).addSegment(lastSegmentRequested);
+    face.expressInterest(nextSegment, file_onData, on_Timeout);
+  }
+};
+
+function info_actions_onData(interest, upcallInfo)
+{
+  convertedData = upcallInfo.getContent().buf().toString(
+    'binary'); //DataUtils.toString (upcallInfo.contentObject.content);
+  console.log(convertedData);
+  moreName = "more";
+  collectionName = "actions";
+
+  if (PARAMS.debug) {
+    $("#json").append($(document.createTextNode(convertedData)));
+    $("#json").removeClass("hidden");
+  }
+
+  console.log("Prefix");
+  console.log(interest.getName().getPrefix(-1).to_uri());
+
+  data = JSON.parse(convertedData);
+  console.log(data);
+  console.log(data[collectionName]);
+  var collection = data[collectionName];
+  info_actions_collection = info_actions_collection.concat(data[collectionName]);
+
+  console.log(info_actions_collection);
+
+  if (data[moreName] !== undefined) {
+    nextSegment = interest.getName().getPrefix(-1).addSegment(data[moreName]);
+    info_actions_counter++;
+
+    if (info_actions_counter < 5) {
+      console.log("MORE: " + nextSegment.to_uri());
+      face.expressInterest(nextSegment, info_actions_onData, on_Timeout);
+    }
+    else {
+      $("#loader").fadeOut(500); // ("hidden");
+      var HD = new HistoryDisplay(CHRONOSHARE);
+      HD.onData(info_actions_collection, data[moreName]);
+    }
+  }
+  else {
+    $("#loader").fadeOut(500); // ("hidden");
+    console.log("I'm triggered more undefined~");
+    var HD = new HistoryDisplay(CHRONOSHARE);
+    HD.onData(info_actions_collection, undefined);
+  }
+};
+
+function info_files_onData(interest, upcallInfo)
+{
+  convertedData = upcallInfo.getContent().buf().toString(
+    'binary'); //DataUtils.toString (upcallInfo.contentObject.content);
+  console.log(convertedData);
+  moreName = "more";
+  collectionName = "files";
+
+  if (PARAMS.debug) {
+    $("#json").append($(document.createTextNode(convertedData)));
+    $("#json").removeClass("hidden");
+  }
+
+  console.log("Prefix");
+  console.log(interest.getName().getPrefix(-1).to_uri());
+
+  data = JSON.parse(convertedData);
+  console.log(data);
+  console.log(data[collectionName]);
+  var collection = data[collectionName];
+  info_files_collection = info_files_collection.concat(data[collectionName]);
+
+  console.log(info_files_collection);
+
+  if (data[moreName] !== undefined) {
+    nextSegment = interest.getName().getPrefix(-1).addSegment(data[moreName]);
+    info_files_counter++;
+
+    if (info_files_counter < 5) {
+      console.log("MORE: " + nextSegment.to_uri());
+      face.expressInterest(nextSegment, info_files_onData, on_Timeout);
+    }
+    else {
+      $("#loader").fadeOut(500); // ("hidden");
+      var HD = new FilesDisplay(CHRONOSHARE);
+      HD.onData(info_files_collection, data[moreName]);
+    }
+  }
+  else {
+    $("#loader").fadeOut(500); // ("hidden");
+    console.log("I'm triggered more undefined~");
+    var HD = new FilesDisplay(CHRONOSHARE);
+    HD.onData(info_files_collection, undefined);
+  }
+};
+
+
+function on_Timeout(interest)
+{
+  $("#error").html("Ha Ha Interest time out");
+  $("#error").removeClass("hidden");
+}
+
 $.Class("CmdRestoreFileClosure", {}, {
   init: function(chronoshare, callback) {
     this.chronoshare = chronoshare;
@@ -112,12 +259,12 @@
   },
   upcall: function(kind, upcallInfo) {
     if (kind == Closure.UPCALL_CONTENT ||
-        kind == Closure.UPCALL_CONTENT_UNVERIFIED) { // disable content verification
+        kind == Closure.UPCALL_CONTENT_UNVERIFIED) { //disable content verification
       convertedData = DataUtils.toString(upcallInfo.contentObject.content);
       this.callback(true, convertedData);
     }
     else if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
-      this.callback(false, "Interest timed out");
+      this.callback(false, "Interest timed out 99");
     }
     else {
       this.callback(false, "Unknown error happened");
@@ -125,230 +272,9 @@
   }
 });
 
-$.Class("FileGetter", {}, {
-  init: function(ndn, baseName, segments, callback) {
-    this.ndn = ndn;
-    this.callback = callback;
-    this.baseName = baseName;
-    this.segments = segments;
-    this.lastSegmentRequested = -1;
 
-    this.data = "";
-  },
-
-  start: function() {
-    this.lastSegmentRequested++;
-
-    request =
-      new Name().add(this.baseName).addSegment(this.lastSegmentRequested);
-
-    console.log(request.to_uri());
-    this.ndn.expressInterest(request, this);
-  },
-
-  upcall: function(kind, upcallInfo) {
-    if (kind == Closure.UPCALL_CONTENT ||
-        kind == Closure.UPCALL_CONTENT_UNVERIFIED) { // disable content verification
-      convertedData = DataUtils.toString(upcallInfo.contentObject.content);
-
-      this.data += convertedData;
-
-      if (this.lastSegmentRequested + 1 == this.segments) {
-        this.callback(true, this.data);
-      }
-      else {
-        this.start();
-      }
-    }
-    else {
-      this.callback(false, "Interest timed out");
-    }
-  }
-});
-
-$.Class("RestPipelineClosure", {}, {
-  init: function(collectionName, moreName) {
-    this.collectionName = collectionName;
-    this.moreName = moreName;
-    $("#json").empty();
-
-    this.collection = [];
-    this.counter = 0;
-  },
-
-  upcall: function(kind, upcallInfo) {
-    if (kind == Closure.UPCALL_CONTENT ||
-        kind == Closure.UPCALL_CONTENT_UNVERIFIED) { // disable content verification
-
-      convertedData = DataUtils.toString(upcallInfo.contentObject.content);
-      if (PARAMS.debug) {
-        $("#json").append($(document.createTextNode(convertedData)));
-        $("#json").removeClass("hidden");
-      }
-      data = JSON.parse(convertedData);
-
-      this.collection = this.collection.concat(data[this.collectionName]);
-      if (data[this.moreName] !== undefined) {
-        nextSegment =
-          upcallInfo.interest.name.cut(1).addSegment(data[this.moreName]);
-        this.counter++;
-
-        if (this.counter < 5) {
-          console.log("MORE: " + nextSegment.to_uri());
-          CHRONOSHARE.ndn.expressInterest(nextSegment, this);
-        }
-        else {
-          $("#loader").fadeOut(500); // ("hidden");
-          this.onData(this.collection, data[this.moreName]);
-        }
-      }
-      else {
-        $("#loader").fadeOut(500); // ("hidden");
-        this.onData(this.collection, undefined);
-      }
-    }
-    else if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
-      $("#loader").fadeOut(500); // ("hidden");
-      this.onTimeout(upcallInfo.interest);
-    }
-    else {
-      $("#loader").fadeOut(500); // ("hidden");
-      this.onUnknownError(upcallInfo.interest);
-    }
-
-    return Closure.RESULT_OK; // make sure we never re-express the interest
-  },
-
-  onData: function(data, more) {},
-
-  onTimeout: function() {
-    $("#error").html("Interest timed out");
-    $("#error").removeClass("hidden");
-  },
-
-  onUnknownError: function() {
-    $("#error").html("Unknown error happened");
-    $("#error").removeClass("hidden");
-  }
-});
-
-// $.Class ("FilesClosure", {}, {
-RestPipelineClosure("FilesClosure", {}, {
+$.Class("HistoryDisplay", {}, {
   init: function(chronoshare) {
-    this._super("files", "more");
-    this.chronoshare = chronoshare;
-  },
-
-  onData: function(data, more) {
-    tbody = $("<tbody />", {"id": "file-list-files"});
-
-    /// @todo Eventually set title for other pages
-    $("title").text("ChronoShare - List of files" +
-                    (PARAMS.item ? " - " + PARAMS.item : ""));
-
-    // error handling?
-    newcontent =
-      $("<div />", {"id": "content"})
-        .append($("<h2 />").append($(document.createTextNode("List of files ")),
-                                   $("<green />").text(PARAMS.item)),
-                $("<table />", {"class": "item-list"})
-                  .append(
-                    $("<thead />")
-                      .append($("<tr />")
-                                .append($("<th />", {
-                                          "class": "filename border-left",
-                                          "scope": "col"
-                                        }).text("Filename"))
-                                .append($("<th />",
-                                          {"class": "version", "scope": "col"})
-                                          .text("Version"))
-                                .append($("<th />",
-                                          {"class": "size", "scope": "col"})
-                                          .text("Size"))
-                                .append($("<th />", {
-                                          "class": "modified",
-                                          "scope": "col"
-                                        }).text("Modified"))
-                                .append($("<th />", {
-                                          "class": "modified-by border-right",
-                                          "scope": "col"
-                                        }).text("Modified By"))))
-                  .append(tbody)
-                  .append($("<tfoot />").append($("<tr />").append($("<td />", {
-                    "colspan": "5",
-                    "class": "border-right border-left"
-                  })))));
-    newcontent.hide();
-
-    for (var i = 0; i < data.length; i++) {
-      file = data[i];
-
-      row = $("<tr />", {"class": "with-context-menu"});
-      if (i % 2) {
-        row.addClass("odd");
-      }
-
-      row.bind('mouseenter mouseleave', function() {
-        $(this).toggleClass('highlighted');
-      });
-
-      row.attr("filename",
-               file.filename); // encodeURIComponent(encodeURIComponent(file.filename)));
-      row.bind('click', function(e) {
-        openHistoryForItem($(this).attr("filename"))
-      });
-
-      row.append(
-        $("<td />", {"class": "filename border-left"})
-          .text(file.filename)
-          .prepend(
-            $("<img />", {"src": imgFullPath(fileExtension(file.filename))})));
-      row.append($("<td />", {"class": "version"}).text(file.version));
-      row.append(
-        $("<td />", {"class": "size"}).text(SegNumToFileSize(file.segNum)));
-      row.append($("<td />", {
-                   "class": "modified"
-                 }).text(new Date(file.timestamp + "+00:00"))); // convert from UTC
-      row.append($("<td />", {"class": "modified-by border-right"})
-                   .append($("<userName />").text(file.owner.userName))
-                   .append($("<seqNo> /").text(file.owner.seqNo)));
-
-      tbody = tbody.append(row);
-    }
-
-    displayContent(newcontent, more, this.base_url());
-
-    $.contextMenu('destroy', ".with-context-menu"); // cleanup
-    $.contextMenu({
-      selector: ".with-context-menu",
-      items: {
-        "info": {name: "x", type: "html", html: "<b>File operations</b>"},
-        "sep1": "---------",
-        history: {
-          name: "View file history",
-          icon: "quit", // need a better icon
-          callback: function(key, opt) {
-            openHistoryForItem(opt.$trigger.attr("filename"));
-          }
-        },
-      }
-    });
-  },
-
-  base_url: function() {
-    url = "#fileList" +
-          "&user=" + encodeURIComponent(encodeURIComponent(PARAMS.user)) +
-          "&folder=" + encodeURIComponent(encodeURIComponent(PARAMS.folder));
-    if (PARAMS.item !== undefined) {
-      url += "&item=" + encodeURIComponent(encodeURIComponent(PARAMS.item));
-    }
-    return url;
-  }
-});
-
-RestPipelineClosure("HistoryClosure", {}, {
-  init: function(chronoshare) {
-    this._super("actions", "more");
     this.chronoshare = chronoshare;
   },
 
@@ -356,7 +282,8 @@
     if (fileExtension(file.attr("filename")) == "txt") {
       CHRONOSHARE.get_file(file.attr("file_modified_by"),
                            DataUtils.toNumbers(file.attr("file_hash")),
-                           file.attr("file_seg_num"), function(status, data) {
+                           file.attr("file_seg_num"),
+                           function(status, data) {
                              $("<div />", {
                                "title": "Preview of " + file.attr("filename") +
                                           " version " + file.attr("file_version")
@@ -462,13 +389,11 @@
         $("<td />", {
           "class": "size"
         }).text(action.update ? SegNumToFileSize(action.update.segNum) : ""));
-      row.append($("<td />", {
-                   "class": "timestamp"
-                 }).text(new Date(action.timestamp + "+00:00"))); // conversion
-                                                                  // from UTC
-      // timezone (we
-      // store action
-      // time in UTC)
+      row.append(
+        $("<td />", {"class": "timestamp"})
+          .text(new Date(
+            action.timestamp +
+            "+00:00"))); // conversion from UTC timezone (we store action time in UTC)
       row.append($("<td />", {"class": "modified-by border-right"})
                    .append($("<userName />").text(action.id.userName))
                    .append($("<seqNo> /").text(action.id.seqNo)));
@@ -529,6 +454,10 @@
                                                        response != "OK") {
                                                      custom_alert(response);
                                                    }
+
+                                                   custom_alert(
+                                                     "Restore Succeed!");
+
                                                    console.log(response);
                                                    self.dialog("close");
 
@@ -568,3 +497,115 @@
     return url;
   }
 });
+
+$.Class("FilesDisplay", {}, {
+  init: function(chronoshare) {
+    this.chronoshare = chronoshare;
+  },
+
+  onData: function(data, more) {
+    tbody = $("<tbody />", {"id": "file-list-files"});
+
+    /// @todo Eventually set title for other pages
+    $("title").text("ChronoShare - List of files" +
+                    (PARAMS.item ? " - " + PARAMS.item : ""));
+
+    // error handling?
+    newcontent =
+      $("<div />", {"id": "content"})
+        .append($("<h2 />").append($(document.createTextNode("List of files ")),
+                                   $("<green />").text(PARAMS.item)),
+                $("<table />", {"class": "item-list"})
+                  .append(
+                    $("<thead />")
+                      .append($("<tr />")
+                                .append($("<th />", {
+                                          "class": "filename border-left",
+                                          "scope": "col"
+                                        }).text("Filename"))
+                                .append($("<th />",
+                                          {"class": "version", "scope": "col"})
+                                          .text("Version"))
+                                .append($("<th />",
+                                          {"class": "size", "scope": "col"})
+                                          .text("Size"))
+                                .append($("<th />", {
+                                          "class": "modified",
+                                          "scope": "col"
+                                        }).text("Modified"))
+                                .append($("<th />", {
+                                          "class": "modified-by border-right",
+                                          "scope": "col"
+                                        }).text("Modified By"))))
+                  .append(tbody)
+                  .append($("<tfoot />").append($("<tr />").append($("<td />", {
+                    "colspan": "5",
+                    "class": "border-right border-left"
+                  })))));
+    newcontent.hide();
+
+    for (var i = 0; i < data.length; i++) {
+      file = data[i];
+
+      row = $("<tr />", {"class": "with-context-menu"});
+      if (i % 2) {
+        row.addClass("odd");
+      }
+
+      row.bind('mouseenter mouseleave', function() {
+        $(this).toggleClass('highlighted');
+      });
+
+      row.attr("filename",
+               file.filename); //encodeURIComponent(encodeURIComponent(file.filename)));
+      row.bind('click', function(e) {
+        openHistoryForItem($(this).attr("filename"))
+      });
+
+      row.append(
+        $("<td />", {"class": "filename border-left"})
+          .text(file.filename)
+          .prepend(
+            $("<img />", {"src": imgFullPath(fileExtension(file.filename))})));
+      row.append($("<td />", {"class": "version"}).text(file.version));
+      row.append(
+        $("<td />", {"class": "size"}).text(SegNumToFileSize(file.segNum)));
+      row.append($("<td />", {
+                   "class": "modified"
+                 }).text(new Date(file.timestamp + "+00:00"))); // convert from UTC
+      row.append($("<td />", {"class": "modified-by border-right"})
+                   .append($("<userName />").text(file.owner.userName))
+                   .append($("<seqNo> /").text(file.owner.seqNo)));
+
+      tbody = tbody.append(row);
+    }
+
+    displayContent(newcontent, more, this.base_url());
+
+    $.contextMenu('destroy', ".with-context-menu"); // cleanup
+    $.contextMenu({
+      selector: ".with-context-menu",
+      items: {
+        "info": {name: "x", type: "html", html: "<b>File operations</b>"},
+        "sep1": "---------",
+        history: {
+          name: "View file history",
+          icon: "quit", // need a better icon
+          callback: function(key, opt) {
+            openHistoryForItem(opt.$trigger.attr("filename"));
+          }
+        },
+      }
+    });
+  },
+
+  base_url: function() {
+    url = "#fileList" +
+          "&user=" + encodeURIComponent(encodeURIComponent(PARAMS.user)) +
+          "&folder=" + encodeURIComponent(encodeURIComponent(PARAMS.folder));
+    if (PARAMS.item !== undefined) {
+      url += "&item=" + encodeURIComponent(encodeURIComponent(PARAMS.item));
+    }
+    return url;
+  }
+});
diff --git a/gui/html/js/ndn-js.js b/gui/html/js/ndn-js.js
index 63f1fef..9408f0c 100644
--- a/gui/html/js/ndn-js.js
+++ b/gui/html/js/ndn-js.js
@@ -1,5017 +1,1679 @@
-/**
- * @author: Jeff Thompson
- * See COPYING for copyright and distribution information.
- * Provide the callback closure for the async communication methods in the NDN class.
- * This is a port of Closure.py from PyNDN, written by: 
- * Derek Kulinski <takeda@takeda.tk>
- * Jeff Burke <jburke@ucla.edu>
- */
-
-/*
- * Create a subclass of Closure and pass an object to async calls.
- */
-var Closure = function Closure() {
-	// I don't think storing NDN's closure is needed
-	// and it creates a reference loop, as of now both
-	// of those variables are never set -- Derek
-	//
-	// Use instance variables to return data to callback
-	this.ndn_data = null;  // this holds the ndn_closure
-    this.ndn_data_dirty = false;
-    
-};
-
-// Upcall result
-Closure.RESULT_ERR               = -1; // upcall detected an error
-Closure.RESULT_OK                =  0; // normal upcall return
-Closure.RESULT_REEXPRESS         =  1; // reexpress the same interest again
-Closure.RESULT_INTEREST_CONSUMED =  2; // upcall claims to consume interest
-Closure.RESULT_VERIFY            =  3; // force an unverified result to be verified
-Closure.RESULT_FETCHKEY          =  4; // get the key in the key locator and re-call the interest
-                                       //   with the key available in the local storage
-
-// Upcall kind
-Closure.UPCALL_FINAL              = 0; // handler is about to be deregistered
-Closure.UPCALL_INTEREST           = 1; // incoming interest
-Closure.UPCALL_CONSUMED_INTEREST  = 2; // incoming interest, someone has answered
-Closure.UPCALL_CONTENT            = 3; // incoming verified content
-Closure.UPCALL_INTEREST_TIMED_OUT = 4; // interest timed out
-Closure.UPCALL_CONTENT_UNVERIFIED = 5; // content that has not been verified
-Closure.UPCALL_CONTENT_BAD        = 6; // verification failed
-
-/*
- * Override this in your subclass.
- * If you're getting strange errors in upcall()
- * check your code whether you're returning a value.
- */
-Closure.prototype.upcall = function(kind, upcallInfo) {
-	//dump('upcall ' + this + " " + kind + " " + upcallInfo + "\n");
-	return Closure.RESULT_OK;
-};
-
-var UpcallInfo = function UpcallInfo(ndn, interest, matchedComps, contentObject) {
-	this.ndn = ndn;  // NDN object (not used)
-	this.interest = interest;  // Interest object
-	this.matchedComps = matchedComps;  // int
-	this.contentObject = contentObject;  // Content object
-};
-
-UpcallInfo.prototype.toString = function() {
-	var ret = "ndn = " + this.ndn;
-	ret += "\nInterest = " + this.interest;
-	ret += "\nmatchedComps = " + this.matchedComps;
-	ret += "\nContentObject: " + this.contentObject;
-	return ret;
-}
-/** 
- * @author: Wentao Shang
- * See COPYING for copyright and distribution information.
- */
-
-var WebSocketTransport = function WebSocketTransport() {    
-    if (!WebSocket)
-        throw new Error("WebSocket support is not available on this platform.");
-    
-	this.ws = null;
-    this.connectedHost = null; // Read by NDN.
-    this.connectedPort = null; // Read by NDN.
-    this.elementReader = null;
-    this.defaultGetHostAndPort = NDN.makeShuffledGetHostAndPort
-        (["A.ws.ndn.ucla.edu", "B.ws.ndn.ucla.edu", "C.ws.ndn.ucla.edu", "D.ws.ndn.ucla.edu", 
-          "E.ws.ndn.ucla.edu"],
-         9696);
-};
-
-/*
- * Connect to the host and port in ndn.  This replaces a previous connection and sets connectedHost
- *   and connectedPort.  Once connected, call onopenCallback().
- * Listen on the port to read an entire binary XML encoded element and call
- *    ndn.onReceivedElement(element).
- */
-WebSocketTransport.prototype.connect = function(ndn, onopenCallback) {
-	if (this.ws != null)
-		delete this.ws;
-	
-	this.ws = new WebSocket('ws://' + ndn.host + ':' + ndn.port);
-	if (LOG > 0) console.log('ws connection created.');
-    this.connectedHost = ndn.host;
-    this.connectedPort = ndn.port;
-	
-	this.ws.binaryType = "arraybuffer";
-	
-    this.elementReader = new BinaryXmlElementReader(ndn);
-	var self = this;
-	this.ws.onmessage = function(ev) {
-		var result = ev.data;
-		//console.log('RecvHandle called.');
-			
-		if(result == null || result == undefined || result == "" ) {
-			console.log('INVALID ANSWER');
-		} else if (result instanceof ArrayBuffer) {
-	        var bytearray = new Uint8Array(result);
-	        
-			if (LOG>3) console.log('BINARY RESPONSE IS ' + DataUtils.toHex(bytearray));
-			
-			try {
-                // Find the end of the binary XML element and call ndn.onReceivedElement.
-                self.elementReader.onReceivedData(bytearray);
-			} catch (ex) {
-				console.log("NDN.ws.onmessage exception: " + ex);
-				return;
-			}
-		}
-	}
-	
-	this.ws.onopen = function(ev) {
-		if (LOG > 3) console.log(ev);
-		if (LOG > 3) console.log('ws.onopen: WebSocket connection opened.');
-		if (LOG > 3) console.log('ws.onopen: ReadyState: ' + this.readyState);
-        // NDN.registerPrefix will fetch the ndndid when needed.
-        
-        onopenCallback();
-	}
-	
-	this.ws.onerror = function(ev) {
-		console.log('ws.onerror: ReadyState: ' + this.readyState);
-		console.log(ev);
-		console.log('ws.onerror: WebSocket error: ' + ev.data);
-	}
-	
-	this.ws.onclose = function(ev) {
-		console.log('ws.onclose: WebSocket connection closed.');
-		self.ws = null;
-		
-		// Close NDN when WebSocket is closed
-		ndn.readyStatus = NDN.CLOSED;
-		ndn.onclose();
-		//console.log("NDN.onclose event fired.");
-	}
-};
-
-/*
- * Send the Uint8Array data.
- */
-WebSocketTransport.prototype.send = function(data) {
-	if (this.ws != null) {
-        // If we directly use data.buffer to feed ws.send(), 
-        // WebSocket may end up sending a packet with 10000 bytes of data.
-        // That is, WebSocket will flush the entire buffer
-        // regardless of the offset of the Uint8Array. So we have to create
-        // a new Uint8Array buffer with just the right size and copy the 
-        // content from binaryInterest to the new buffer.
-        //    ---Wentao
-        var bytearray = new Uint8Array(data.length);
-        bytearray.set(data);
-        this.ws.send(bytearray.buffer);
-		if (LOG > 3) console.log('ws.send() returned.');
-	}
-	else
-		console.log('WebSocket connection is not established.');
-}
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class contains all NDNx tags
- */
-
-
-var NDNProtocolDTags = {
-
-	/**
-	 * Note if you add one of these, add it to the reverse string map as well.
-	 * Emphasize getting the work done at compile time over trying to make something
-	 * flexible and developer error-proof.
-	 */
-
-	 Any : 13,
-	 Name : 14,
-	 Component : 15,
-	 Certificate : 16,
-	 Collection : 17,
-	 CompleteName : 18,
-	 Content : 19,
-	 SignedInfo : 20,
-	 ContentDigest : 21,
-	 ContentHash : 22,
-	 Count : 24,
-	 Header : 25,
-	 Interest : 26,	/* 20090915 */
-	 Key : 27,
-	 KeyLocator : 28,
-	 KeyName : 29,
-	 Length : 30,
-	 Link : 31,
-	 LinkAuthenticator : 32,
-	 NameComponentCount : 33,	/* DeprecatedInInterest */
-	 RootDigest : 36,
-	 Signature : 37,
-	 Start : 38,
-	 Timestamp : 39,
-	 Type : 40,
-	 Nonce : 41,
-	 Scope : 42,
-	 Exclude : 43,
-	 Bloom : 44,
-	 BloomSeed : 45,
-	 AnswerOriginKind : 47,
-	 InterestLifetime : 48,
-	 Witness : 53,
-	 SignatureBits : 54,
-	 DigestAlgorithm : 55,
-	 BlockSize : 56,
-	 FreshnessSeconds : 58,
-	 FinalBlockID : 59,
-	 PublisherPublicKeyDigest : 60,
-	 PublisherCertificateDigest : 61,
-	 PublisherIssuerKeyDigest : 62,
-	 PublisherIssuerCertificateDigest : 63,
-	 ContentObject : 64,	/* 20090915 */
-	 WrappedKey : 65,
-	 WrappingKeyIdentifier : 66,
-	 WrapAlgorithm : 67,
-	 KeyAlgorithm : 68,
-	 Label : 69,
-	 EncryptedKey : 70,
-	 EncryptedNonceKey : 71,
-	 WrappingKeyName : 72,
-	 Action : 73,
-	 FaceID : 74,
-	 IPProto : 75,
-	 Host : 76,
-	 Port : 77,
-	 MulticastInterface : 78,
-	 ForwardingFlags : 79,
-	 FaceInstance : 80,
-	 ForwardingEntry : 81,
-	 MulticastTTL : 82,
-	 MinSuffixComponents : 83,
-	 MaxSuffixComponents : 84,
-	 ChildSelector : 85,
-	 RepositoryInfo : 86,
-	 Version : 87,
-	 RepositoryVersion : 88,
-	 GlobalPrefix : 89,
-	 LocalName : 90,
-	 Policy : 91,
-	 Namespace : 92,
-	 GlobalPrefixName : 93,
-	 PolicyVersion : 94,
-	 KeyValueSet : 95,
-	 KeyValuePair : 96,
-	 IntegerValue : 97,
-	 DecimalValue : 98,
-	 StringValue : 99,
-	 BinaryValue : 100,
-	 NameValue : 101,
-	 Entry : 102,
-	 ACL : 103,
-	 ParameterizedName : 104,
-	 Prefix : 105,
-	 Suffix : 106,
-	 Root : 107,
-	 ProfileName : 108,
-	 Parameters : 109,
-	 InfoString : 110,
-	// 111 unallocated
-	 StatusResponse : 112,
-	 StatusCode : 113,
-	 StatusText : 114,
-
-	// Sync protocol
-	 SyncNode : 115,
-	 SyncNodeKind : 116,
-	 SyncNodeElement : 117,
-	 SyncVersion : 118,
-	 SyncNodeElements : 119,
-	 SyncContentHash : 120,
-	 SyncLeafCount : 121,
-	 SyncTreeDepth : 122,
-	 SyncByteCount : 123,
-	 ConfigSlice : 124,
-	 ConfigSliceList : 125,
-	 ConfigSliceOp : 126,
-
-	// Remember to keep in sync with schema/tagnames.csvsdict
-	 NDNProtocolDataUnit : 17702112,
-	 NDNPROTOCOL_DATA_UNIT : "NDNProtocolDataUnit"
-};
-
-var NDNProtocolDTagsStrings = [
-	null, null, null, null, null, null, null, null, null, null, null,
-	null, null,
-	"Any", "Name", "Component", "Certificate", "Collection", "CompleteName",
-	"Content", "SignedInfo", "ContentDigest", "ContentHash", null, "Count", "Header",
-	"Interest", "Key", "KeyLocator", "KeyName", "Length", "Link", "LinkAuthenticator",
-	"NameComponentCount", null, null, "RootDigest", "Signature", "Start", "Timestamp", "Type",
-	"Nonce", "Scope", "Exclude", "Bloom", "BloomSeed", null, "AnswerOriginKind",
-	"InterestLifetime", null, null, null, null, "Witness", "SignatureBits", "DigestAlgorithm", "BlockSize",
-	null, "FreshnessSeconds", "FinalBlockID", "PublisherPublicKeyDigest", "PublisherCertificateDigest",
-	"PublisherIssuerKeyDigest", "PublisherIssuerCertificateDigest", "ContentObject",
-	"WrappedKey", "WrappingKeyIdentifier", "WrapAlgorithm", "KeyAlgorithm", "Label",
-	"EncryptedKey", "EncryptedNonceKey", "WrappingKeyName", "Action", "FaceID", "IPProto",
-	"Host", "Port", "MulticastInterface", "ForwardingFlags", "FaceInstance",
-	"ForwardingEntry", "MulticastTTL", "MinSuffixComponents", "MaxSuffixComponents", "ChildSelector",
-	"RepositoryInfo", "Version", "RepositoryVersion", "GlobalPrefix", "LocalName",
-	"Policy", "Namespace", "GlobalPrefixName", "PolicyVersion", "KeyValueSet", "KeyValuePair",
-	"IntegerValue", "DecimalValue", "StringValue", "BinaryValue", "NameValue", "Entry",
-	"ACL", "ParameterizedName", "Prefix", "Suffix", "Root", "ProfileName", "Parameters",
-	"InfoString", null,
-    "StatusResponse", "StatusCode", "StatusText", "SyncNode", "SyncNodeKind", "SyncNodeElement",
-    "SyncVersion", "SyncNodeElements", "SyncContentHash", "SyncLeafCount", "SyncTreeDepth", "SyncByteCount",
-    "ConfigSlice", "ConfigSliceList", "ConfigSliceOp" ];
-
-
-//TESTING
-//console.log(exports.NDNProtocolDTagsStrings[17]);
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents NDNTime Objects
- */
-
-var NDNTime = function NDNTime(
-                               
-		input) {
-
-
-
-
-	this.NANOS_MAX = 999877929;
-	
-	/*if(typeof input =='object'){
-		this.longDate = DataUtils.byteArrayToUnsignedLong(input);
-		this.binaryDate = input;
-	}*/
-	if(typeof input =='number'){
-		this.msec = input;
-		//this.binaryDate = DataUtils.unsignedLongToByteArray(input);
-
-	}
-	else{
-		if(LOG>1) console.log('UNRECOGNIZED TYPE FOR TIME');
-	}
-};
-
-
-NDNTime.prototype.getJavascriptDate = function(){
-	var d = new Date();
-	d.setTime( this.msec );
-	return d
-};
-
-	/**
-	 * Create a NDNTime
-	 * @param timestamp source timestamp to initialize from, some precision will be lost
-	 */
-
-
-	/**
-	 * Create a NDNTime from its binary encoding
-	 * @param binaryTime12 the binary representation of a NDNTime
-	 */
-/*NDNTime.prototype.setDateBinary = function(
-	//byte [] 
-		binaryTime12) {
-
-
-	if ((null == binaryTime12) || (binaryTime12.length == 0)) {
-		throw new IllegalArgumentException("Invalid binary time!");
-	}
-	
-
-	value = 0;
-	for(i = 0; i < binaryTime12.length; i++) {
-		value = value << 8;
-		b = (binaryTime12[i]) & 0xFF;
-		value |= b;
-	}
-
-	//this.date = new Date(value);
-
-};
-
-//byte[]
-NDNTime.prototype.toBinaryTime = function() {
-
-	return this.msec; //unsignedLongToByteArray(this.date.getTime());
-
-}*/
-/*
-unsignedLongToByteArray= function( value) {
-	if( 0 == value )
-		return [0];
-
-	if( 0 <= value && value <= 0x00FF ) {
-		//byte [] 
-		bb = new Array[1];
-		bb[0] = (value & 0x00FF);
-		return bb;
-	}
-
-	
-	//byte [] 
-	out = null;
-	//int
-	offset = -1;
-	for(var i = 7; i >=0; --i) {
-		//byte
-		b = ((value >> (i * 8)) & 0xFF);
-		if( out == null && b != 0 ) {
-			out = new Array(i+1);//byte[i+1];
-			offset = i;
-		}
-		if( out != null )
-			out[ offset - i ] = b;
-	}
-	return out;
-}*/
-	
-/**
- * @author: Jeff Thompson
- * See COPYING for copyright and distribution information.
- * This is the closure class for use in expressInterest to re express with exponential falloff.
- */
-
-/*
- * Create a new ExponentialReExpressClosure where upcall responds to UPCALL_INTEREST_TIMED_OUT
- *   by expressing the interest again with double the interestLifetime. If the interesLifetime goes
- *   over maxInterestLifetime, then call callerClosure.upcall with UPCALL_INTEREST_TIMED_OUT.
- * When upcall is not UPCALL_INTEREST_TIMED_OUT, just call callerClosure.upcall.
- * 
- * settings is an associative array with the following defaults:
- * {
- *   maxInterestLifetime: 16000 // milliseconds
- * }
- */
-var ExponentialReExpressClosure = function ExponentialReExpressClosure
-        (callerClosure, settings) {
-    // Inherit from Closure.
-    Closure.call(this);
-    
-    this.callerClosure = callerClosure;
-    settings = (settings || {});
-	this.maxInterestLifetime = (settings.maxInterestLifetime || 16000);
-};
-
-ExponentialReExpressClosure.prototype.upcall = function(kind, upcallInfo) {
-    try {
-        if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
-            var interestLifetime = upcallInfo.interest.interestLifetime;
-            if (interestLifetime == null)
-                return this.callerClosure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, upcallInfo);
-            
-            var nextInterestLifetime = interestLifetime * 2;
-            if (nextInterestLifetime > this.maxInterestLifetime)
-                return this.callerClosure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, upcallInfo);
-            
-            var nextInterest = upcallInfo.interest.clone();
-            nextInterest.interestLifetime = nextInterestLifetime;
-            upcallInfo.ndn.expressInterest(nextInterest.name, this, nextInterest);
-            return Closure.RESULT_OK;
-        }  
-        else
-            return this.callerClosure.upcall(kind, upcallInfo);
-    } catch (ex) {
-        console.log("ExponentialReExpressClosure.upcall exception: " + ex);
-        return Closure.RESULT_ERR;
+// Domain Public by Eric Wendelin http://www.eriwen.com/ (2008)
+//                  Luke Smith http://lucassmith.name/ (2008)
+//                  Loic Dachary <loic@dachary.org> (2008)
+//                  Johan Euphrosine <proppy@aminche.com> (2008)
+//                  Oyvind Sean Kinsey http://kinsey.no/blog (2010)
+//                  Victor Homyakov <victor-homyakov@users.sourceforge.net> (2010)
+/*global module, exports, define, ActiveXObject*/
+(function(global, factory) {
+    if (typeof exports === 'object') {
+        // Node
+        module.exports.printStackTrace = factory();
+    } else if (typeof define === 'function' && define.amd) {
+        // AMD
+        define(factory);
+    } else {
+        // Browser globals
+        global.printStackTrace = factory();
     }
-};
-/**
- * @author: Meki Cheraoui, Jeff Thompson
- * See COPYING for copyright and distribution information.
- * This class represents a Name as an array of components where each is a byte array.
- */
-
-/*
- * Create a new Name from _components.
- * If _components is a string, parse it as a URI.
- * If _components is a Name, add a deep copy of its components.
- * Otherwise it is an array of components where each is a string, byte array, ArrayBuffer, Uint8Array
- *   or Name.
- * Convert and store as an array of Uint8Array.
- * If a component is a string, encode as utf8.
- */
-var Name = function Name(_components){
-	if( typeof _components == 'string') {
-		if(LOG>3)console.log('Content Name String '+_components);
-		this.components = Name.createNameArray(_components);
-	}
-	else if(typeof _components === 'object'){
-		this.components = [];
-        if (_components instanceof Name)
-            this.add(_components);
-        else {
-            for (var i = 0; i < _components.length; ++i)
-                this.add(_components[i]);
-        }
-	}
-	else if(_components==null)
-		this.components =[];
-	else
-		if(LOG>1)console.log("NO CONTENT NAME GIVEN");
-};
-
-Name.prototype.getName = function() {
-    return this.to_uri();
-};
-
-/* Parse name as a URI and return an array of Uint8Array components.
- *
- */
-Name.createNameArray = function(name) {
-    name = name.trim();
-    if (name.length <= 0)
-        return [];
-
-    var iColon = name.indexOf(':');
-    if (iColon >= 0) {
-        // Make sure the colon came before a '/'.
-        var iFirstSlash = name.indexOf('/');
-        if (iFirstSlash < 0 || iColon < iFirstSlash)
-            // Omit the leading protocol such as ndn:
-            name = name.substr(iColon + 1, name.length - iColon - 1).trim();
-    }
-
-  	if (name[0] == '/') {
-        if (name.length >= 2 && name[1] == '/') {
-            // Strip the authority following "//".
-            var iAfterAuthority = name.indexOf('/', 2);
-            if (iAfterAuthority < 0)
-                // Unusual case: there was only an authority.
-                return [];
-            else
-                name = name.substr(iAfterAuthority + 1, name.length - iAfterAuthority - 1).trim();
-        }
-        else
-            name = name.substr(1, name.length - 1).trim();
-    }
-
-	var array = name.split('/');
-
-    // Unescape the components.
-    for (var i = 0; i < array.length; ++i) {
-        var component = Name.fromEscapedString(array[i]);
-
-        if (component == null) {
-            // Ignore the illegal componenent.  This also gets rid of a trailing '/'.
-            array.splice(i, 1);
-            --i;
-            continue;
-        }
-        else
-            array[i] = component;
-    }
-
-	return array;
-}
-
-
-Name.prototype.from_ndnb = function(/*XMLDecoder*/ decoder)  {
-		decoder.readStartElement(this.getElementLabel());
-
-
-		this.components = new Array(); //new ArrayList<byte []>();
-
-		while (decoder.peekStartElement(NDNProtocolDTags.Component)) {
-			this.add(decoder.readBinaryElement(NDNProtocolDTags.Component));
-		}
-
-		decoder.readEndElement();
-};
-
-Name.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)  {
-
-		if( this.components ==null )
-			throw new Error("CANNOT ENCODE EMPTY CONTENT NAME");
-
-		encoder.writeStartElement(this.getElementLabel());
-		var count = this.components.length;
-		for (var i=0; i < count; i++) {
-			encoder.writeElement(NDNProtocolDTags.Component, this.components[i]);
-		}
-		encoder.writeEndElement();
-};
-
-Name.prototype.getElementLabel = function(){
-	return NDNProtocolDTags.Name;
-};
-
-/*
- * component is a string, byte array, ArrayBuffer, Uint8Array or Name.
- * Convert to Uint8Array and add to this Name.
- * If a component is a string, encode as utf8.
- * Return this Name object to allow chaining calls to add.
- */
-Name.prototype.add = function(component){
-    var result;
-    if(typeof component == 'string')
-        result = DataUtils.stringToUtf8Array(component);
-	else if(typeof component == 'object' && component instanceof Uint8Array)
-        result = new Uint8Array(component);
-	else if(typeof component == 'object' && component instanceof ArrayBuffer) {
-        // Make a copy.  Don't use ArrayBuffer.slice since it isn't always supported.
-        result = new Uint8Array(new ArrayBuffer(component.byteLength));
-        result.set(new Uint8Array(component));
-    }
-    else if (typeof component == 'object' && component instanceof Name) {
-        var components;
-        if (component == this)
-            // special case, when we need to create a copy
-            components = this.components.slice(0, this.components.length);
-        else
-            components = component.components;
-
-        for (var i = 0; i < components.length; ++i)
-            this.components.push(new Uint8Array(components[i]));
-        return this;
-    }
-	else if(typeof component == 'object')
-        // Assume component is a byte array.  We can't check instanceof Array because
-        //   this doesn't work in JavaScript if the array comes from a different module.
-        result = new Uint8Array(component);
-	else
-		throw new Error("Cannot add Name element at index " + this.components.length +
-            ": Invalid type");
-
-    this.components.push(result);
-	return this;
-};
-
-/**
- * @brief Add component that represents a segment number
- *
- * @param number Segment number (integer is expected)
- *
- * This component has a special format handling:
- * - if number is zero, then %00 is added
- * - if number is between 1 and 255, %00%01 .. %00%FF is added
- * - ...
- */
-Name.prototype.addSegment = function(number) {
-    // step 1: figure out how many bytes will be needed
-    var bytes = 1; // at least 1 byte
-    var test_number = number;
-    while (test_number > 0) {
-        bytes ++;
-        test_number >>= 8;
-    }
-
-    var result = new Uint8Array (bytes);
-    var index = 0;
-    result[index] = 0;
-    index ++;
-    while (number > 0) {
-        result[index] = number & 0xFF;
-        number >>= 8;
-        index ++;
-    }
-
-    this.components.push(result);
-    return this;
-}
-
-// Return the escaped name string according to "NDNx URI Scheme".
-Name.prototype.to_uri = function() {
-    if (this.components.length == 0)
-        return "/";
-
-	var result = "";
-
-	for(var i = 0; i < this.components.length; ++i)
-		result += "/"+ Name.toEscapedString(this.components[i]);
-
-	return result;
-};
-
-/**
-* @brief Add component that represents a segment number
-*
-* @param number Segment number (integer is expected)
-*
-* This component has a special format handling:
-* - if number is zero, then %00 is added
-* - if number is between 1 and 255, %00%01 .. %00%FF is added
-* - ...
-*/
-Name.prototype.addSegment = function(number) {
-    var segmentNumberBigEndian = DataUtils.nonNegativeIntToBigEndian(number);
-    // Put a 0 byte in front.
-    var segmentNumberComponent = new Uint8Array(segmentNumberBigEndian.length + 1);
-    segmentNumberComponent.set(segmentNumberBigEndian, 1);
-
-    this.components.push(segmentNumberComponent);
-    return this;
-};
-
-/*
- * Return a new Name with the first nComponents components of this Name.
- */
-Name.prototype.getPrefix = function(nComponents) {
-    return new Name(this.components.slice(0, nComponents));
-}
-
-/**
- * @brief Get prefix of the name, containing less minusComponents right components
- * @param minusComponents number of components to cut from the back
- */
-Name.prototype.cut = function (minusComponents) {
-    return new Name(this.components.slice(0, this.components.length-1));
-}
-
-/*
- * Return a new ArrayBuffer of the component at i.
- */
-Name.prototype.getComponent = function(i) {
-    var result = new ArrayBuffer(this.components[i].length);
-    new Uint8Array(result).set(this.components[i]);
-    return result;
-}
-
-/*
- * The "file name" in a name is the last component that isn't blank and doesn't start with one of the
- *   special marker octets (for version, etc.).  Return the index in this.components of
- *   the file name, or -1 if not found.
- */
-Name.prototype.indexOfFileName = function() {
-    for (var i = this.components.length - 1; i >= 0; --i) {
-        var component = this.components[i];
-        if (component.length <= 0)
-            continue;
-
-        if (component[0] == 0 || component[0] == 0xC0 || component[0] == 0xC1 ||
-            (component[0] >= 0xF5 && component[0] <= 0xFF))
-            continue;
-
-        return i;
-    }
-
-    return -1;
-}
-
-/*
- * Return true if this Name has the same components as name.
- */
-Name.prototype.equalsName = function(name) {
-    if (this.components.length != name.components.length)
-        return false;
-
-    // Start from the last component because they are more likely to differ.
-    for (var i = this.components.length - 1; i >= 0; --i) {
-        if (!DataUtils.arraysEqual(this.components[i], name.components[i]))
-            return false;
-    }
-
-    return true;
-}
-
-/*
- * Find the last component in name that has a ContentDigest and return the digest value as Uint8Array,
- *   or null if not found.  See Name.getComponentContentDigestValue.
- */
-Name.prototype.getContentDigestValue = function() {
-    for (var i = this.components.length - 1; i >= 0; --i) {
-        var digestValue = Name.getComponentContentDigestValue(this.components[i]);
-        if (digestValue != null)
-           return digestValue;
-    }
-
-    return null;
-}
-
-/*
- * If component is a ContentDigest, return the digest value as a Uint8Array subarray (don't modify!).
- * If not a ContentDigest, return null.
- * A ContentDigest component is Name.ContentDigestPrefix + 32 bytes + Name.ContentDigestSuffix.
- */
-Name.getComponentContentDigestValue = function(component) {
-    var digestComponentLength = Name.ContentDigestPrefix.length + 32 + Name.ContentDigestSuffix.length;
-    // Check for the correct length and equal ContentDigestPrefix and ContentDigestSuffix.
-    if (component.length == digestComponentLength &&
-        DataUtils.arraysEqual(component.subarray(0, Name.ContentDigestPrefix.length),
-                              Name.ContentDigestPrefix) &&
-        DataUtils.arraysEqual(component.subarray
-           (component.length - Name.ContentDigestSuffix.length, component.length),
-                              Name.ContentDigestSuffix))
-       return component.subarray(Name.ContentDigestPrefix.length, Name.ContentDigestPrefix.length + 32);
-   else
-       return null;
-}
-
-// Meta GUID "%C1.M.G%C1" + ContentDigest with a 32 byte BLOB.
-Name.ContentDigestPrefix = new Uint8Array([0xc1, 0x2e, 0x4d, 0x2e, 0x47, 0xc1, 0x01, 0xaa, 0x02, 0x85]);
-Name.ContentDigestSuffix = new Uint8Array([0x00]);
-
-/*
- * Return component as an escaped string according to "NDNx URI Scheme".
- * We can't use encodeURIComponent because that doesn't encode all the characters we want to.
- */
-Name.toEscapedString = function(component) {
-    var result = "";
-    var gotNonDot = false;
-    for (var i = 0; i < component.length; ++i) {
-        if (component[i] != 0x2e) {
-            gotNonDot = true;
-            break;
-        }
-    }
-    if (!gotNonDot) {
-        // Special case for component of zero or more periods.  Add 3 periods.
-        result = "...";
-        for (var i = 0; i < component.length; ++i)
-            result += ".";
-    }
-    else {
-        for (var i = 0; i < component.length; ++i) {
-            var value = component[i];
-            // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
-            if (value >= 0x30 && value <= 0x39 || value >= 0x41 && value <= 0x5a ||
-                value >= 0x61 && value <= 0x7a || value == 0x2b || value == 0x2d ||
-                value == 0x2e || value == 0x5f)
-                result += String.fromCharCode(value);
-            else
-                result += "%" + (value < 16 ? "0" : "") + value.toString(16).toUpperCase();
-        }
-    }
-    return result;
-};
-
-/*
- * Return component as a Uint8Array by decoding the escapedString according to "NDNx URI Scheme".
- * If escapedString is "", "." or ".." then return null, which means to skip the component in the name.
- */
-Name.fromEscapedString = function(escapedString) {
-    var component = unescape(escapedString.trim());
-
-    if (component.match(/[^.]/) == null) {
-        // Special case for component of only periods.
-        if (component.length <= 2)
-            // Zero, one or two periods is illegal.  Ignore this componenent to be
-            //   consistent with the C implementation.
-            return null;
-        else
-            // Remove 3 periods.
-            return DataUtils.toNumbersFromString(component.substr(3, component.length - 3));
-    }
-    else
-        return DataUtils.toNumbersFromString(component);
-}
-
-Name.prototype.match = function(/*Name*/ name) {
-	var i_name = this.components;
-	var o_name = name.components;
-
-	// The intrest name is longer than the name we are checking it against.
-	if (i_name.length > o_name.length)
-            return false;
-
-	// Check if at least one of given components doesn't match.
-    for (var i = 0; i < i_name.length; ++i) {
-        if (!DataUtils.arraysEqual(i_name[i], o_name[i]))
-            return false;
-    }
-
-	return true;
-};
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents ContentObject Objects
- */
-var ContentObject = function ContentObject(_name,_signedInfo,_content,_signature){
-	
-	
-	if (typeof _name == 'string') {
-		this.name = new Name(_name);
-	}
-	else{
-		//TODO Check the class of _name
-		this.name = _name;
-	}
-	this.signedInfo = _signedInfo;
-	
-	if (typeof _content == 'string') {
-		this.content = DataUtils.toNumbersFromString(_content);
-	} else {
-		this.content = _content;
-	}
-	
-	this.signature = _signature;
-
-	
-	this.startSIG = null;
-	this.endSIG = null;
-	
-	//this.startSignedInfo = null;
-	this.endContent = null;
-	
-	this.rawSignatureData = null;
-};
-
-ContentObject.prototype.sign = function(){
-
-	var n1 = this.encodeObject(this.name);
-	var n2 = this.encodeObject(this.signedInfo);
-	var n3 = this.encodeContent();
-	/*console.log('sign: ');
-	console.log(n1);
-	console.log(n2);
-	console.log(n3);*/
-	
-	//var n = n1.concat(n2,n3);
-	var tempBuf = new ArrayBuffer(n1.length + n2.length + n3.length);
-	var n = new Uint8Array(tempBuf);
-	//console.log(n);
-	n.set(n1, 0);
-	//console.log(n);
-	n.set(n2, n1.length);
-	//console.log(n);
-	n.set(n3, n1.length + n2.length);
-	//console.log(n);
-	
-	if(LOG>4)console.log('Signature Data is (binary) '+n);
-	
-	if(LOG>4)console.log('Signature Data is (RawString)');
-	
-	if(LOG>4)console.log( DataUtils.toString(n) );
-	
-	//var sig = DataUtils.toString(n);
-
-	
-	var rsa = new RSAKey();
-			
-	rsa.readPrivateKeyFromPEMString(globalKeyManager.privateKey);
-	
-	//var hSig = rsa.signString(sig, "sha256");
-
-	var hSig = rsa.signByteArrayWithSHA256(n);
-
-	
-	if(LOG>4)console.log('SIGNATURE SAVED IS');
-	
-	if(LOG>4)console.log(hSig);
-	
-	if(LOG>4)console.log(  DataUtils.toNumbers(hSig.trim()));
-
-	this.signature.signature = DataUtils.toNumbers(hSig.trim());
-	
-
-};
-
-ContentObject.prototype.encodeObject = function encodeObject(obj){
-	var enc = new BinaryXMLEncoder();
- 
-	obj.to_ndnb(enc);
-	
-	var num = enc.getReducedOstream();
-
-	return num;
-
-	
-};
-
-ContentObject.prototype.encodeContent = function encodeContent(obj){
-	var enc = new BinaryXMLEncoder();
-	 
-	enc.writeElement(NDNProtocolDTags.Content, this.content);
-
-	var num = enc.getReducedOstream();
-
-	return num;
-
-	
-};
-
-ContentObject.prototype.saveRawData = function(bytes){
-	
-	var sigBits = bytes.subarray(this.startSIG, this.endSIG);
-
-	this.rawSignatureData = sigBits;
-};
-
-ContentObject.prototype.from_ndnb = function(/*XMLDecoder*/ decoder) {
-
-	// TODO VALIDATE THAT ALL FIELDS EXCEPT SIGNATURE ARE PRESENT
-
-		decoder.readStartElement(this.getElementLabel());
-
-
-		if( decoder.peekStartElement(NDNProtocolDTags.Signature) ){
-			this.signature = new Signature();
-			this.signature.from_ndnb(decoder);
-		}
-		
-		//this.endSIG = decoder.offset;
-
-		this.startSIG = decoder.offset;
-
-		this.name = new Name();
-		this.name.from_ndnb(decoder);
-		
-		//this.startSignedInfo = decoder.offset;
-	
-		
-		if( decoder.peekStartElement(NDNProtocolDTags.SignedInfo) ){
-			this.signedInfo = new SignedInfo();
-			this.signedInfo.from_ndnb(decoder);
-		}
-		
-		this.content = decoder.readBinaryElement(NDNProtocolDTags.Content);
-
-		
-		//this.endContent = decoder.offset;
-		this.endSIG = decoder.offset;
-
-		
-		decoder.readEndElement();
-		
-		this.saveRawData(decoder.istream);
-};
-
-ContentObject.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)  {
-
-	//TODO verify name, SignedInfo and Signature is present
-
-
-	encoder.writeStartElement(this.getElementLabel());
-
-	
-
-
-	if(null!=this.signature) this.signature.to_ndnb(encoder);
-	
-	
-	this.startSIG = encoder.offset;
-	
-
-	if(null!=this.name) this.name.to_ndnb(encoder);
-	
-	//this.endSIG = encoder.offset;
-	//this.startSignedInfo = encoder.offset;
-	
-	
-	if(null!=this.signedInfo) this.signedInfo.to_ndnb(encoder);
-
-	encoder.writeElement(NDNProtocolDTags.Content, this.content);
-
-	
-	this.endSIG = encoder.offset;
-	
-	//this.endContent = encoder.offset;
-	
-
-	encoder.writeEndElement();
-	
-	this.saveRawData(encoder.ostream);
-	
-};
-
-ContentObject.prototype.getElementLabel= function(){return NDNProtocolDTags.ContentObject;};
-
-/**
- * Signature
- */
-var Signature = function Signature(_witness,_signature,_digestAlgorithm) {
-	
-    this.Witness = _witness;//byte [] _witness;
-	this.signature = _signature;//byte [] _signature;
-	this.digestAlgorithm = _digestAlgorithm//String _digestAlgorithm;
-};
-
-Signature.prototype.from_ndnb =function( decoder) {
-		decoder.readStartElement(this.getElementLabel());
-		
-		if(LOG>4)console.log('STARTED DECODING SIGNATURE');
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.DigestAlgorithm)) {
-			if(LOG>4)console.log('DIGIEST ALGORITHM FOUND');
-			this.digestAlgorithm = decoder.readUTF8Element(NDNProtocolDTags.DigestAlgorithm); 
-		}
-		if (decoder.peekStartElement(NDNProtocolDTags.Witness)) {
-			if(LOG>4)console.log('WITNESS FOUND');
-			this.Witness = decoder.readBinaryElement(NDNProtocolDTags.Witness); 
-		}
-		
-		//FORCE TO READ A SIGNATURE
-
-			if(LOG>4)console.log('SIGNATURE FOUND');
-			this.signature = decoder.readBinaryElement(NDNProtocolDTags.SignatureBits);
-
-		decoder.readEndElement();
-	
-};
-
-
-Signature.prototype.to_ndnb= function( encoder){
-    	
-	if (!this.validate()) {
-		throw new Error("Cannot encode: field values missing.");
-	}
-	
-	encoder.writeStartElement(this.getElementLabel());
-	
-	if ((null != this.digestAlgorithm) && (!this.digestAlgorithm.equals(NDNDigestHelper.DEFAULT_DIGEST_ALGORITHM))) {
-		encoder.writeElement(NDNProtocolDTags.DigestAlgorithm, OIDLookup.getDigestOID(this.DigestAlgorithm));
-	}
-	
-	if (null != this.Witness) {
-		// needs to handle null witness
-		encoder.writeElement(NDNProtocolDTags.Witness, this.Witness);
-	}
-
-	encoder.writeElement(NDNProtocolDTags.SignatureBits, this.signature);
-
-	encoder.writeEndElement();   		
-};
-
-Signature.prototype.getElementLabel = function() { return NDNProtocolDTags.Signature; };
-
-
-Signature.prototype.validate = function() {
-		return null != this.signature;
-};
-
-
-/**
- * SignedInfo
- */
-var ContentType = {DATA:0, ENCR:1, GONE:2, KEY:3, LINK:4, NACK:5};
-var ContentTypeValue = {0:0x0C04C0, 1:0x10D091,2:0x18E344,3:0x28463F,4:0x2C834A,5:0x34008A};
-var ContentTypeValueReverse = {0x0C04C0:0, 0x10D091:1,0x18E344:2,0x28463F:3,0x2C834A:4,0x34008A:5};
-
-var SignedInfo = function SignedInfo(_publisher,_timestamp,_type,_locator,_freshnessSeconds,_finalBlockID){
-
-	//TODO, Check types
-
-    this.publisher = _publisher; //publisherPublicKeyDigest
-    this.timestamp=_timestamp; // NDN Time
-    this.type=_type; // ContentType
-    this.locator =_locator;//KeyLocator
-    this.freshnessSeconds =_freshnessSeconds; // Integer
-    this.finalBlockID=_finalBlockID; //byte array
-    
-    // SWT: merge setFields() method into constructor
-    this.setFields();
-
-};
-
-SignedInfo.prototype.setFields = function(){
-	//BASE64 -> RAW STRING
-	
-	//this.locator = new KeyLocator(  DataUtils.toNumbersFromString(stringCertificate)  ,KeyLocatorType.CERTIFICATE );
-	
-	var publicKeyHex = globalKeyManager.publicKey;
-
-	if(LOG>4)console.log('PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ');
-	if(LOG>4)console.log(publicKeyHex);
-	
-	var publicKeyBytes = DataUtils.toNumbers(globalKeyManager.publicKey) ; 
-
-	
-
-	//var stringCertificate = DataUtils.base64toString(globalKeyManager.certificate);
-	
-	//if(LOG>3)console.log('string Certificate is '+stringCertificate);
-
-	//HEX -> BYTE ARRAY
-	//var publisherkey = DataUtils.toNumbers(hex_sha256(stringCertificate));
-	
-	//if(LOG>3)console.log('publisher key is ');
-	//if(LOG>3)console.log(publisherkey);
-	
-	var publisherKeyDigest = hex_sha256_from_bytes(publicKeyBytes);
-
-	this.publisher = new PublisherPublicKeyDigest(  DataUtils.toNumbers(  publisherKeyDigest )  );
-	
-	//this.publisher = new PublisherPublicKeyDigest(publisherkey);
-
-	var d = new Date();
-	
-	var time = d.getTime();
-	
-
-    this.timestamp = new NDNTime( time );
-    
-    if(LOG>4)console.log('TIME msec is');
-
-    if(LOG>4)console.log(this.timestamp.msec);
-
-    //DATA
-	this.type = 0;//0x0C04C0;//ContentTypeValue[ContentType.DATA];
-	
-	//if(LOG>4)console.log('toNumbersFromString(stringCertificate) '+DataUtils.toNumbersFromString(stringCertificate));
-	
-	if(LOG>4)console.log('PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ');
-	if(LOG>4)console.log(publicKeyBytes);
-
-	this.locator = new KeyLocator(  publicKeyBytes  ,KeyLocatorType.KEY );
-
-	//this.locator = new KeyLocator(  DataUtils.toNumbersFromString(stringCertificate)  ,KeyLocatorType.CERTIFICATE );
-
-};
-
-SignedInfo.prototype.from_ndnb = function( decoder){
-
-		decoder.readStartElement( this.getElementLabel() );
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)) {
-			if(LOG>4)console.log('DECODING PUBLISHER KEY');
-			this.publisher = new PublisherPublicKeyDigest();
-			this.publisher.from_ndnb(decoder);
-		}
-
-		if (decoder.peekStartElement(NDNProtocolDTags.Timestamp)) {
-			if(LOG>4)console.log('DECODING TIMESTAMP');
-			this.timestamp = decoder.readDateTime(NDNProtocolDTags.Timestamp);
-		}
-
-		if (decoder.peekStartElement(NDNProtocolDTags.Type)) {
-			var binType = decoder.readBinaryElement(NDNProtocolDTags.Type);//byte [] 
-		
-			
-			//TODO Implement type of Key Reading
-			
-			if(LOG>4)console.log('Binary Type of of Signed Info is '+binType);
-
-			this.type = binType;
-			
-			
-			//TODO Implement type of Key Reading
-			
-			
-			if (null == this.type) {
-				throw new Error("Cannot parse signedInfo type: bytes.");
-			}
-			
-		} else {
-			this.type = ContentType.DATA; // default
-		}
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.FreshnessSeconds)) {
-			this.freshnessSeconds = decoder.readIntegerElement(NDNProtocolDTags.FreshnessSeconds);
-			if(LOG>4)console.log('FRESHNESS IN SECONDS IS '+ this.freshnessSeconds);
-		}
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.FinalBlockID)) {
-			if(LOG>4)console.log('DECODING FINAL BLOCKID');
-			this.finalBlockID = decoder.readBinaryElement(NDNProtocolDTags.FinalBlockID);
-		}
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.KeyLocator)) {
-			if(LOG>4)console.log('DECODING KEY LOCATOR');
-			this.locator = new KeyLocator();
-			this.locator.from_ndnb(decoder);
-		}
-				
-		decoder.readEndElement();
-};
-
-SignedInfo.prototype.to_ndnb = function( encoder)  {
-		if (!this.validate()) {
-			throw new Error("Cannot encode : field values missing.");
-		}
-		encoder.writeStartElement(this.getElementLabel());
-		
-		if (null!=this.publisher) {
-			if(LOG>3) console.log('ENCODING PUBLISHER KEY' + this.publisher.publisherPublicKeyDigest);
-
-			this.publisher.to_ndnb(encoder);
-		}
-
-		if (null!=this.timestamp) {
-			encoder.writeDateTime(NDNProtocolDTags.Timestamp, this.timestamp );
-		}
-		
-		if (null!=this.type && this.type !=0) {
-			
-			encoder.writeElement(NDNProtocolDTags.type, this.type);
-		}
-		
-		if (null!=this.freshnessSeconds) {
-			encoder.writeElement(NDNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
-		}
-
-		if (null!=this.finalBlockID) {
-			encoder.writeElement(NDNProtocolDTags.FinalBlockID, this.finalBlockID);
-		}
-
-		if (null!=this.locator) {
-			this.locator.to_ndnb(encoder);
-		}
-
-		encoder.writeEndElement();   		
-};
-	
-SignedInfo.prototype.valueToType = function(){
-	//for (Entry<byte [], ContentType> entry : ContentValueTypes.entrySet()) {
-		//if (Arrays.equals(value, entry.getKey()))
-			//return entry.getValue();
-		//}
-	return null;
-	
-};
-
-SignedInfo.prototype.getElementLabel = function() { 
-	return NDNProtocolDTags.SignedInfo;
-};
-
-SignedInfo.prototype.validate = function() {
-		// We don't do partial matches any more, even though encoder/decoder
-		// is still pretty generous.
-		if (null ==this.publisher || null==this.timestamp ||null== this.locator)
-			return false;
-		return true;
-};
-/*
- * Date Format 1.2.3
- * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
- * MIT license
- *
- * Includes enhancements by Scott Trenda <scott.trenda.net>
- * and Kris Kowal <cixar.com/~kris.kowal/>
- *
- * Accepts a date, a mask, or a date and a mask.
- * Returns a formatted version of the given date.
- * The date defaults to the current date/time.
- * The mask defaults to dateFormat.masks.default.
- */
-
-var DateFormat = function () {
-	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
-		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
-		timezoneClip = /[^-+\dA-Z]/g,
-		pad = function (val, len) {
-			val = String(val);
-			len = len || 2;
-			while (val.length < len) val = "0" + val;
-			return val;
-		};
-
-	// Regexes and supporting functions are cached through closure
-	return function (date, mask, utc) {
-		var dF = dateFormat;
-
-		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
-		if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
-			mask = date;
-			date = undefined;
-		}
-
-		// Passing date through Date applies Date.parse, if necessary
-		date = date ? new Date(date) : new Date;
-		if (isNaN(date)) throw SyntaxError("invalid date");
-
-		mask = String(dF.masks[mask] || mask || dF.masks["default"]);
-
-		// Allow setting the utc argument via the mask
-		if (mask.slice(0, 4) == "UTC:") {
-			mask = mask.slice(4);
-			utc = true;
-		}
-
-		var	_ = utc ? "getUTC" : "get",
-			d = date[_ + "Date"](),
-			D = date[_ + "Day"](),
-			m = date[_ + "Month"](),
-			y = date[_ + "FullYear"](),
-			H = date[_ + "Hours"](),
-			M = date[_ + "Minutes"](),
-			s = date[_ + "Seconds"](),
-			L = date[_ + "Milliseconds"](),
-			o = utc ? 0 : date.getTimezoneOffset(),
-			flags = {
-				d:    d,
-				dd:   pad(d),
-				ddd:  dF.i18n.dayNames[D],
-				dddd: dF.i18n.dayNames[D + 7],
-				m:    m + 1,
-				mm:   pad(m + 1),
-				mmm:  dF.i18n.monthNames[m],
-				mmmm: dF.i18n.monthNames[m + 12],
-				yy:   String(y).slice(2),
-				yyyy: y,
-				h:    H % 12 || 12,
-				hh:   pad(H % 12 || 12),
-				H:    H,
-				HH:   pad(H),
-				M:    M,
-				MM:   pad(M),
-				s:    s,
-				ss:   pad(s),
-				l:    pad(L, 3),
-				L:    pad(L > 99 ? Math.round(L / 10) : L),
-				t:    H < 12 ? "a"  : "p",
-				tt:   H < 12 ? "am" : "pm",
-				T:    H < 12 ? "A"  : "P",
-				TT:   H < 12 ? "AM" : "PM",
-				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
-				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
-				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
-			};
-
-		return mask.replace(token, function ($0) {
-			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
-		});
-	};
-}();
-
-// Some common format strings
-DateFormat.masks = {
-	"default":      "ddd mmm dd yyyy HH:MM:ss",
-	shortDate:      "m/d/yy",
-	mediumDate:     "mmm d, yyyy",
-	longDate:       "mmmm d, yyyy",
-	fullDate:       "dddd, mmmm d, yyyy",
-	shortTime:      "h:MM TT",
-	mediumTime:     "h:MM:ss TT",
-	longTime:       "h:MM:ss TT Z",
-	isoDate:        "yyyy-mm-dd",
-	isoTime:        "HH:MM:ss",
-	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
-	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
-};
-
-// Internationalization strings
-DateFormat.i18n = {
-	dayNames: [
-		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
-		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
-	],
-	monthNames: [
-		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
-	]
-};
-
-// For convenience...
-Date.prototype.format = function (mask, utc) {
-	return dateFormat(this, mask, utc);
-};
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Interest Objects
- */
-
-// _interestLifetime is in milliseconds.
-var Interest = function Interest
-   (_name, _faceInstance, _minSuffixComponents, _maxSuffixComponents, _publisherPublicKeyDigest, _exclude, 
-    _childSelector, _answerOriginKind, _scope, _interestLifetime, _nonce) {
-		
-	this.name = _name;
-	this.faceInstance = _faceInstance;
-	this.maxSuffixComponents = _maxSuffixComponents;
-	this.minSuffixComponents = _minSuffixComponents;
-	
-	this.publisherPublicKeyDigest = _publisherPublicKeyDigest;
-	this.exclude = _exclude;
-	this.childSelector = _childSelector;
-	this.answerOriginKind = _answerOriginKind;
-	this.scope = _scope;
-	this.interestLifetime = _interestLifetime;  // milli seconds
-	this.nonce = _nonce;	
-};
-
-Interest.RECURSIVE_POSTFIX = "*";
-
-Interest.CHILD_SELECTOR_LEFT = 0;
-Interest.CHILD_SELECTOR_RIGHT = 1;
-Interest.ANSWER_CONTENT_STORE = 1;
-Interest.ANSWER_GENERATED = 2;
-Interest.ANSWER_STALE = 4;		// Stale answer OK
-Interest.MARK_STALE = 16;		// Must have scope 0.  Michael calls this a "hack"
-
-Interest.DEFAULT_ANSWER_ORIGIN_KIND = Interest.ANSWER_CONTENT_STORE | Interest.ANSWER_GENERATED;
-
-
-Interest.prototype.from_ndnb = function(/*XMLDecoder*/ decoder) {
-
-		decoder.readStartElement(NDNProtocolDTags.Interest);
-
-		this.name = new Name();
-		this.name.from_ndnb(decoder);
-
-		if (decoder.peekStartElement(NDNProtocolDTags.MinSuffixComponents))
-			this.minSuffixComponents = decoder.readIntegerElement(NDNProtocolDTags.MinSuffixComponents);
-
-		if (decoder.peekStartElement(NDNProtocolDTags.MaxSuffixComponents)) 
-			this.maxSuffixComponents = decoder.readIntegerElement(NDNProtocolDTags.MaxSuffixComponents);
-			
-		if (decoder.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)) {
-			this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
-			this.publisherPublicKeyDigest.from_ndnb(decoder);
-		}
-
-		if (decoder.peekStartElement(NDNProtocolDTags.Exclude)) {
-			this.exclude = new Exclude();
-			this.exclude.from_ndnb(decoder);
-		}
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.ChildSelector))
-			this.childSelector = decoder.readIntegerElement(NDNProtocolDTags.ChildSelector);
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.AnswerOriginKind))
-			this.answerOriginKind = decoder.readIntegerElement(NDNProtocolDTags.AnswerOriginKind);
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.Scope))
-			this.scope = decoder.readIntegerElement(NDNProtocolDTags.Scope);
-
-		if (decoder.peekStartElement(NDNProtocolDTags.InterestLifetime))
-			this.interestLifetime = 1000.0 * DataUtils.bigEndianToUnsignedInt
-                (decoder.readBinaryElement(NDNProtocolDTags.InterestLifetime)) / 4096;
-		
-		if (decoder.peekStartElement(NDNProtocolDTags.Nonce))
-			this.nonce = decoder.readBinaryElement(NDNProtocolDTags.Nonce);
-		
-		decoder.readEndElement();
-};
-
-Interest.prototype.to_ndnb = function(/*XMLEncoder*/ encoder){
-		//Could check if name is present
-		
-		encoder.writeStartElement(NDNProtocolDTags.Interest);
-		
-		this.name.to_ndnb(encoder);
-	
-		if (null != this.minSuffixComponents) 
-			encoder.writeElement(NDNProtocolDTags.MinSuffixComponents, this.minSuffixComponents);	
-
-		if (null != this.maxSuffixComponents) 
-			encoder.writeElement(NDNProtocolDTags.MaxSuffixComponents, this.maxSuffixComponents);
-
-		if (null != this.publisherPublicKeyDigest)
-			this.publisherPublicKeyDigest.to_ndnb(encoder);
-		
-		if (null != this.exclude)
-			this.exclude.to_ndnb(encoder);
-		
-		if (null != this.childSelector) 
-			encoder.writeElement(NDNProtocolDTags.ChildSelector, this.childSelector);
-
-		if (this.DEFAULT_ANSWER_ORIGIN_KIND != this.answerOriginKind && this.answerOriginKind!=null) 
-			encoder.writeElement(NDNProtocolDTags.AnswerOriginKind, this.answerOriginKind);
-		
-		if (null != this.scope) 
-			encoder.writeElement(NDNProtocolDTags.Scope, this.scope);
-		
-		if (null != this.interestLifetime) 
-			encoder.writeElement(NDNProtocolDTags.InterestLifetime, 
-                DataUtils.nonNegativeIntToBigEndian((this.interestLifetime / 1000.0) * 4096));
-		
-		if (null != this.nonce)
-			encoder.writeElement(NDNProtocolDTags.Nonce, this.nonce);
-		
-		encoder.writeEndElement();
-
-};
-
-/*
- * Return true if this.name.match(name) and the name conforms to the interest selectors.
- */
-Interest.prototype.matches_name = function(/*Name*/ name) {
-    if (!this.name.match(name))
-        return false;
-    
-    if (this.minSuffixComponents != null &&
-        // Add 1 for the implicit digest.
-        !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
-        return false;
-    if (this.maxSuffixComponents != null &&
-        // Add 1 for the implicit digest.
-        !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
-        return false;
-    if (this.exclude != null && name.components.length > this.name.components.length &&
-        this.exclude.matches(name.components[this.name.components.length]))
-        return false;
-    
-    return true;
-};
-
-/*
- * Return a new Interest with the same fields as this Interest.  
- * Note: This does NOT make a deep clone of the name, exclue or other objects.
- */
-Interest.prototype.clone = function() {
-    return new Interest
-       (this.name, this.faceInstance, this.minSuffixComponents, this.maxSuffixComponents, 
-        this.publisherPublicKeyDigest, this.exclude, this.childSelector, this.answerOriginKind, 
-        this.scope, this.interestLifetime, this.nonce);
-};
-
-/*
- * Handle the interest Exclude element.
- * _values is an array where each element is either Uint8Array component or Exclude.ANY.
- */
-var Exclude = function Exclude(_values) { 
-	this.values = (_values || []);
-}
-
-Exclude.ANY = "*";
-
-Exclude.prototype.from_ndnb = function(/*XMLDecoder*/ decoder) {
-	decoder.readStartElement(NDNProtocolDTags.Exclude);
-
-	while (true) {
-        if (decoder.peekStartElement(NDNProtocolDTags.Component))
-            this.values.push(decoder.readBinaryElement(NDNProtocolDTags.Component));
-        else if (decoder.peekStartElement(NDNProtocolDTags.Any)) {
-            decoder.readStartElement(NDNProtocolDTags.Any);
-            decoder.readEndElement();
-            this.values.push(Exclude.ANY);
-        }
-        else if (decoder.peekStartElement(NDNProtocolDTags.Bloom)) {
-            // Skip the Bloom and treat it as Any.
-            decoder.readBinaryElement(NDNProtocolDTags.Bloom);
-            this.values.push(Exclude.ANY);
-        }
-        else
-            break;
-	}
-    
-    decoder.readEndElement();
-};
-
-Exclude.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)  {
-	if (this.values == null || this.values.length == 0)
-		return;
-
-	encoder.writeStartElement(NDNProtocolDTags.Exclude);
-    
-    // TODO: Do we want to order the components (except for ANY)?
-    for (var i = 0; i < this.values.length; ++i) {
-        if (this.values[i] == Exclude.ANY) {
-            encoder.writeStartElement(NDNProtocolDTags.Any);
-            encoder.writeEndElement();
-        }
-        else
-            encoder.writeElement(NDNProtocolDTags.Component, this.values[i]);
-    }
-
-	encoder.writeEndElement();
-};
-
-/*
- * Return a string with elements separated by "," and Exclude.ANY shown as "*". 
- */
-Exclude.prototype.to_uri = function() {
-	if (this.values == null || this.values.length == 0)
-		return "";
-
-    var result = "";
-    for (var i = 0; i < this.values.length; ++i) {
-        if (i > 0)
-            result += ",";
-        
-        if (this.values[i] == Exclude.ANY)
-            result += "*";
-        else
-            result += Name.toEscapedString(this.values[i]);
-    }
-    return result;
-};
-
-/*
- * Return true if the component matches any of the exclude criteria.
- */
-Exclude.prototype.matches = function(/*Uint8Array*/ component) {
-    for (var i = 0; i < this.values.length; ++i) {
-        if (this.values[i] == Exclude.ANY) {
-            var lowerBound = null;
-            if (i > 0)
-                lowerBound = this.values[i - 1];
-            
-            // Find the upper bound, possibly skipping over multiple ANY in a row.
-            var iUpperBound;
-            var upperBound = null;
-            for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
-                if (this.values[iUpperBound] != Exclude.ANY) {
-                    upperBound = this.values[iUpperBound];
-                    break;
-                }
-            }
-            
-            // If lowerBound != null, we already checked component equals lowerBound on the last pass.
-            // If upperBound != null, we will check component equals upperBound on the next pass.
-            if (upperBound != null) {
-                if (lowerBound != null) {
-                    if (Exclude.compareComponents(component, lowerBound) > 0 &&
-                        Exclude.compareComponents(component, upperBound) < 0)
-                        return true;
-                }
-                else {
-                    if (Exclude.compareComponents(component, upperBound) < 0)
-                        return true;
-                }
-                
-                // Make i equal iUpperBound on the next pass.
-                i = iUpperBound - 1;
-            }
-            else {
-                if (lowerBound != null) {
-                    if (Exclude.compareComponents(component, lowerBound) > 0)
-                        return true;
-                }
-                else
-                    // this.values has only ANY.
-                    return true;
-            }
-        }
-        else {
-            if (DataUtils.arraysEqual(component, this.values[i]))
-                return true;
-        }
-    }
-    
-    return false;
-};
-
-/*
- * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
- * A component is less if it is shorter, otherwise if equal length do a byte comparison.
- */
-Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
-    if (component1.length < component2.length)
-        return -1;
-    if (component1.length > component2.length)
-        return 1;
-    
-    for (var i = 0; i < component1.length; ++i) {
-        if (component1[i] < component2[i])
-            return -1;
-        if (component1[i] > component2[i])
-            return 1;
-    }
-
-    return 0;
-};
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Key Objects
- */
-
-var Key = function Key(){
-    /* TODO: Port from PyNDN:
-	generateRSA()
-	privateToDER()
-	publicToDER()
-	privateToPEM()
-	publicToPEM()
-	fromDER()
-	fromPEM()
+}(this, function() {
+    /**
+     * Main function giving a function stack trace with a forced or passed in Error
+     *
+     * @cfg {Error} e The error to create a stacktrace from (optional)
+     * @cfg {Boolean} guess If we should try to resolve the names of anonymous functions
+     * @return {Array} of Strings with functions, lines, files, and arguments where possible
      */
-}
-
-/**
- * KeyLocator
- */
-var KeyLocatorType = {
-	KEY:1,
-	CERTIFICATE:2,
-	KEYNAME:3
-};
-
-var KeyLocator = function KeyLocator(_input,_type){ 
-
-    this.type = _type;
-    
-    if (_type == KeyLocatorType.KEYNAME){
-    	if (LOG>3) console.log('KeyLocator: SET KEYNAME');
-    	this.keyName = _input;
-    }
-    else if (_type == KeyLocatorType.KEY){
-    	if (LOG>3) console.log('KeyLocator: SET KEY');
-    	this.publicKey = _input;
-    }
-    else if (_type == KeyLocatorType.CERTIFICATE){
-    	if (LOG>3) console.log('KeyLocator: SET CERTIFICATE');
-    	this.certificate = _input;
+    function printStackTrace(options) {
+        options = options || {guess: true};
+        var ex = options.e || null, guess = !!options.guess, mode = options.mode || null;
+        var p = new printStackTrace.implementation(), result = p.run(ex, mode);
+        return (guess) ? p.guessAnonymousFunctions(result) : result;
     }
 
-};
+    printStackTrace.implementation = function() {
+    };
 
-KeyLocator.prototype.from_ndnb = function(decoder) {
+    printStackTrace.implementation.prototype = {
+        /**
+         * @param {Error} [ex] The error to create a stacktrace from (optional)
+         * @param {String} [mode] Forced mode (optional, mostly for unit tests)
+         */
+        run: function(ex, mode) {
+            ex = ex || this.createException();
+            mode = mode || this.mode(ex);
+            if (mode === 'other') {
+                return this.other(arguments.callee);
+            } else {
+                return this[mode](ex);
+            }
+        },
 
-	decoder.readStartElement(this.getElementLabel());
+        createException: function() {
+            try {
+                this.undef();
+            } catch (e) {
+                return e;
+            }
+        },
 
-	if (decoder.peekStartElement(NDNProtocolDTags.Key)) {
-		try {
-			var encodedKey = decoder.readBinaryElement(NDNProtocolDTags.Key);
-			// This is a DER-encoded SubjectPublicKeyInfo.
-			
-			//TODO FIX THIS, This should create a Key Object instead of keeping bytes
+        /**
+         * Mode could differ for different exception, e.g.
+         * exceptions in Chrome may or may not have arguments or stack.
+         *
+         * @return {String} mode of operation for the exception
+         */
+        mode: function(e) {
+            if (typeof window !== 'undefined' && window.navigator.userAgent.indexOf('PhantomJS') > -1) {
+                return 'phantomjs';
+            }
 
-			this.publicKey =   encodedKey;//CryptoUtil.getPublicKey(encodedKey);
-			this.type = KeyLocatorType.KEY;
-			
+            if (e['arguments'] && e.stack) {
+                return 'chrome';
+            }
 
-			if(LOG>4) console.log('PUBLIC KEY FOUND: '+ this.publicKey);
-			//this.publicKey = encodedKey;
-			
-			
-		} catch (e) {
-			throw new Error("Cannot parse key: ", e);
-		} 
+            if (e.stack && e.sourceURL) {
+                return 'safari';
+            }
 
-		if (null == this.publicKey) {
-			throw new Error("Cannot parse key: ");
-		}
+            if (e.stack && e.number) {
+                return 'ie';
+            }
 
-	} else if ( decoder.peekStartElement(NDNProtocolDTags.Certificate)) {
-		try {
-			var encodedCert = decoder.readBinaryElement(NDNProtocolDTags.Certificate);
-			
-			/*
-			 * Certificates not yet working
-			 */
-			
-			//CertificateFactory factory = CertificateFactory.getInstance("X.509");
-			//this.certificate = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(encodedCert));
-			
+            if (e.stack && e.fileName) {
+                return 'firefox';
+            }
 
-			this.certificate = encodedCert;
-			this.type = KeyLocatorType.CERTIFICATE;
-
-			if(LOG>4) console.log('CERTIFICATE FOUND: '+ this.certificate);
-			
-		} catch ( e) {
-			throw new Error("Cannot decode certificate: " +  e);
-		}
-		if (null == this.certificate) {
-			throw new Error("Cannot parse certificate! ");
-		}
-	} else  {
-		this.type = KeyLocatorType.KEYNAME;
-		
-		this.keyName = new KeyName();
-		this.keyName.from_ndnb(decoder);
-	}
-	decoder.readEndElement();
-};
-	
-
-KeyLocator.prototype.to_ndnb = function( encoder) {
-	
-	if(LOG>4) console.log('type is is ' + this.type);
-	//TODO Check if Name is missing
-	if (!this.validate()) {
-		throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
-	}
-
-	
-	//TODO FIX THIS TOO
-	encoder.writeStartElement(this.getElementLabel());
-	
-	if (this.type == KeyLocatorType.KEY) {
-		if(LOG>5)console.log('About to encode a public key' +this.publicKey);
-		encoder.writeElement(NDNProtocolDTags.Key, this.publicKey);
-		
-	} else if (this.type == KeyLocatorType.CERTIFICATE) {
-		
-		try {
-			encoder.writeElement(NDNProtocolDTags.Certificate, this.certificate);
-		} catch ( e) {
-			throw new Error("CertificateEncodingException attempting to write key locator: " + e);
-		}
-		
-	} else if (this.type == KeyLocatorType.KEYNAME) {
-		
-		this.keyName.to_ndnb(encoder);
-	}
-	encoder.writeEndElement();
-	
-};
-
-KeyLocator.prototype.getElementLabel = function() {
-	return NDNProtocolDTags.KeyLocator; 
-};
-
-KeyLocator.prototype.validate = function() {
-	return (  (null != this.keyName) || (null != this.publicKey) || (null != this.certificate)   );
-};
-
-/**
- * KeyName is only used by KeyLocator.
- */
-var KeyName = function KeyName() {
-	this.contentName = this.contentName;  //contentName
-	this.publisherID = this.publisherID;  //publisherID
-
-};
-
-KeyName.prototype.from_ndnb=function( decoder){
-	
-
-	decoder.readStartElement(this.getElementLabel());
-
-	this.contentName = new Name();
-	this.contentName.from_ndnb(decoder);
-	
-	if(LOG>4) console.log('KEY NAME FOUND: ');
-	
-	if ( PublisherID.peek(decoder) ) {
-		this.publisherID = new PublisherID();
-		this.publisherID.from_ndnb(decoder);
-	}
-	
-	decoder.readEndElement();
-};
-
-KeyName.prototype.to_ndnb = function( encoder) {
-	if (!this.validate()) {
-		throw new Error("Cannot encode : field values missing.");
-	}
-	
-	encoder.writeStartElement(this.getElementLabel());
-	
-	this.contentName.to_ndnb(encoder);
-	if (null != this.publisherID)
-		this.publisherID.to_ndnb(encoder);
-
-	encoder.writeEndElement();   		
-};
-	
-KeyName.prototype.getElementLabel = function() { return NDNProtocolDTags.KeyName; };
-
-KeyName.prototype.validate = function() {
-		// DKS -- do we do recursive validation?
-		// null signedInfo ok
-		return (null != this.contentName);
-};
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Publisher and PublisherType Objects
- */
-
-
-var PublisherType = function PublisherType(_tag){
-    	this.KEY =(NDNProtocolDTags.PublisherPublicKeyDigest);
-    	this.CERTIFICATE= (NDNProtocolDTags.PublisherCertificateDigest);
-    	this.ISSUER_KEY=	(NDNProtocolDTags.PublisherIssuerKeyDigest);
-    	this.ISSUER_CERTIFICATE	=(NDNProtocolDTags.PublisherIssuerCertificateDigest);
-
-    	this.Tag = _tag;
-}; 
-
-var isTypeTagVal = function(tagVal) {
-		if ((tagVal == NDNProtocolDTags.PublisherPublicKeyDigest) ||
-			(tagVal == NDNProtocolDTags.PublisherCertificateDigest) ||
-			(tagVal == NDNProtocolDTags.PublisherIssuerKeyDigest) ||
-			(tagVal == NDNProtocolDTags.PublisherIssuerCertificateDigest)) {
-			return true;
-		}
-		return false;
-};
-
-
-
-
-var PublisherID = function PublisherID() {
-
-	this.PUBLISHER_ID_DIGEST_ALGORITHM = "SHA-256";
-	this.PUBLISHER_ID_LEN = 256/8;
-    
-	//TODO, implement publisherID creation and key creation
-
-    //TODO implement generatePublicKeyDigest
-    this.publisherID =null;//= generatePublicKeyDigest(key);//ByteArray
-    
-    //TODO implement generate key
-    //CryptoUtil.generateKeyID(PUBLISHER_ID_DIGEST_ALGORITHM, key);
-    this.publisherType = null;//isIssuer ? PublisherType.ISSUER_KEY : PublisherType.KEY;//publisher Type
-    
-};
-
-
-PublisherID.prototype.from_ndnb = function(decoder) {
-		
-		// We have a choice here of one of 4 binary element types.
-		var nextTag = decoder.peekStartElementAsLong();
-		
-		if (null == nextTag) {
-			throw new Error("Cannot parse publisher ID.");
-		} 
-		
-		this.publisherType = new PublisherType(nextTag); 
-		
-		if (!isTypeTagVal(nextTag)) {
-			throw new Error("Invalid publisher ID, got unexpected type: " + nextTag);
-		}
-		this.publisherID = decoder.readBinaryElement(nextTag);
-		if (null == this.publisherID) {
-			throw new ContentDecodingException(new Error("Cannot parse publisher ID of type : " + nextTag + "."));
-		}
-};
-
-PublisherID.prototype.to_ndnb = function(encoder) {
-	if (!this.validate()) {
-		throw new Error("Cannot encode " + this.getClass().getName() + ": field values missing.");
-	}
-
-	encoder.writeElement(this.getElementLabel(), this.publisherID);
-};
-	
-PublisherID.peek = function(/* XMLDecoder */ decoder) {
-
-		//Long
-		var nextTag = decoder.peekStartElementAsLong();
-		
-		if (null == nextTag) {
-			// on end element
-			return false;
-		}
-		return (isTypeTagVal(nextTag));
-	};
-
-PublisherID.prototype.getElementLabel = function() { 
-	return this.publisherType.Tag;
-};
-
-PublisherID.prototype.validate = function(){
-	return ((null != id() && (null != type())));
-};
-
-
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents PublisherPublicKeyDigest Objects
- */
-var PublisherPublicKeyDigest = function PublisherPublicKeyDigest(_pkd){ 
-	
- 	 //this.PUBLISHER_ID_LEN = 256/8;
-	 this.PUBLISHER_ID_LEN = 512/8;
- 	 
-
-	 this.publisherPublicKeyDigest = _pkd;
- 	 //if( typeof _pkd == "object") this.publisherPublicKeyDigest = _pkd; // Byte Array
- 	 //else if( typeof _pkd == "PublicKey") ;//TODO...
-    
-};
-
-PublisherPublicKeyDigest.prototype.from_ndnb = function( decoder) {		
-
-		this.publisherPublicKeyDigest = decoder.readBinaryElement(this.getElementLabel());
-		
-		if(LOG>4)console.log('Publisher public key digest is ' + this.publisherPublicKeyDigest);
-
-		if (null == this.publisherPublicKeyDigest) {
-			throw new Error("Cannot parse publisher key digest.");
-		}
-		
-		//TODO check if the length of the PublisherPublicKeyDigest is correct ( Security reason)
-
-		if (this.publisherPublicKeyDigest.length != this.PUBLISHER_ID_LEN) {
-			if (LOG > 0)
-                console.log('LENGTH OF PUBLISHER ID IS WRONG! Expected ' + this.PUBLISHER_ID_LEN + ", got " + this.publisherPublicKeyDigest.length);
-			
-			//this.publisherPublicKeyDigest = new PublisherPublicKeyDigest(this.PublisherPublicKeyDigest).PublisherKeyDigest;		
-		}
-	};
-
-PublisherPublicKeyDigest.prototype.to_ndnb= function( encoder) {
-		//TODO Check that the ByteArray for the key is present
-		if (!this.validate()) {
-			throw new Error("Cannot encode : field values missing.");
-		}
-		if(LOG>3) console.log('PUBLISHER KEY DIGEST IS'+this.publisherPublicKeyDigest);
-		encoder.writeElement(this.getElementLabel(), this.publisherPublicKeyDigest);
-};
-	
-PublisherPublicKeyDigest.prototype.getElementLabel = function() { return NDNProtocolDTags.PublisherPublicKeyDigest; };
-
-PublisherPublicKeyDigest.prototype.validate =function() {
-		return (null != this.publisherPublicKeyDigest);
-};
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Face Instances
- */
-
-var NetworkProtocol = { TCP:6, UDP:17};
-
-var FaceInstance  = function FaceInstance(
-	    _action,
-		_publisherPublicKeyDigest,
-		_faceID,
-		_ipProto,
-		_host,
-		_port,
-		_multicastInterface,
-		_multicastTTL,
-		_freshnessSeconds){
-	
-
-	this.action = _action;
-	this.publisherPublicKeyDigest = _publisherPublicKeyDigest;
-	this.faceID = _faceID;
-	this.ipProto = _ipProto;
-	this.host = _host;
-	this.Port = _port;
-	this.multicastInterface =_multicastInterface;
-	this.multicastTTL =_multicastTTL;
-	this.freshnessSeconds = _freshnessSeconds;
-	
-	//action           ::= ("newface" | "destroyface" | "queryface")
-	//publisherPublicKeyDigest ::= SHA-256 digest
-	//faceID           ::= nonNegativeInteger
-	//ipProto          ::= nonNegativeInteger [IANA protocol number, 6=TCP, 17=UDP]
-	//Host             ::= textual representation of numeric IPv4 or IPv6 address
-	//Port             ::= nonNegativeInteger [1..65535]
-	//MulticastInterface ::= textual representation of numeric IPv4 or IPv6 address
-	//MulticastTTL     ::= nonNegativeInteger [1..255]
-	//freshnessSeconds ::= nonNegativeInteger
-
-};
-
-/**
- * Used by NetworkObject to decode the object from a network stream.
- */
-FaceInstance.prototype.from_ndnb = function(//XMLDecoder 
-	decoder) {
-
-	decoder.readStartElement(this.getElementLabel());
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.Action)) {
-		
-		this.action = decoder.readUTF8Element(NDNProtocolDTags.Action);
-		
-	}
-	if (decoder.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)) {
-		
-		this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
-		this.publisherPublicKeyDigest.from_ndnb(decoder);
-		
-	}
-	if (decoder.peekStartElement(NDNProtocolDTags.FaceID)) {
-		
-		this.faceID = decoder.readIntegerElement(NDNProtocolDTags.FaceID);
-		
-	}
-	if (decoder.peekStartElement(NDNProtocolDTags.IPProto)) {
-		
-		//int
-		var pI = decoder.readIntegerElement(NDNProtocolDTags.IPProto);
-		
-		this.ipProto = null;
-		
-		if (NetworkProtocol.TCP == pI) {
-			
-			this.ipProto = NetworkProtocol.TCP;
-			
-		} else if (NetworkProtocol.UDP == pI) {
-			
-			this.ipProto = NetworkProtocol.UDP;
-			
-		} else {
-			
-			throw new Error("FaceInstance.decoder.  Invalid " + 
-					NDNProtocolDTags.tagToString(NDNProtocolDTags.IPProto) + " field: " + pI);
-			
-		}
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.Host)) {
-		
-		this.host = decoder.readUTF8Element(NDNProtocolDTags.Host);
-		
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.Port)) {
-		this.Port = decoder.readIntegerElement(NDNProtocolDTags.Port); 
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.MulticastInterface)) {
-		this.multicastInterface = decoder.readUTF8Element(NDNProtocolDTags.MulticastInterface); 
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.MulticastTTL)) {
-		this.multicastTTL = decoder.readIntegerElement(NDNProtocolDTags.MulticastTTL); 
-	}
-	
-	if (decoder.peekStartElement(NDNProtocolDTags.FreshnessSeconds)) {
-		this.freshnessSeconds = decoder.readIntegerElement(NDNProtocolDTags.FreshnessSeconds); 
-	}
-	decoder.readEndElement();
-}
-
-/**
- * Used by NetworkObject to encode the object to a network stream.
- */
-FaceInstance.prototype.to_ndnb = function(//XMLEncoder
-	encoder){
-
-	//if (!this.validate()) {
-		//throw new Error("Cannot encode : field values missing.");
-		//throw new Error("")
-	//}
-	encoder.writeStartElement(this.getElementLabel());
-	
-	if (null != this.action && this.action.length != 0)
-		encoder.writeElement(NDNProtocolDTags.Action, this.action);	
-	
-	if (null != this.publisherPublicKeyDigest) {
-		this.publisherPublicKeyDigest.to_ndnb(encoder);
-	}
-	if (null != this.faceID) {
-		encoder.writeElement(NDNProtocolDTags.FaceID, this.faceID);
-	}
-	if (null != this.ipProto) {
-		//encoder.writeElement(NDNProtocolDTags.IPProto, this.IpProto.value());
-		encoder.writeElement(NDNProtocolDTags.IPProto, this.ipProto);
-	}
-	if (null != this.host && this.host.length != 0) {
-		encoder.writeElement(NDNProtocolDTags.Host, this.host);	
-	}
-	if (null != this.Port) {
-		encoder.writeElement(NDNProtocolDTags.Port, this.Port);
-	}
-	if (null != this.multicastInterface && this.multicastInterface.length != 0) {
-		encoder.writeElement(NDNProtocolDTags.MulticastInterface, this.multicastInterface);
-	}
-	if (null !=  this.multicastTTL) {
-		encoder.writeElement(NDNProtocolDTags.MulticastTTL, this.multicastTTL);
-	}
-	if (null != this.freshnessSeconds) {
-		encoder.writeElement(NDNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
-	}
-	encoder.writeEndElement();   			
-}
-
-
-FaceInstance.prototype.getElementLabel= function(){return NDNProtocolDTags.FaceInstance;};
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- * This class represents Forwarding Entries
- */
-
-var ForwardingEntry = function ForwardingEntry(
-                                               //ActionType 
-		_action, 
-		//Name 
-		_prefixName, 
-		//PublisherPublicKeyDigest
-		_ndndId, 
-		//Integer 
-		_faceID, 
-		//Integer 
-		_flags, 
-		//Integer 
-		_lifetime){
-		
-		
-	
-		//String
-	this.action = _action;
-		//Name\
-	this.prefixName = _prefixName;
-		//PublisherPublicKeyDigest 
-	this.ndndID = _ndndId;
-		//Integer		
-	this.faceID = _faceID;
-		//Integer		
-	this.flags = _flags;
-		//Integer 		
-	this.lifetime = _lifetime;  // in seconds
-
-};
-
-ForwardingEntry.prototype.from_ndnb =function(
-	//XMLDecoder 
-	decoder) 
-	//throws ContentDecodingException
-	{
-			decoder.readStartElement(this.getElementLabel());
-			if (decoder.peekStartElement(NDNProtocolDTags.Action)) {
-				this.action = decoder.readUTF8Element(NDNProtocolDTags.Action); 
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.Name)) {
-				this.prefixName = new Name();
-				this.prefixName.from_ndnb(decoder) ;
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)) {
-				this.NdndId = new PublisherPublicKeyDigest();
-				this.NdndId.from_ndnb(decoder);
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.FaceID)) {
-				this.faceID = decoder.readIntegerElement(NDNProtocolDTags.FaceID); 
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.ForwardingFlags)) {
-				this.flags = decoder.readIntegerElement(NDNProtocolDTags.ForwardingFlags); 
-			}
-			if (decoder.peekStartElement(NDNProtocolDTags.FreshnessSeconds)) {
-				this.lifetime = decoder.readIntegerElement(NDNProtocolDTags.FreshnessSeconds); 
-			}
-			decoder.readEndElement();
-		};
-
-		/**
-		 * Used by NetworkObject to encode the object to a network stream.
-		 */
-ForwardingEntry.prototype.to_ndnb =function(
-	//XMLEncoder 
-encoder) 
-{
-
-
-			//if (!validate()) {
-				//throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
-			//}
-			encoder.writeStartElement(this.getElementLabel());
-			if (null != this.action && this.action.length != 0)
-				encoder.writeElement(NDNProtocolDTags.Action, this.action);	
-			if (null != this.prefixName) {
-				this.prefixName.to_ndnb(encoder);
-			}
-			if (null != this.NdndId) {
-				this.NdndId.to_ndnb(encoder);
-			}
-			if (null != this.faceID) {
-				encoder.writeElement(NDNProtocolDTags.FaceID, this.faceID);
-			}
-			if (null != this.flags) {
-				encoder.writeElement(NDNProtocolDTags.ForwardingFlags, this.flags);
-			}
-			if (null != this.lifetime) {
-				encoder.writeElement(NDNProtocolDTags.FreshnessSeconds, this.lifetime);
-			}
-			encoder.writeEndElement();   			
-		};
-
-ForwardingEntry.prototype.getElementLabel = function() { return NDNProtocolDTags.ForwardingEntry; }
-/**
- * @author: Jeff Thompson
- * See COPYING for copyright and distribution information.
- * Encapsulate an Uint8Array and support dynamic reallocation.
- */
-
-/*
- * Create a DynamicUint8Array where this.array is a Uint8Array of size length.
- * If length is not supplied, use a default initial length.
- * The methods will update this.length.
- * To access the array, use this.array or call subarray.
- */
-var DynamicUint8Array = function DynamicUint8Array(length) {
-	if (!length)
-        length = 16;
-    
-    this.array = new Uint8Array(length);
-    this.length = length;
-};
-
-/*
- * Ensure that this.array has the length, reallocate and copy if necessary.
- * Update this.length which may be greater than length.
- */
-DynamicUint8Array.prototype.ensureLength = function(length) {
-    if (this.array.length >= length)
-        return;
-    
-    // See if double is enough.
-    var newLength = this.array.length * 2;
-    if (length > newLength)
-        // The needed length is much greater, so use it.
-        newLength = length;
-    
-    var newArray = new Uint8Array(newLength);
-    newArray.set(this.array);
-    this.array = newArray;
-    this.length = newLength;
-};
-
-/*
- * Call this.array.set(value, offset), reallocating if necessary. 
- */
-DynamicUint8Array.prototype.set = function(value, offset) {
-    this.ensureLength(value.length + offset);
-    this.array.set(value, offset);
-};
-
-/*
- * Return this.array.subarray(begin, end);
- */
-DynamicUint8Array.prototype.subarray = function(begin, end) {
-    return this.array.subarray(begin, end);
-}
-/**
- * This class is used to encode ndnb binary elements (blob, type/value pairs).
- * 
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- */
-
-var XML_EXT = 0x00; 
-	
-var XML_TAG = 0x01; 
-	
-var XML_DTAG = 0x02; 
-	
-var XML_ATTR = 0x03; 
- 
-var XML_DATTR = 0x04; 
-	
-var XML_BLOB = 0x05; 
-	
-var XML_UDATA = 0x06; 
-	
-var XML_CLOSE = 0x0;
-
-var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
-
-
-var XML_TT_BITS = 3;
-var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
-var XML_TT_VAL_BITS = XML_TT_BITS + 1;
-var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
-var XML_REG_VAL_BITS = 7;
-var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
-var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
-var BYTE_MASK = 0xFF;
-var LONG_BYTES = 8;
-var LONG_BITS = 64;
-	
-var bits_11 = 0x0000007FF;
-var bits_18 = 0x00003FFFF;
-var bits_32 = 0x0FFFFFFFF;
-
-
-var BinaryXMLEncoder = function BinaryXMLEncoder(){
-	this.ostream = new DynamicUint8Array(100);
-	this.offset =0;
-	this.CODEC_NAME = "Binary";
-};
-
-/*
- * Encode utf8Content as utf8.
- */
-BinaryXMLEncoder.prototype.writeUString = function(/*String*/ utf8Content) {
-	this.encodeUString(utf8Content, XML_UDATA);
-};
-
-
-BinaryXMLEncoder.prototype.writeBlob = function(
-		/*Uint8Array*/ binaryContent
-		) {
-	
-	if(LOG >3) console.log(binaryContent);
-	
-	this.encodeBlob(binaryContent, binaryContent.length);
-};
-
-
-BinaryXMLEncoder.prototype.writeStartElement = function(
-	/*String*/ tag, 
-	/*TreeMap<String,String>*/ attributes
-	) {
-
-	/*Long*/ var dictionaryVal = tag; //stringToTag(tag);
-	
-	if (null == dictionaryVal) {
-		this.encodeUString(tag, XML_TAG);
-	} else {
-		this.encodeTypeAndVal(XML_DTAG, dictionaryVal);
-	}
-	
-	if (null != attributes) {
-		this.writeAttributes(attributes); 
-	}
-};
-
-
-BinaryXMLEncoder.prototype.writeEndElement = function() {
-    this.ostream.ensureLength(this.offset + 1);
-	this.ostream.array[this.offset] = XML_CLOSE;
-	this.offset += 1;
-}
-
-
-BinaryXMLEncoder.prototype.writeAttributes = function(/*TreeMap<String,String>*/ attributes) {
-	if (null == attributes) {
-		return;
-	}
-
-	// the keySet of a TreeMap is sorted.
-
-	for(var i=0; i<attributes.length;i++){
-		var strAttr = attributes[i].k;
-		var strValue = attributes[i].v;
-
-		var dictionaryAttr = stringToTag(strAttr);
-		if (null == dictionaryAttr) {
-			// not in dictionary, encode as attr
-			// compressed format wants length of tag represented as length-1
-			// to save that extra bit, as tag cannot be 0 length.
-			// encodeUString knows to do that.
-			this.encodeUString(strAttr, XML_ATTR);
-		} else {
-			this.encodeTypeAndVal(XML_DATTR, dictionaryAttr);
-		}
-		// Write value
-		this.encodeUString(strValue);
-		
-	}
-}
-
-
-//returns a string
-stringToTag = function(/*long*/ tagVal) {
-	if ((tagVal >= 0) && (tagVal < NDNProtocolDTagsStrings.length)) {
-		return NDNProtocolDTagsStrings[tagVal];
-	} else if (tagVal == NDNProtocolDTags.NDNProtocolDataUnit) {
-		return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT;
-	}
-	return null;
-};
-
-//returns a Long
-tagToString =  function(/*String*/ tagName) {
-	// the slow way, but right now we don't care.... want a static lookup for the forward direction
-	for (var i=0; i < NDNProtocolDTagsStrings.length; ++i) {
-		if ((null != NDNProtocolDTagsStrings[i]) && (NDNProtocolDTagsStrings[i] == tagName)) {
-			return i;
-		}
-	}
-	if (NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT == tagName) {
-		return NDNProtocolDTags.NDNProtocolDataUnit;
-	}
-	return null;
-};
-
-/*
- * If Content is a string, then encode as utf8 and write UDATA.
- */
-BinaryXMLEncoder.prototype.writeElement = function(
-		//long 
-		tag, 
-		//byte[] 
-		Content,
-		//TreeMap<String, String> 
-		attributes
-		) {
-	this.writeStartElement(tag, attributes);
-	// Will omit if 0-length
-	
-	if(typeof Content === 'number') {
-		if(LOG>4) console.log('GOING TO WRITE THE NUMBER .charCodeAt(0) ' + Content.toString().charCodeAt(0) );
-		if(LOG>4) console.log('GOING TO WRITE THE NUMBER ' + Content.toString() );
-		if(LOG>4) console.log('type of number is ' + typeof Content.toString() );
-		
-		this.writeUString(Content.toString());
-		//whatever
-	}
-	else if(typeof Content === 'string'){
-		if(LOG>4) console.log('GOING TO WRITE THE STRING  ' + Content );
-		if(LOG>4) console.log('type of STRING is ' + typeof Content );
-		
-		this.writeUString(Content);
-	}
-	else{
-		if(LOG>4) console.log('GOING TO WRITE A BLOB  ' + Content );
-
-		this.writeBlob(Content);
-	}
-	
-	this.writeEndElement();
-}
-
-
-
-var TypeAndVal = function TypeAndVal(_type,_val) {
-	this.type = _type;
-	this.val = _val;
-	
-};
-
-
-BinaryXMLEncoder.prototype.encodeTypeAndVal = function(
-		//int
-		type, 
-		//long 
-		val
-		) {
-	
-	if(LOG>4) console.log('Encoding type '+ type+ ' and value '+ val);
-	
-	if(LOG>4) console.log('OFFSET IS ' + this.offset);
-	
-	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
-		throw new Error("Tag and value must be positive, and tag valid.");
-	}
-	
-	// Encode backwards. Calculate how many bytes we need:
-	var numEncodingBytes = this.numEncodingBytes(val);
-	this.ostream.ensureLength(this.offset + numEncodingBytes);
-
-	// Bottom 4 bits of val go in last byte with tag.
-	this.ostream.array[this.offset + numEncodingBytes - 1] = 
-		//(byte)
-			(BYTE_MASK &
-					(((XML_TT_MASK & type) | 
-					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
-					 XML_TT_NO_MORE); // set top bit for last byte
-	val = val >>> XML_TT_VAL_BITS;
-	
-	// Rest of val goes into preceding bytes, 7 bits per byte, top bit
-	// is "more" flag.
-	var i = this.offset + numEncodingBytes - 2;
-	while ((0 != val) && (i >= this.offset)) {
-		this.ostream.array[i] = //(byte)
-				(BYTE_MASK & (val & XML_REG_VAL_MASK)); // leave top bit unset
-		val = val >>> XML_REG_VAL_BITS;
-		--i;
-	}
-	if (val != 0) {
-		throw new Error( "This should not happen: miscalculated encoding");
-		//Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
-	}
-	this.offset+= numEncodingBytes;
-	
-	return numEncodingBytes;
-};
-
-/*
- * Encode ustring as utf8.
- */
-BinaryXMLEncoder.prototype.encodeUString = function(
-		//String 
-		ustring, 
-		//byte 
-		type) {
-	
-	if (null == ustring)
-		return;
-	if (type == XML_TAG || type == XML_ATTR && ustring.length == 0)
-		return;
-	
-	if(LOG>3) console.log("The string to write is ");
-	if(LOG>3) console.log(ustring);
-
-	var strBytes = DataUtils.stringToUtf8Array(ustring);
-	
-	this.encodeTypeAndVal(type, 
-						(((type == XML_TAG) || (type == XML_ATTR)) ?
-								(strBytes.length-1) :
-								strBytes.length));
-	
-	if(LOG>3) console.log("THE string to write is ");
-	
-	if(LOG>3) console.log(strBytes);
-	
-	this.writeString(strBytes);
-	this.offset+= strBytes.length;
-};
-
-
-
-BinaryXMLEncoder.prototype.encodeBlob = function(
-		//Uint8Array 
-		blob, 
-		//int 
-		length) {
-
-
-	if (null == blob)
-		return;
-	
-	if(LOG>4) console.log('LENGTH OF XML_BLOB IS '+length);
-	
-	/*blobCopy = new Array(blob.Length);
-	
-	for (i = 0; i < blob.length; i++) //in InStr.ToCharArray())
-	{
-		blobCopy[i] = blob[i];
-	}*/
-
-	this.encodeTypeAndVal(XML_BLOB, length);
-
-	this.writeBlobArray(blob);
-	this.offset += length;
-};
-
-var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
-var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
-var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
-
-BinaryXMLEncoder.prototype.numEncodingBytes = function(
-		//long
-		x) {
-	if (x <= ENCODING_LIMIT_1_BYTE) return (1);
-	if (x <= ENCODING_LIMIT_2_BYTES) return (2);
-	if (x <= ENCODING_LIMIT_3_BYTES) return (3);
-	
-	var numbytes = 1;
-	
-	// Last byte gives you XML_TT_VAL_BITS
-	// Remainder each give you XML_REG_VAL_BITS
-	x = x >>> XML_TT_VAL_BITS;
-	while (x != 0) {
-        numbytes++;
-		x = x >>> XML_REG_VAL_BITS;
-	}
-	return (numbytes);
-};
-
-BinaryXMLEncoder.prototype.writeDateTime = function(
-		//String 
-		tag, 
-		//NDNTime 
-		dateTime) {
-	
-	if(LOG>4)console.log('ENCODING DATE with LONG VALUE');
-	if(LOG>4)console.log(dateTime.msec);
-	
-	//var binarydate = DataUtils.unsignedLongToByteArray( Math.round((dateTime.msec/1000) * 4096)  );
-	
-
-	//parse to hex
-	var binarydate =  Math.round((dateTime.msec/1000) * 4096).toString(16)  ;
-
-	//HACK
-	var binarydate =  DataUtils.toNumbers( '0'.concat(binarydate,'0')) ;
-
-	
-	if(LOG>4)console.log('ENCODING DATE with BINARY VALUE');
-	if(LOG>4)console.log(binarydate);
-	if(LOG>4)console.log('ENCODING DATE with BINARY VALUE(HEX)');
-	if(LOG>4)console.log(DataUtils.toHex(binarydate));
-	
-	this.writeElement(tag, binarydate);
-};
-
-// This does not update this.offset.
-BinaryXMLEncoder.prototype.writeString = function(input) {
-	
-    if(typeof input === 'string'){
-		//console.log('went here');
-    	if(LOG>4) console.log('GOING TO WRITE A STRING');
-    	if(LOG>4) console.log(input);
-        
-        this.ostream.ensureLength(this.offset + input.length);
-		for (var i = 0; i < input.length; i++) {
-			if(LOG>4) console.log('input.charCodeAt(i)=' + input.charCodeAt(i));
-		    this.ostream.array[this.offset + i] = (input.charCodeAt(i));
-		}
-	}
-    else{
-		if(LOG>4) console.log('GOING TO WRITE A STRING IN BINARY FORM');
-		if(LOG>4) console.log(input);
-		
-		this.writeBlobArray(input);
-    }
-    /*
-	else if(typeof input === 'object'){
-		
-	}	
-	*/
-};
-
-
-BinaryXMLEncoder.prototype.writeBlobArray = function(
-		//Uint8Array 
-		blob) {
-	
-	if(LOG>4) console.log('GOING TO WRITE A BLOB');
-    
-	this.ostream.set(blob, this.offset);
-};
-
-
-BinaryXMLEncoder.prototype.getReducedOstream = function() {
-	return this.ostream.subarray(0, this.offset);
-};
-
-/**
- * This class is used to decode ndnb binary elements (blob, type/value pairs).
- * 
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- */
-
-var XML_EXT = 0x00; 
-	
-var XML_TAG = 0x01; 
-	
-var XML_DTAG = 0x02; 
-	
-var XML_ATTR = 0x03; 
- 
-var XML_DATTR = 0x04; 
-	
-var XML_BLOB = 0x05; 
-	
-var XML_UDATA = 0x06; 
-	
-var XML_CLOSE = 0x0;
-
-var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
-	
-
-var XML_TT_BITS = 3;
-var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
-var XML_TT_VAL_BITS = XML_TT_BITS + 1;
-var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
-var XML_REG_VAL_BITS = 7;
-var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
-var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
-var BYTE_MASK = 0xFF;
-var LONG_BYTES = 8;
-var LONG_BITS = 64;
-	
-var bits_11 = 0x0000007FF;
-var bits_18 = 0x00003FFFF;
-var bits_32 = 0x0FFFFFFFF;
-
-
-
-//returns a string
-tagToString = function(/*long*/ tagVal) {
-	if ((tagVal >= 0) && (tagVal < NDNProtocolDTagsStrings.length)) {
-		return NDNProtocolDTagsStrings[tagVal];
-	} else if (tagVal == NDNProtocolDTags.NDNProtocolDataUnit) {
-		return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT;
-	}
-	return null;
-};
-
-//returns a Long
-stringToTag =  function(/*String*/ tagName) {
-	// the slow way, but right now we don't care.... want a static lookup for the forward direction
-	for (var i=0; i < NDNProtocolDTagsStrings.length; ++i) {
-		if ((null != NDNProtocolDTagsStrings[i]) && (NDNProtocolDTagsStrings[i] == tagName)) {
-			return i;
-		}
-	}
-	if (NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT == tagName) {
-		return NDNProtocolDTags.NDNProtocolDataUnit;
-	}
-	return null;
-};
-
-//console.log(stringToTag(64));
-var BinaryXMLDecoder = function BinaryXMLDecoder(istream){
-	var MARK_LEN=512;
-	var DEBUG_MAX_LEN =  32768;
-	
-	this.istream = istream;
-	this.offset = 0;
-};
-
-BinaryXMLDecoder.prototype.initializeDecoding = function() {
-		//if (!this.istream.markSupported()) {
-			//throw new IllegalArgumentException(this.getClass().getName() + ": input stream must support marking!");
-		//}
-}
-
-BinaryXMLDecoder.prototype.readStartDocument = function(){
-		// Currently no start document in binary encoding.
-	}
-
-BinaryXMLDecoder.prototype.readEndDocument = function() {
-		// Currently no end document in binary encoding.
-	};
-
-BinaryXMLDecoder.prototype.readStartElement = function(
-		//String 
-		startTag,
-		//TreeMap<String, String> 
-		attributes) {
-	
-		
-		//NOT SURE
-		//if(typeof startTag == 'number')
-			//startTag = tagToString(startTag);
-		
-			//TypeAndVal 
-			var tv = this.decodeTypeAndVal();
-			
-			if (null == tv) {
-				throw new ContentDecodingException(new Error("Expected start element: " + startTag + " got something not a tag."));
-			}
-			
-			//String 
-			var decodedTag = null;
-			//console.log(tv);
-			//console.log(typeof tv);
-			
-			//console.log(XML_TAG);
-			if (tv.type() == XML_TAG) {
-				//console.log('got here');
-				//Log.info(Log.FAC_ENCODING, "Unexpected: got tag in readStartElement; looking for tag " + startTag + " got length: " + (int)tv.val()+1);
-				// Tag value represents length-1 as tags can never be empty.
-				var valval ;
-				if(typeof tv.val() == 'string'){
-					valval = (parseInt(tv.val())) + 1;
-				}
-				else
-					valval = (tv.val())+ 1;
-				
-				//console.log('valval is ' +valval);
-				
-				decodedTag = this.decodeUString(valval);
-				
-			} else if (tv.type() == XML_DTAG) {
-				//console.log('gothere');
-				//console.log(tv.val());
-				//decodedTag = tagToString(tv.val());
-				//console.log()
-				decodedTag = tv.val();
-			}
-			
-			//console.log(decodedTag);
-			//console.log('startTag is '+startTag);
-			
-			
-			if ((null ==  decodedTag) || decodedTag != startTag ) {
-				console.log('expecting '+ startTag + ' but got '+ decodedTag);
-				throw new ContentDecodingException(new Error("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")"));
-			}
-			
-			// DKS: does not read attributes out of stream if caller doesn't
-			// ask for them. Should possibly peek and skip over them regardless.
-			// TODO: fix this
-			if (null != attributes) {
-				readAttributes(attributes); 
-			}
-	}
-	
-
-BinaryXMLDecoder.prototype.readAttributes = function(
-	// array of [attributeName, attributeValue] 
-	attributes) {
-	
-	if (null == attributes) {
-		return;
-	}
-
-	try {
-		// Now need to get attributes.
-		//TypeAndVal 
-		var nextTV = this.peekTypeAndVal();
-
-		while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
-				(XML_DATTR == nextTV.type()))) {
-
-			// Decode this attribute. First, really read the type and value.
-			//this.TypeAndVal 
-			var thisTV = this.decodeTypeAndVal();
-
-			//String 
-			var attributeName = null;
-			if (XML_ATTR == thisTV.type()) {
-				// Tag value represents length-1 as attribute names cannot be empty.
-				var valval ;
-				if(typeof thisTV.val() == 'string'){
-					valval = (parseInt(thisTV.val())) + 1;
-				}
-				else
-					valval = (thisTV.val())+ 1;
-				
-				attributeName = this.decodeUString(valval);
-
-			} else if (XML_DATTR == thisTV.type()) {
-				// DKS TODO are attributes same or different dictionary?
-				attributeName = tagToString(thisTV.val());
-				if (null == attributeName) {
-					throw new ContentDecodingException(new Error("Unknown DATTR value" + thisTV.val()));
-				}
-			}
-			// Attribute values are always UDATA
-			//String
-			var attributeValue = this.decodeUString();
-
-			//
-			attributes.push([attributeName, attributeValue]);
-
-			nextTV = this.peekTypeAndVal();
-		}
-	} catch ( e) {
-		throw new ContentDecodingException(new Error("readStartElement", e));
-	}
-};
-
-//returns a string
-BinaryXMLDecoder.prototype.peekStartElementAsString = function() {
-	//this.istream.mark(MARK_LEN);
-
-	//String 
-	var decodedTag = null;
-	var previousOffset = this.offset;
-	try {
-		// Have to distinguish genuine errors from wrong tags. Could either use
-		// a special exception subtype, or redo the work here.
-		//this.TypeAndVal 
-		var tv = this.decodeTypeAndVal();
-
-		if (null != tv) {
-
-			if (tv.type() == XML_TAG) {
-				/*if (tv.val()+1 > DEBUG_MAX_LEN) {
-					throw new ContentDecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!")(;
-				}*/
-
-				// Tag value represents length-1 as tags can never be empty.
-				var valval ;
-				if(typeof tv.val() == 'string'){
-					valval = (parseInt(tv.val())) + 1;
-				}
-				else
-					valval = (tv.val())+ 1;
-				
-				decodedTag = this.decodeUString(valval);
-				
-				//Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
-
-			} else if (tv.type() == XML_DTAG) {
-				decodedTag = tagToString(tv.val());					
-			}
-
-		} // else, not a type and val, probably an end element. rewind and return false.
-
-	} catch ( e) {
-
-	} finally {
-		try {
-			this.offset = previousOffset;
-		} catch ( e) {
-			Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
-			throw new ContentDecodingException(new Error("Cannot reset stream! " + e.getMessage(), e));
-		}
-	}
-	return decodedTag;
-};
-
-BinaryXMLDecoder.prototype.peekStartElement = function(
-		//String 
-		startTag) {
-	//String 
-	if(typeof startTag == 'string'){
-		var decodedTag = this.peekStartElementAsString();
-		
-		if ((null !=  decodedTag) && decodedTag == startTag) {
-			return true;
-		}
-		return false;
-	}
-	else if(typeof startTag == 'number'){
-		var decodedTag = this.peekStartElementAsLong();
-		if ((null !=  decodedTag) && decodedTag == startTag) {
-			return true;
-		}
-		return false;
-	}
-	else{
-		throw new ContentDecodingException(new Error("SHOULD BE STRING OR NUMBER"));
-	}
-}
-//returns Long
-BinaryXMLDecoder.prototype.peekStartElementAsLong = function() {
-		//this.istream.mark(MARK_LEN);
-
-		//Long
-		var decodedTag = null;
-		
-		var previousOffset = this.offset;
-		
-		try {
-			// Have to distinguish genuine errors from wrong tags. Could either use
-			// a special exception subtype, or redo the work here.
-			//this.TypeAndVal
-			var tv = this.decodeTypeAndVal();
-
-			if (null != tv) {
-
-				if (tv.type() == XML_TAG) {
-					if (tv.val()+1 > DEBUG_MAX_LEN) {
-						throw new ContentDecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!"));
-					}
-
-					var valval ;
-					if(typeof tv.val() == 'string'){
-						valval = (parseInt(tv.val())) + 1;
-					}
-					else
-						valval = (tv.val())+ 1;
-					
-					// Tag value represents length-1 as tags can never be empty.
-					//String 
-					var strTag = this.decodeUString(valval);
-					
-					decodedTag = stringToTag(strTag);
-					
-					//Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
-					
-				} else if (tv.type() == XML_DTAG) {
-					decodedTag = tv.val();					
-				}
-
-			} // else, not a type and val, probably an end element. rewind and return false.
-
-		} catch ( e) {
-			
-		} finally {
-			try {
-				//this.istream.reset();
-				this.offset = previousOffset;
-			} catch ( e) {
-				Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
-				throw new Error("Cannot reset stream! " + e.getMessage(), e);
-			}
-		}
-		return decodedTag;
-	};
-
-
-// returns a byte[]
-BinaryXMLDecoder.prototype.readBinaryElement = function(
-		//long 
-		startTag,
-		//TreeMap<String, String> 
-		attributes){
-	//byte [] 
-	var blob = null;
-	
-	this.readStartElement(startTag, attributes);
-	blob = this.readBlob();	
-
-	return blob;
-};
-	
-	
-BinaryXMLDecoder.prototype.readEndElement = function(){
-			if(LOG>4)console.log('this.offset is '+this.offset);
-			
-			var next = this.istream[this.offset]; 
-			
-			this.offset++;
-			//read();
-			
-			if(LOG>4)console.log('XML_CLOSE IS '+XML_CLOSE);
-			if(LOG>4)console.log('next is '+next);
-			
-			if (next != XML_CLOSE) {
-				console.log("Expected end element, got: " + next);
-				throw new ContentDecodingException(new Error("Expected end element, got: " + next));
-			}
-	};
-
-
-//String	
-BinaryXMLDecoder.prototype.readUString = function(){
-			//String 
-			var ustring = this.decodeUString();	
-			this.readEndElement();
-			return ustring;
-
-	};
-	
-
-//returns a uint8array
-BinaryXMLDecoder.prototype.readBlob = function() {
-			//uint8array
-			
-			var blob = this.decodeBlob();	
-			this.readEndElement();
-			return blob;
-
-	};
-
-
-//NDNTime
-BinaryXMLDecoder.prototype.readDateTime = function(
-	//long 
-	startTag)  {
-	//byte [] 
-	
-	var byteTimestamp = this.readBinaryElement(startTag);
-
-	//var lontimestamp = DataUtils.byteArrayToUnsignedLong(byteTimestamp);
-
-	byteTimestamp = DataUtils.toHex(byteTimestamp);
-	
-	
-	byteTimestamp = parseInt(byteTimestamp, 16);
-
-	var lontimestamp = (byteTimestamp/ 4096) * 1000;
-
-	//if(lontimestamp<0) lontimestamp =  - lontimestamp;
-
-	if(LOG>3) console.log('DECODED DATE WITH VALUE');
-	if(LOG>3) console.log(lontimestamp);
-	
-
-	//NDNTime 
-	var timestamp = new NDNTime(lontimestamp);
-	//timestamp.setDateBinary(byteTimestamp);
-	
-	if (null == timestamp) {
-		throw new ContentDecodingException(new Error("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp)));
-	}		
-	return timestamp;
-};
-
-BinaryXMLDecoder.prototype.decodeTypeAndVal = function() {
-	
-	/*int*/var type = -1;
-	/*long*/var val = 0;
-	/*boolean*/var more = true;
-
-	do {
-		
-		var next = this.istream[this.offset ];
-		
-		
-		if (next < 0) {
-			return null; 
-		}
-
-		if ((0 == next) && (0 == val)) {
-			return null;
-		}
-		
-		more = (0 == (next & XML_TT_NO_MORE));
-		
-		if  (more) {
-			val = val << XML_REG_VAL_BITS;
-			val |= (next & XML_REG_VAL_MASK);
-		} else {
-
-			type = next & XML_TT_MASK;
-			val = val << XML_TT_VAL_BITS;
-			val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
-		}
-		
-		this.offset++;
-		
-	} while (more);
-	
-	if(LOG>3)console.log('TYPE is '+ type + ' VAL is '+ val);
-
-	return new TypeAndVal(type, val);
-};
-
-
-
-//TypeAndVal
-BinaryXMLDecoder.peekTypeAndVal = function() {
-	//TypeAndVal 
-	var tv = null;
-	
-	//this.istream.mark(LONG_BYTES*2);		
-	
-	var previousOffset = this.offset;
-	
-	try {
-		tv = this.decodeTypeAndVal();
-	} finally {
-		//this.istream.reset();
-		this.offset = previousOffset;
-	}
-	
-	return tv;
-};
-
-
-//Uint8Array
-BinaryXMLDecoder.prototype.decodeBlob = function(
-		//int 
-		blobLength) {
-	
-	if(null == blobLength){
-		//TypeAndVal
-		var tv = this.decodeTypeAndVal();
-
-		var valval ;
-		
-		if(typeof tv.val() == 'string'){
-			valval = (parseInt(tv.val()));
-		}
-		else
-			valval = (tv.val());
-		
-		//console.log('valval here is ' + valval);
-		return  this.decodeBlob(valval);
-	}
-	
-	//
-	//Uint8Array
-	var bytes = this.istream.subarray(this.offset, this.offset+ blobLength);
-	this.offset += blobLength;
-	
-	return bytes;
-};
-
-//String
-BinaryXMLDecoder.prototype.decodeUString = function(
-		//int 
-		byteLength) {
-	if(null == byteLength ){
-		var tempStreamPosition = this.offset;
-			
-		//TypeAndVal 
-		var tv = this.decodeTypeAndVal();
-		
-		if(LOG>3)console.log('TV is '+tv);
-		if(LOG>3)console.log(tv);
-		
-		if(LOG>3)console.log('Type of TV is '+typeof tv);
-	
-		if ((null == tv) || (XML_UDATA != tv.type())) { // if we just have closers left, will get back null
-			//if (Log.isLoggable(Log.FAC_ENCODING, Level.FINEST))
-				//Log.finest(Log.FAC_ENCODING, "Expected UDATA, got " + ((null == tv) ? " not a tag " : tv.type()) + ", assuming elided 0-length blob.");
-			
-			this.offset = tempStreamPosition;
-			
-			return "";
-		}
-			
-		return this.decodeUString(tv.val());
-	}
-	else{
-		//uint8array 
-		var stringBytes = this.decodeBlob(byteLength);
-		
-		//return DataUtils.getUTF8StringFromBytes(stringBytes);
-		return  DataUtils.toString(stringBytes);
-		
-	}
-};
-
-//OBject containg a pair of type and value
-var TypeAndVal = function TypeAndVal(_type,_val) {
-	this.t = _type;
-	this.v = _val;
-};
-
-TypeAndVal.prototype.type = function(){
-	return this.t;
-};
-
-TypeAndVal.prototype.val = function(){
-	return this.v;
-};
-
-
-
-
-BinaryXMLDecoder.prototype.readIntegerElement =function(
-	//String 
-	startTag) {
-
-	//String 
-	if(LOG>4) console.log('READING INTEGER '+ startTag);
-	if(LOG>4) console.log('TYPE OF '+ typeof startTag);
-	
-	var strVal = this.readUTF8Element(startTag);
-	
-	return parseInt(strVal);
-};
-
-
-BinaryXMLDecoder.prototype.readUTF8Element =function(
-			//String 
-			startTag,
-			//TreeMap<String, String> 
-			attributes) {
-			//throws Error where name == "ContentDecodingException" 
-
-		this.readStartElement(startTag, attributes); // can't use getElementText, can't get attributes
-		//String 
-		var strElementText = this.readUString();
-		return strElementText;
-};
-
-
-/* 
- * Set the offset into the input, used for the next read.
- */
-BinaryXMLDecoder.prototype.seek = function(
-        //int
-        offset) {
-    this.offset = offset;
-}
-
-/*
- * Call with: throw new ContentDecodingException(new Error("message")).
- */
-function ContentDecodingException(error) {
-    this.message = error.message;
-    // Copy lineNumber, etc. from where new Error was called.
-    for (var prop in error)
-        this[prop] = error[prop];
-}
-ContentDecodingException.prototype = new Error();
-ContentDecodingException.prototype.name = "ContentDecodingException";
-
-/**
- * This class uses BinaryXMLDecoder to follow the structure of a ndnb binary element to 
- * determine its end.
- * 
- * @author: Jeff Thompson
- * See COPYING for copyright and distribution information.
- */
-
-var BinaryXMLStructureDecoder = function BinaryXMLDecoder() {
-    this.gotElementEnd = false;
-	this.offset = 0;
-    this.level = 0;
-    this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
-    this.headerLength = 0;
-    this.useHeaderBuffer = false;
-    this.headerBuffer = new DynamicUint8Array(5);
-    this.nBytesToRead = 0;
-};
-
-BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE = 0;
-BinaryXMLStructureDecoder.READ_BYTES = 1;
-
-/*
- * Continue scanning input starting from this.offset.  If found the end of the element
- *   which started at offset 0 then return true, else false.
- * If this returns false, you should read more into input and call again.
- * You have to pass in input each time because the array could be reallocated.
- * This throws an exception for badly formed ndnb.
- */
-BinaryXMLStructureDecoder.prototype.findElementEnd = function(
-    // Uint8Array
-    input)
-{
-    if (this.gotElementEnd)
-        // Someone is calling when we already got the end.
-        return true;
-    
-    var decoder = new BinaryXMLDecoder(input);
-    
-    while (true) {
-        if (this.offset >= input.length)
-            // All the cases assume we have some input.
-            return false;
-        
-        switch (this.state) {
-            case BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE:               
-                // First check for XML_CLOSE.
-                if (this.headerLength == 0 && input[this.offset] == XML_CLOSE) {
-                    ++this.offset;
-                    // Close the level.
-                    --this.level;
-                    if (this.level == 0)
-                        // Finished.
-                        return true;
-                    if (this.level < 0)
-                        throw new Error("BinaryXMLStructureDecoder: Unexepected close tag at offset " +
-                            (this.offset - 1));
-                    
-                    // Get ready for the next header.
-                    this.startHeader();
-                    break;
+            if (e.message && e['opera#sourceloc']) {
+                // e.message.indexOf("Backtrace:") > -1 -> opera9
+                // 'opera#sourceloc' in e -> opera9, opera10a
+                // !e.stacktrace -> opera9
+                if (!e.stacktrace) {
+                    return 'opera9'; // use e.message
                 }
-                
-                var startingHeaderLength = this.headerLength;
-                while (true) {
-                    if (this.offset >= input.length) {
-                        // We can't get all of the header bytes from this input. Save in headerBuffer.
-                        this.useHeaderBuffer = true;
-                        var nNewBytes = this.headerLength - startingHeaderLength;
-                        this.headerBuffer.set
-                            (input.subarray(this.offset - nNewBytes, nNewBytes), startingHeaderLength);
-                        
-                        return false;
-                    }
-                    var headerByte = input[this.offset++];
-                    ++this.headerLength;
-                    if (headerByte & XML_TT_NO_MORE)
-                        // Break and read the header.
-                        break;
+                if (e.message.indexOf('\n') > -1 && e.message.split('\n').length > e.stacktrace.split('\n').length) {
+                    // e.message may have more stack entries than e.stacktrace
+                    return 'opera9'; // use e.message
                 }
-                
-                var typeAndVal;
-                if (this.useHeaderBuffer) {
-                    // Copy the remaining bytes into headerBuffer.
-                    nNewBytes = this.headerLength - startingHeaderLength;
-                    this.headerBuffer.set
-                        (input.subarray(this.offset - nNewBytes, nNewBytes), startingHeaderLength);
+                return 'opera10a'; // use e.stacktrace
+            }
 
-                    typeAndVal = new BinaryXMLDecoder(this.headerBuffer.array).decodeTypeAndVal();
+            if (e.message && e.stack && e.stacktrace) {
+                // e.stacktrace && e.stack -> opera10b
+                if (e.stacktrace.indexOf("called from line") < 0) {
+                    return 'opera10b'; // use e.stacktrace, format differs from 'opera10a'
+                }
+                // e.stacktrace && e.stack -> opera11
+                return 'opera11'; // use e.stacktrace, format differs from 'opera10a', 'opera10b'
+            }
+
+            if (e.stack && !e.fileName) {
+                // Chrome 27 does not have e.arguments as earlier versions,
+                // but still does not have e.fileName as Firefox
+                return 'chrome';
+            }
+
+            return 'other';
+        },
+
+        /**
+         * Given a context, function name, and callback function, overwrite it so that it calls
+         * printStackTrace() first with a callback and then runs the rest of the body.
+         *
+         * @param {Object} context of execution (e.g. window)
+         * @param {String} functionName to instrument
+         * @param {Function} callback function to call with a stack trace on invocation
+         */
+        instrumentFunction: function(context, functionName, callback) {
+            context = context || window;
+            var original = context[functionName];
+            context[functionName] = function instrumented() {
+                callback.call(this, printStackTrace().slice(4));
+                return context[functionName]._instrumented.apply(this, arguments);
+            };
+            context[functionName]._instrumented = original;
+        },
+
+        /**
+         * Given a context and function name of a function that has been
+         * instrumented, revert the function to it's original (non-instrumented)
+         * state.
+         *
+         * @param {Object} context of execution (e.g. window)
+         * @param {String} functionName to de-instrument
+         */
+        deinstrumentFunction: function(context, functionName) {
+            if (context[functionName].constructor === Function &&
+                context[functionName]._instrumented &&
+                context[functionName]._instrumented.constructor === Function) {
+                context[functionName] = context[functionName]._instrumented;
+            }
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on Chrome's stack string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        chrome: function(e) {
+            return (e.stack + '\n')
+                .replace(/^[\s\S]+?\s+at\s+/, ' at ') // remove message
+                .replace(/^\s+(at eval )?at\s+/gm, '') // remove 'at' and indentation
+                .replace(/^([^\(]+?)([\n$])/gm, '{anonymous}() ($1)$2')
+                .replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}() ($1)')
+                .replace(/^(.+) \((.+)\)$/gm, '$1@$2')
+                .split('\n')
+                .slice(0, -1);
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on Safari's stack string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        safari: function(e) {
+            return e.stack.replace(/\[native code\]\n/m, '')
+                .replace(/^(?=\w+Error\:).*$\n/m, '')
+                .replace(/^@/gm, '{anonymous}()@')
+                .split('\n');
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on IE's stack string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        ie: function(e) {
+            return e.stack
+                .replace(/^\s*at\s+(.*)$/gm, '$1')
+                .replace(/^Anonymous function\s+/gm, '{anonymous}() ')
+                .replace(/^(.+)\s+\((.+)\)$/gm, '$1@$2')
+                .split('\n')
+                .slice(1);
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on Firefox's stack string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        firefox: function(e) {
+            return e.stack.replace(/(?:\n@:0)?\s+$/m, '')
+                .replace(/^(?:\((\S*)\))?@/gm, '{anonymous}($1)@')
+                .split('\n');
+        },
+
+        opera11: function(e) {
+            var ANON = '{anonymous}', lineRE = /^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/;
+            var lines = e.stacktrace.split('\n'), result = [];
+
+            for (var i = 0, len = lines.length; i < len; i += 2) {
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    var location = match[4] + ':' + match[1] + ':' + match[2];
+                    var fnName = match[3] || "global code";
+                    fnName = fnName.replace(/<anonymous function: (\S+)>/, "$1").replace(/<anonymous function>/, ANON);
+                    result.push(fnName + '@' + location + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
+                }
+            }
+
+            return result;
+        },
+
+        opera10b: function(e) {
+            // "<anonymous function: run>([arguments not available])@file://localhost/G:/js/stacktrace.js:27\n" +
+            // "printStackTrace([arguments not available])@file://localhost/G:/js/stacktrace.js:18\n" +
+            // "@file://localhost/G:/js/test/functional/testcase1.html:15"
+            var lineRE = /^(.*)@(.+):(\d+)$/;
+            var lines = e.stacktrace.split('\n'), result = [];
+
+            for (var i = 0, len = lines.length; i < len; i++) {
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    var fnName = match[1] ? (match[1] + '()') : "global code";
+                    result.push(fnName + '@' + match[2] + ':' + match[3]);
+                }
+            }
+
+            return result;
+        },
+
+        /**
+         * Given an Error object, return a formatted Array based on Opera 10's stacktrace string.
+         *
+         * @param e - Error object to inspect
+         * @return Array<String> of function calls, files and line numbers
+         */
+        opera10a: function(e) {
+            // "  Line 27 of linked script file://localhost/G:/js/stacktrace.js\n"
+            // "  Line 11 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html: In function foo\n"
+            var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;
+            var lines = e.stacktrace.split('\n'), result = [];
+
+            for (var i = 0, len = lines.length; i < len; i += 2) {
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    var fnName = match[3] || ANON;
+                    result.push(fnName + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
+                }
+            }
+
+            return result;
+        },
+
+        // Opera 7.x-9.2x only!
+        opera9: function(e) {
+            // "  Line 43 of linked script file://localhost/G:/js/stacktrace.js\n"
+            // "  Line 7 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html\n"
+            var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)/i;
+            var lines = e.message.split('\n'), result = [];
+
+            for (var i = 2, len = lines.length; i < len; i += 2) {
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    result.push(ANON + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
+                }
+            }
+
+            return result;
+        },
+
+        phantomjs: function(e) {
+            var ANON = '{anonymous}', lineRE = /(\S+) \((\S+)\)/i;
+            var lines = e.stack.split('\n'), result = [];
+
+            for (var i = 1, len = lines.length; i < len; i++) {
+                lines[i] = lines[i].replace(/^\s+at\s+/gm, '');
+                var match = lineRE.exec(lines[i]);
+                if (match) {
+                    result.push(match[1] + '()@' + match[2]);
                 }
                 else {
-                    // We didn't have to use the headerBuffer.
-                    decoder.seek(this.offset - this.headerLength);
-                    typeAndVal = decoder.decodeTypeAndVal();
+                    result.push(ANON + '()@' + lines[i]);
                 }
-                
-                if (typeAndVal == null)
-                    throw new Error("BinaryXMLStructureDecoder: Can't read header starting at offset " +
-                        (this.offset - this.headerLength));
-                
-                // Set the next state based on the type.
-                var type = typeAndVal.t;
-                if (type == XML_DATTR)
-                    // We already consumed the item. READ_HEADER_OR_CLOSE again.
-                    // ndnb has rules about what must follow an attribute, but we are just scanning.
-                    this.startHeader();
-                else if (type == XML_DTAG || type == XML_EXT) {
-                    // Start a new level and READ_HEADER_OR_CLOSE again.
-                    ++this.level;
-                    this.startHeader();
+            }
+
+            return result;
+        },
+
+        // Safari 5-, IE 9-, and others
+        other: function(curr) {
+            var ANON = '{anonymous}', fnRE = /function(?:\s+([\w$]+))?\s*\(/, stack = [], fn, args, maxStackSize = 10;
+            var slice = Array.prototype.slice;
+            while (curr && stack.length < maxStackSize) {
+                fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
+                try {
+                    args = slice.call(curr['arguments'] || []);
+                } catch (e) {
+                    args = ['Cannot access arguments: ' + e];
                 }
-                else if (type == XML_TAG || type == XML_ATTR) {
-                    if (type == XML_TAG)
-                        // Start a new level and read the tag.
-                        ++this.level;
-                    // Minimum tag or attribute length is 1.
-                    this.nBytesToRead = typeAndVal.v + 1;
-                    this.state = BinaryXMLStructureDecoder.READ_BYTES;
-                    // ndnb has rules about what must follow an attribute, but we are just scanning.
+                stack[stack.length] = fn + '(' + this.stringifyArguments(args) + ')';
+                try {
+                    curr = curr.caller;
+                } catch (e) {
+                    stack[stack.length] = 'Cannot access caller: ' + e;
+                    break;
                 }
-                else if (type == XML_BLOB || type == XML_UDATA) {
-                    this.nBytesToRead = typeAndVal.v;
-                    this.state = BinaryXMLStructureDecoder.READ_BYTES;
+            }
+            return stack;
+        },
+
+        /**
+         * Given arguments array as a String, substituting type names for non-string types.
+         *
+         * @param {Arguments,Array} args
+         * @return {String} stringified arguments
+         */
+        stringifyArguments: function(args) {
+            var result = [];
+            var slice = Array.prototype.slice;
+            for (var i = 0; i < args.length; ++i) {
+                var arg = args[i];
+                if (arg === undefined) {
+                    result[i] = 'undefined';
+                } else if (arg === null) {
+                    result[i] = 'null';
+                } else if (arg.constructor) {
+                    // TODO constructor comparison does not work for iframes
+                    if (arg.constructor === Array) {
+                        if (arg.length < 3) {
+                            result[i] = '[' + this.stringifyArguments(arg) + ']';
+                        } else {
+                            result[i] = '[' + this.stringifyArguments(slice.call(arg, 0, 1)) + '...' + this.stringifyArguments(slice.call(arg, -1)) + ']';
+                        }
+                    } else if (arg.constructor === Object) {
+                        result[i] = '#object';
+                    } else if (arg.constructor === Function) {
+                        result[i] = '#function';
+                    } else if (arg.constructor === String) {
+                        result[i] = '"' + arg + '"';
+                    } else if (arg.constructor === Number) {
+                        result[i] = arg;
+                    } else {
+                        result[i] = '?';
+                    }
                 }
-                else
-                    throw new Error("BinaryXMLStructureDecoder: Unrecognized header type " + type);
-                break;
-            
-            case BinaryXMLStructureDecoder.READ_BYTES:
-                var nRemainingBytes = input.length - this.offset;
-                if (nRemainingBytes < this.nBytesToRead) {
-                    // Need more.
-                    this.offset += nRemainingBytes;
-                    this.nBytesToRead -= nRemainingBytes;
-                    return false;
+            }
+            return result.join(',');
+        },
+
+        sourceCache: {},
+
+        /**
+         * @return {String} the text from a given URL
+         */
+        ajax: function(url) {
+            var req = this.createXMLHTTPObject();
+            if (req) {
+                try {
+                    req.open('GET', url, false);
+                    //req.overrideMimeType('text/plain');
+                    //req.overrideMimeType('text/javascript');
+                    req.send(null);
+                    //return req.status == 200 ? req.responseText : '';
+                    return req.responseText;
+                } catch (e) {
                 }
-                // Got the bytes.  Read a new header or close.
-                this.offset += this.nBytesToRead;
-                this.startHeader();
-                break;
-            
-            default:
-                // We don't expect this to happen.
-                throw new Error("BinaryXMLStructureDecoder: Unrecognized state " + this.state);
+            }
+            return '';
+        },
+
+        /**
+         * Try XHR methods in order and store XHR factory.
+         *
+         * @return {XMLHttpRequest} XHR function or equivalent
+         */
+        createXMLHTTPObject: function() {
+            var xmlhttp, XMLHttpFactories = [
+                function() {
+                    return new XMLHttpRequest();
+                }, function() {
+                    return new ActiveXObject('Msxml2.XMLHTTP');
+                }, function() {
+                    return new ActiveXObject('Msxml3.XMLHTTP');
+                }, function() {
+                    return new ActiveXObject('Microsoft.XMLHTTP');
+                }
+            ];
+            for (var i = 0; i < XMLHttpFactories.length; i++) {
+                try {
+                    xmlhttp = XMLHttpFactories[i]();
+                    // Use memoization to cache the factory
+                    this.createXMLHTTPObject = XMLHttpFactories[i];
+                    return xmlhttp;
+                } catch (e) {
+                }
+            }
+        },
+
+        /**
+         * Given a URL, check if it is in the same domain (so we can get the source
+         * via Ajax).
+         *
+         * @param url {String} source url
+         * @return {Boolean} False if we need a cross-domain request
+         */
+        isSameDomain: function(url) {
+            return typeof location !== "undefined" && url.indexOf(location.hostname) !== -1; // location may not be defined, e.g. when running from nodejs.
+        },
+
+        /**
+         * Get source code from given URL if in the same domain.
+         *
+         * @param url {String} JS source URL
+         * @return {Array} Array of source code lines
+         */
+        getSource: function(url) {
+            // TODO reuse source from script tags?
+            if (!(url in this.sourceCache)) {
+                this.sourceCache[url] = this.ajax(url).split('\n');
+            }
+            return this.sourceCache[url];
+        },
+
+        guessAnonymousFunctions: function(stack) {
+            for (var i = 0; i < stack.length; ++i) {
+                var reStack = /\{anonymous\}\(.*\)@(.*)/,
+                    reRef = /^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/,
+                    frame = stack[i], ref = reStack.exec(frame);
+
+                if (ref) {
+                    var m = reRef.exec(ref[1]);
+                    if (m) { // If falsey, we did not get any file/line information
+                        var file = m[1], lineno = m[2], charno = m[3] || 0;
+                        if (file && this.isSameDomain(file) && lineno) {
+                            var functionName = this.guessAnonymousFunction(file, lineno, charno);
+                            stack[i] = frame.replace('{anonymous}', functionName);
+                        }
+                    }
+                }
+            }
+            return stack;
+        },
+
+        guessAnonymousFunction: function(url, lineNo, charNo) {
+            var ret;
+            try {
+                ret = this.findFunctionName(this.getSource(url), lineNo);
+            } catch (e) {
+                ret = 'getSource failed with url: ' + url + ', exception: ' + e.toString();
+            }
+            return ret;
+        },
+
+        findFunctionName: function(source, lineNo) {
+            // FIXME findFunctionName fails for compressed source
+            // (more than one function on the same line)
+            // function {name}({args}) m[1]=name m[2]=args
+            var reFunctionDeclaration = /function\s+([^(]*?)\s*\(([^)]*)\)/;
+            // {name} = function ({args}) TODO args capture
+            // /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*function(?:[^(]*)/
+            var reFunctionExpression = /['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*function\b/;
+            // {name} = eval()
+            var reFunctionEvaluation = /['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*(?:eval|new Function)\b/;
+            // Walk backwards in the source lines until we find
+            // the line which matches one of the patterns above
+            var code = "", line, maxLines = Math.min(lineNo, 20), m, commentPos;
+            for (var i = 0; i < maxLines; ++i) {
+                // lineNo is 1-based, source[] is 0-based
+                line = source[lineNo - i - 1];
+                commentPos = line.indexOf('//');
+                if (commentPos >= 0) {
+                    line = line.substr(0, commentPos);
+                }
+                // TODO check other types of comments? Commented code may lead to false positive
+                if (line) {
+                    code = line + code;
+                    m = reFunctionExpression.exec(code);
+                    if (m && m[1]) {
+                        return m[1];
+                    }
+                    m = reFunctionDeclaration.exec(code);
+                    if (m && m[1]) {
+                        //return m[1] + "(" + (m[2] || "") + ")";
+                        return m[1];
+                    }
+                    m = reFunctionEvaluation.exec(code);
+                    if (m && m[1]) {
+                        return m[1];
+                    }
+                }
+            }
+            return '(?)';
         }
-    }
-};
+    };
 
-/*
- * Set the state to READ_HEADER_OR_CLOSE and set up to start reading the header
- */
-BinaryXMLStructureDecoder.prototype.startHeader = function() {
-    this.headerLength = 0;
-    this.useHeaderBuffer = false;
-    this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;    
-}
-
-/*
- *  Set the offset into the input, used for the next read.
- */
-BinaryXMLStructureDecoder.prototype.seek = function(
-        //int
-        offset) {
-    this.offset = offset;
-}
+    return printStackTrace;
+}));
 /**
- * This class contains utilities to help parse the data
- * author: Meki Cheraoui, Jeff Thompson
- * See COPYING for copyright and distribution information.
- */
- 
-var DataUtils = function DataUtils(){
-	
-	
-};
-
-
-/*
- * NOTE THIS IS CURRENTLY NOT BEHING USED
- * 
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Ryan Bennett
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
  */
 
-DataUtils.keyStr = "ABCDEFGHIJKLMNOP" +
-               "QRSTUVWXYZabcdef" +
-               "ghijklmnopqrstuv" +
-               "wxyz0123456789+/" +
-               "=";
+// define a shim require function so that a node/browserify require calls dont cause errors when ndn-js is used via <script> tag
 
-               
+/** @ignore */
+var ndn = ndn || {}
+/** @ignore */
+var exports = ndn;
+
+/** @ignore */
+var module = {}
+/** @ignore */
+function require(){return ndn;}
 /**
- * Raw String to Base 64
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
  */
-DataUtils.stringtoBase64=function stringtoBase64(input) {
-     input = escape(input);
-     var output = "";
-     var chr1, chr2, chr3 = "";
-     var enc1, enc2, enc3, enc4 = "";
-     var i = 0;
 
-     do {
-        chr1 = input.charCodeAt(i++);
-        chr2 = input.charCodeAt(i++);
-        chr3 = input.charCodeAt(i++);
+// This is included after stacktrace.js and browserify-require.js so that
+// require().printStackTrace works.
 
-        enc1 = chr1 >> 2;
-        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
-        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
-        enc4 = chr3 & 63;
+exports.printStackTrace = printStackTrace;
+/**
+ * This module checks for the availability of various crypto.subtle api's at runtime,
+ * exporting a function that returns the known availability of necessary NDN crypto apis
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Ryan Bennett <nomad.ry@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
 
-        if (isNaN(chr2)) {
-           enc3 = enc4 = 64;
-        } else if (isNaN(chr3)) {
-           enc4 = 64;
-        }
-
-        output = output +
-           DataUtils.keyStr.charAt(enc1) +
-           DataUtils.keyStr.charAt(enc2) +
-           DataUtils.keyStr.charAt(enc3) +
-           DataUtils.keyStr.charAt(enc4);
-        chr1 = chr2 = chr3 = "";
-        enc1 = enc2 = enc3 = enc4 = "";
-     } while (i < input.length);
-
-     return output;
+function DetectSubtleCrypto(){
+  var use = false;
+  var baselineSupport = (
+                            (typeof crypto !== 'undefined' && crypto && crypto.subtle)
+                            && (
+                                (location.protocol === "https:" || "chrome-extension:" || "chrome:")
+                                || (location.hostname === "localhost" || location.hostname === "127.0.0.1")
+                               )
+                        ) ? true : false ;
+  if (baselineSupport) {
+    var algo = { name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, hash:{name:"SHA-256"}, publicExponent: new Uint8Array([0x01, 0x00, 0x01])};
+    var keypair;
+    //try to perform every RSA crypto operation we need, if everything works, set use = true
+    crypto.subtle.generateKey(
+      algo,
+      true, //exportable;
+      ["sign", "verify"]).then(function(key){
+        keypair = key;
+        return crypto.subtle.sign(algo, key.privateKey, new Uint8Array([1,2,3,4,5]));
+      }).then(function(signature){
+        return crypto.subtle.verify(algo, keypair.publicKey, signature, new Uint8Array([1,2,3,4,5]));
+      }).then(function(verified){
+        return crypto.subtle.exportKey("pkcs8",keypair.privateKey);
+      }).then(function(pkcs8){
+        return crypto.subtle.importKey("pkcs8", pkcs8, algo, true, ["sign"]);
+      }).then(function(importedKey){
+        return crypto.subtle.exportKey("spki", keypair.publicKey);
+      }).then(function(spki){
+        return crypto.subtle.importKey("spki", spki, algo, true, ["verify"]);
+      }).then(function(importedKey){
+        var testDigest = new Uint8Array([1,2,3,4,5]);
+        return crypto.subtle.digest({name:"SHA-256"}, testDigest.buffer);
+      }).then(function(result){
+        use = true;
+      }, function(err){
+        console.log("DetectSubtleCrypto encountered error, not using crypto.subtle: ", err)
+      });
   }
-
-/**
- * Base 64 to Raw String 
- */
-DataUtils.base64toString = function base64toString(input) {
-     var output = "";
-     var chr1, chr2, chr3 = "";
-     var enc1, enc2, enc3, enc4 = "";
-     var i = 0;
-
-     // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
-     var base64test = /[^A-Za-z0-9\+\/\=]/g;
-     /* Test for invalid characters. */
-     if (base64test.exec(input)) {
-        alert("There were invalid base64 characters in the input text.\n" +
-              "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
-              "Expect errors in decoding.");
-     }
-     
-     input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
-
-     do {
-        enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
-        enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
-        enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
-        enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));
-
-        chr1 = (enc1 << 2) | (enc2 >> 4);
-        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
-        chr3 = ((enc3 & 3) << 6) | enc4;
-
-        output = output + String.fromCharCode(chr1);
-
-        if (enc3 != 64) {
-           output = output + String.fromCharCode(chr2);
-        }
-        if (enc4 != 64) {
-           output = output + String.fromCharCode(chr3);
-        }
-
-        chr1 = chr2 = chr3 = "";
-        enc1 = enc2 = enc3 = enc4 = "";
-
-     } while (i < input.length);
-
-     return unescape(output);
-  };
-
-//byte [] 
-
-/**
- * NOT WORKING!!!!!
- * 
- * Unsiged Long Number to Byte Array
- */
-	
- /*
-DataUtils.unsignedLongToByteArray= function( value) {
-	
-	if(LOG>4)console.log('INPUT IS '+value);
-	
-	if( 0 == value )
-		return [0];
-
-	if( 0 <= value && value <= 0x00FF ) {
-		//byte [] 
-		var bb = new Array(1);
-		bb[0] = (value & 0x00FF);
-		return bb;
-	}
-
-	if(LOG>4) console.log('type of value is '+typeof value);
-	if(LOG>4) console.log('value is '+value);
-	//byte [] 
-	var out = null;
-	//int
-	var offset = -1;
-	for(var i = 7; i >=0; --i) {
-		//byte
-		console.log(i);
-		console.log('value is '+value);
-		console.log('(value >> (i * 8)) '+ (value >> (i * 8))  );
-		console.log(' ((value >> (i * 8)) & 0xFF) '+ ((value >> (i * 8)) & 0xFF)  );
-
-		var b = ((value >> (i * 8)) & 0xFF)  ;
-		
-		if(LOG>4) console.log('b is '+b);
-		
-		if( out == null && b != 0 ) {
-			//out = new byte[i+1];
-			out = new Array(i+1);
-			offset = i;
-		}
-		
-		if( out != null )
-			out[ offset - i ] = b;
-	}
-	if(LOG>4)console.log('OUTPUT IS ');
-	if(LOG>4)console.log(out);
-	return out;
+  return function useSubtleCrypto(){
+    return use;
+  }
 }
+
+var UseSubtleCrypto = DetectSubtleCrypto();
+
+exports.UseSubtleCrypto = UseSubtleCrypto;
+/*! CryptoJS v3.1.2 core-fix.js
+ * code.google.com/p/crypto-js
+ * (c) 2009-2013 by Jeff Mott. All rights reserved.
+ * code.google.com/p/crypto-js/wiki/License
+ * THIS IS FIX of 'core.js' to fix Hmac issue.
+ * https://code.google.com/p/crypto-js/issues/detail?id=84
+ * https://crypto-js.googlecode.com/svn-history/r667/branches/3.x/src/core.js
+ */
+/**
+ * CryptoJS core components.
+ */
+var CryptoJS = CryptoJS || (function (Math, undefined) {
+    /**
+     * CryptoJS namespace.
+     */
+    var C = {};
+
+    /**
+     * Library namespace.
+     */
+    var C_lib = C.lib = {};
+
+    /**
+     * Base object for prototypal inheritance.
+     */
+    var Base = C_lib.Base = (function () {
+        function F() {}
+
+        return {
+            /**
+             * Creates a new object that inherits from this object.
+             *
+             * @param {Object} overrides Properties to copy into the new object.
+             *
+             * @return {Object} The new object.
+             *
+             * @static
+             *
+             * @example
+             *
+             *     var MyType = CryptoJS.lib.Base.extend({
+             *         field: 'value',
+             *
+             *         method: function () {
+             *         }
+             *     });
+             */
+            extend: function (overrides) {
+                // Spawn
+                F.prototype = this;
+                var subtype = new F();
+
+                // Augment
+                if (overrides) {
+                    subtype.mixIn(overrides);
+                }
+
+                // Create default initializer
+                if (!subtype.hasOwnProperty('init')) {
+                    subtype.init = function () {
+                        subtype.$super.init.apply(this, arguments);
+                    };
+                }
+
+                // Initializer's prototype is the subtype object
+                subtype.init.prototype = subtype;
+
+                // Reference supertype
+                subtype.$super = this;
+
+                return subtype;
+            },
+
+            /**
+             * Extends this object and runs the init method.
+             * Arguments to create() will be passed to init().
+             *
+             * @return {Object} The new object.
+             *
+             * @static
+             *
+             * @example
+             *
+             *     var instance = MyType.create();
+             */
+            create: function () {
+                var instance = this.extend();
+                instance.init.apply(instance, arguments);
+
+                return instance;
+            },
+
+            /**
+             * Initializes a newly created object.
+             * Override this method to add some logic when your objects are created.
+             *
+             * @example
+             *
+             *     var MyType = CryptoJS.lib.Base.extend({
+             *         init: function () {
+             *             // ...
+             *         }
+             *     });
+             */
+            init: function () {
+            },
+
+            /**
+             * Copies properties into this object.
+             *
+             * @param {Object} properties The properties to mix in.
+             *
+             * @example
+             *
+             *     MyType.mixIn({
+             *         field: 'value'
+             *     });
+             */
+            mixIn: function (properties) {
+                for (var propertyName in properties) {
+                    if (properties.hasOwnProperty(propertyName)) {
+                        this[propertyName] = properties[propertyName];
+                    }
+                }
+
+                // IE won't copy toString using the loop above
+                if (properties.hasOwnProperty('toString')) {
+                    this.toString = properties.toString;
+                }
+            },
+
+            /**
+             * Creates a copy of this object.
+             *
+             * @return {Object} The clone.
+             *
+             * @example
+             *
+             *     var clone = instance.clone();
+             */
+            clone: function () {
+                return this.init.prototype.extend(this);
+            }
+        };
+    }());
+
+    /**
+     * An array of 32-bit words.
+     *
+     * @property {Array} words The array of 32-bit words.
+     * @property {number} sigBytes The number of significant bytes in this word array.
+     */
+    var WordArray = C_lib.WordArray = Base.extend({
+        /**
+         * Initializes a newly created word array.
+         *
+         * @param {Array} words (Optional) An array of 32-bit words.
+         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.lib.WordArray.create();
+         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
+         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
+         */
+        init: function (words, sigBytes) {
+            words = this.words = words || [];
+
+            if (sigBytes != undefined) {
+                this.sigBytes = sigBytes;
+            } else {
+                this.sigBytes = words.length * 4;
+            }
+        },
+
+        /**
+         * Converts this word array to a string.
+         *
+         * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
+         *
+         * @return {string} The stringified word array.
+         *
+         * @example
+         *
+         *     var string = wordArray + '';
+         *     var string = wordArray.toString();
+         *     var string = wordArray.toString(CryptoJS.enc.Utf8);
+         */
+        toString: function (encoder) {
+            return (encoder || Hex).stringify(this);
+        },
+
+        /**
+         * Concatenates a word array to this word array.
+         *
+         * @param {WordArray} wordArray The word array to append.
+         *
+         * @return {WordArray} This word array.
+         *
+         * @example
+         *
+         *     wordArray1.concat(wordArray2);
+         */
+        concat: function (wordArray) {
+            // Shortcuts
+            var thisWords = this.words;
+            var thatWords = wordArray.words;
+            var thisSigBytes = this.sigBytes;
+            var thatSigBytes = wordArray.sigBytes;
+
+            // Clamp excess bits
+            this.clamp();
+
+            // Concat
+            if (thisSigBytes % 4) {
+                // Copy one byte at a time
+                for (var i = 0; i < thatSigBytes; i++) {
+                    var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+                    thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
+                }
+            } else {
+                // Copy one word at a time
+                for (var i = 0; i < thatSigBytes; i += 4) {
+                    thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
+                }
+            }
+            this.sigBytes += thatSigBytes;
+
+            // Chainable
+            return this;
+        },
+
+        /**
+         * Removes insignificant bits.
+         *
+         * @example
+         *
+         *     wordArray.clamp();
+         */
+        clamp: function () {
+            // Shortcuts
+            var words = this.words;
+            var sigBytes = this.sigBytes;
+
+            // Clamp
+            words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
+            words.length = Math.ceil(sigBytes / 4);
+        },
+
+        /**
+         * Creates a copy of this word array.
+         *
+         * @return {WordArray} The clone.
+         *
+         * @example
+         *
+         *     var clone = wordArray.clone();
+         */
+        clone: function () {
+            var clone = Base.clone.call(this);
+            clone.words = this.words.slice(0);
+
+            return clone;
+        },
+
+        /**
+         * Creates a word array filled with random bytes.
+         *
+         * @param {number} nBytes The number of random bytes to generate.
+         *
+         * @return {WordArray} The random word array.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.lib.WordArray.random(16);
+         */
+        random: function (nBytes) {
+            var words = [];
+            for (var i = 0; i < nBytes; i += 4) {
+                words.push((Math.random() * 0x100000000) | 0);
+            }
+
+            return new WordArray.init(words, nBytes);
+        }
+    });
+
+    /**
+     * Encoder namespace.
+     */
+    var C_enc = C.enc = {};
+
+    /**
+     * Hex encoding strategy.
+     */
+    var Hex = C_enc.Hex = {
+        /**
+         * Converts a word array to a hex string.
+         *
+         * @param {WordArray} wordArray The word array.
+         *
+         * @return {string} The hex string.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
+         */
+        stringify: function (wordArray) {
+            // Shortcuts
+            var words = wordArray.words;
+            var sigBytes = wordArray.sigBytes;
+
+            // Convert
+            var hexChars = [];
+            for (var i = 0; i < sigBytes; i++) {
+                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+                hexChars.push((bite >>> 4).toString(16));
+                hexChars.push((bite & 0x0f).toString(16));
+            }
+
+            return hexChars.join('');
+        },
+
+        /**
+         * Converts a hex string to a word array.
+         *
+         * @param {string} hexStr The hex string.
+         *
+         * @return {WordArray} The word array.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
+         */
+        parse: function (hexStr) {
+            // Shortcut
+            var hexStrLength = hexStr.length;
+
+            // Convert
+            var words = [];
+            for (var i = 0; i < hexStrLength; i += 2) {
+                words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
+            }
+
+            return new WordArray.init(words, hexStrLength / 2);
+        }
+    };
+
+    /**
+     * Latin1 encoding strategy.
+     */
+    var Latin1 = C_enc.Latin1 = {
+        /**
+         * Converts a word array to a Latin1 string.
+         *
+         * @param {WordArray} wordArray The word array.
+         *
+         * @return {string} The Latin1 string.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
+         */
+        stringify: function (wordArray) {
+            // Shortcuts
+            var words = wordArray.words;
+            var sigBytes = wordArray.sigBytes;
+
+            // Convert
+            var latin1Chars = [];
+            for (var i = 0; i < sigBytes; i++) {
+                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+                latin1Chars.push(String.fromCharCode(bite));
+            }
+
+            return latin1Chars.join('');
+        },
+
+        /**
+         * Converts a Latin1 string to a word array.
+         *
+         * @param {string} latin1Str The Latin1 string.
+         *
+         * @return {WordArray} The word array.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
+         */
+        parse: function (latin1Str) {
+            // Shortcut
+            var latin1StrLength = latin1Str.length;
+
+            // Convert
+            var words = [];
+            for (var i = 0; i < latin1StrLength; i++) {
+                words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
+            }
+
+            return new WordArray.init(words, latin1StrLength);
+        }
+    };
+
+    /**
+     * UTF-8 encoding strategy.
+     */
+    var Utf8 = C_enc.Utf8 = {
+        /**
+         * Converts a word array to a UTF-8 string.
+         *
+         * @param {WordArray} wordArray The word array.
+         *
+         * @return {string} The UTF-8 string.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
+         */
+        stringify: function (wordArray) {
+            try {
+                return decodeURIComponent(escape(Latin1.stringify(wordArray)));
+            } catch (e) {
+                throw new Error('Malformed UTF-8 data');
+            }
+        },
+
+        /**
+         * Converts a UTF-8 string to a word array.
+         *
+         * @param {string} utf8Str The UTF-8 string.
+         *
+         * @return {WordArray} The word array.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
+         */
+        parse: function (utf8Str) {
+            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
+        }
+    };
+
+    /**
+     * Abstract buffered block algorithm template.
+     *
+     * The property blockSize must be implemented in a concrete subtype.
+     *
+     * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
+     */
+    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
+        /**
+         * Resets this block algorithm's data buffer to its initial state.
+         *
+         * @example
+         *
+         *     bufferedBlockAlgorithm.reset();
+         */
+        reset: function () {
+            // Initial values
+            this._data = new WordArray.init();
+            this._nDataBytes = 0;
+        },
+
+        /**
+         * Adds new data to this block algorithm's buffer.
+         *
+         * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
+         *
+         * @example
+         *
+         *     bufferedBlockAlgorithm._append('data');
+         *     bufferedBlockAlgorithm._append(wordArray);
+         */
+        _append: function (data) {
+            // Convert string to WordArray, else assume WordArray already
+            if (typeof data == 'string') {
+                data = Utf8.parse(data);
+            }
+
+            // Append
+            this._data.concat(data);
+            this._nDataBytes += data.sigBytes;
+        },
+
+        /**
+         * Processes available data blocks.
+         *
+         * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
+         *
+         * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
+         *
+         * @return {WordArray} The processed data.
+         *
+         * @example
+         *
+         *     var processedData = bufferedBlockAlgorithm._process();
+         *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
+         */
+        _process: function (doFlush) {
+            // Shortcuts
+            var data = this._data;
+            var dataWords = data.words;
+            var dataSigBytes = data.sigBytes;
+            var blockSize = this.blockSize;
+            var blockSizeBytes = blockSize * 4;
+
+            // Count blocks ready
+            var nBlocksReady = dataSigBytes / blockSizeBytes;
+            if (doFlush) {
+                // Round up to include partial blocks
+                nBlocksReady = Math.ceil(nBlocksReady);
+            } else {
+                // Round down to include only full blocks,
+                // less the number of blocks that must remain in the buffer
+                nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
+            }
+
+            // Count words ready
+            var nWordsReady = nBlocksReady * blockSize;
+
+            // Count bytes ready
+            var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
+
+            // Process blocks
+            if (nWordsReady) {
+                for (var offset = 0; offset < nWordsReady; offset += blockSize) {
+                    // Perform concrete-algorithm logic
+                    this._doProcessBlock(dataWords, offset);
+                }
+
+                // Remove processed words
+                var processedWords = dataWords.splice(0, nWordsReady);
+                data.sigBytes -= nBytesReady;
+            }
+
+            // Return processed words
+            return new WordArray.init(processedWords, nBytesReady);
+        },
+
+        /**
+         * Creates a copy of this object.
+         *
+         * @return {Object} The clone.
+         *
+         * @example
+         *
+         *     var clone = bufferedBlockAlgorithm.clone();
+         */
+        clone: function () {
+            var clone = Base.clone.call(this);
+            clone._data = this._data.clone();
+
+            return clone;
+        },
+
+        _minBufferSize: 0
+    });
+
+    /**
+     * Abstract hasher template.
+     *
+     * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
+     */
+    var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
+        /**
+         * Configuration options.
+         */
+        cfg: Base.extend(),
+
+        /**
+         * Initializes a newly created hasher.
+         *
+         * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
+         *
+         * @example
+         *
+         *     var hasher = CryptoJS.algo.SHA256.create();
+         */
+        init: function (cfg) {
+            // Apply config defaults
+            this.cfg = this.cfg.extend(cfg);
+
+            // Set initial values
+            this.reset();
+        },
+
+        /**
+         * Resets this hasher to its initial state.
+         *
+         * @example
+         *
+         *     hasher.reset();
+         */
+        reset: function () {
+            // Reset data buffer
+            BufferedBlockAlgorithm.reset.call(this);
+
+            // Perform concrete-hasher logic
+            this._doReset();
+        },
+
+        /**
+         * Updates this hasher with a message.
+         *
+         * @param {WordArray|string} messageUpdate The message to append.
+         *
+         * @return {Hasher} This hasher.
+         *
+         * @example
+         *
+         *     hasher.update('message');
+         *     hasher.update(wordArray);
+         */
+        update: function (messageUpdate) {
+            // Append
+            this._append(messageUpdate);
+
+            // Update the hash
+            this._process();
+
+            // Chainable
+            return this;
+        },
+
+        /**
+         * Finalizes the hash computation.
+         * Note that the finalize operation is effectively a destructive, read-once operation.
+         *
+         * @param {WordArray|string} messageUpdate (Optional) A final message update.
+         *
+         * @return {WordArray} The hash.
+         *
+         * @example
+         *
+         *     var hash = hasher.finalize();
+         *     var hash = hasher.finalize('message');
+         *     var hash = hasher.finalize(wordArray);
+         */
+        finalize: function (messageUpdate) {
+            // Final message update
+            if (messageUpdate) {
+                this._append(messageUpdate);
+            }
+
+            // Perform concrete-hasher logic
+            var hash = this._doFinalize();
+
+            return hash;
+        },
+
+        blockSize: 512/32,
+
+        /**
+         * Creates a shortcut function to a hasher's object interface.
+         *
+         * @param {Hasher} hasher The hasher to create a helper for.
+         *
+         * @return {Function} The shortcut function.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
+         */
+        _createHelper: function (hasher) {
+            return function (message, cfg) {
+                return new hasher.init(cfg).finalize(message);
+            };
+        },
+
+        /**
+         * Creates a shortcut function to the HMAC's object interface.
+         *
+         * @param {Hasher} hasher The hasher to use in this HMAC helper.
+         *
+         * @return {Function} The shortcut function.
+         *
+         * @static
+         *
+         * @example
+         *
+         *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
+         */
+        _createHmacHelper: function (hasher) {
+            return function (message, key) {
+                return new C_algo.HMAC.init(hasher, key).finalize(message);
+            };
+        }
+    });
+
+    /**
+     * Algorithm namespace.
+     */
+    var C_algo = C.algo = {};
+
+    return C;
+}(Math));
+
+exports.CryptoJS = CryptoJS;
+module.exports = exports;
+/*
+CryptoJS v3.1.2
+code.google.com/p/crypto-js
+(c) 2009-2013 by Jeff Mott. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
+associated documentation files (the "Software"), to deal in the Software without restriction, including 
+without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
+sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+code.google.com/p/crypto-js/wiki/License
+*/
+
+var C = require('./core.js').CryptoJS;
+(function (Math) {
+    // Shortcuts
+    var C_lib = C.lib;
+    var WordArray = C_lib.WordArray;
+    var Hasher = C_lib.Hasher;
+    var C_algo = C.algo;
+
+    // Initialization and round constants tables
+    var H = [];
+    var K = [];
+
+    // Compute constants
+    (function () {
+        function isPrime(n) {
+            var sqrtN = Math.sqrt(n);
+            for (var factor = 2; factor <= sqrtN; factor++) {
+                if (!(n % factor)) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        function getFractionalBits(n) {
+            return ((n - (n | 0)) * 0x100000000) | 0;
+        }
+
+        var n = 2;
+        var nPrime = 0;
+        while (nPrime < 64) {
+            if (isPrime(n)) {
+                if (nPrime < 8) {
+                    H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
+                }
+                K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
+
+                nPrime++;
+            }
+
+            n++;
+        }
+    }());
+
+    // Reusable object
+    var W = [];
+
+    /**
+     * SHA-256 hash algorithm.
+     */
+    var SHA256 = C_algo.SHA256 = Hasher.extend({
+        _doReset: function () {
+            this._hash = new WordArray.init(H.slice(0));
+        },
+
+        _doProcessBlock: function (M, offset) {
+            // Shortcut
+            var H = this._hash.words;
+
+            // Working variables
+            var a = H[0];
+            var b = H[1];
+            var c = H[2];
+            var d = H[3];
+            var e = H[4];
+            var f = H[5];
+            var g = H[6];
+            var h = H[7];
+
+            // Computation
+            for (var i = 0; i < 64; i++) {
+                if (i < 16) {
+                    W[i] = M[offset + i] | 0;
+                } else {
+                    var gamma0x = W[i - 15];
+                    var gamma0  = ((gamma0x << 25) | (gamma0x >>> 7))  ^
+                                  ((gamma0x << 14) | (gamma0x >>> 18)) ^
+                                   (gamma0x >>> 3);
+
+                    var gamma1x = W[i - 2];
+                    var gamma1  = ((gamma1x << 15) | (gamma1x >>> 17)) ^
+                                  ((gamma1x << 13) | (gamma1x >>> 19)) ^
+                                   (gamma1x >>> 10);
+
+                    W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
+                }
+
+                var ch  = (e & f) ^ (~e & g);
+                var maj = (a & b) ^ (a & c) ^ (b & c);
+
+                var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
+                var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7)  | (e >>> 25));
+
+                var t1 = h + sigma1 + ch + K[i] + W[i];
+                var t2 = sigma0 + maj;
+
+                h = g;
+                g = f;
+                f = e;
+                e = (d + t1) | 0;
+                d = c;
+                c = b;
+                b = a;
+                a = (t1 + t2) | 0;
+            }
+
+            // Intermediate hash value
+            H[0] = (H[0] + a) | 0;
+            H[1] = (H[1] + b) | 0;
+            H[2] = (H[2] + c) | 0;
+            H[3] = (H[3] + d) | 0;
+            H[4] = (H[4] + e) | 0;
+            H[5] = (H[5] + f) | 0;
+            H[6] = (H[6] + g) | 0;
+            H[7] = (H[7] + h) | 0;
+        },
+
+        _doFinalize: function () {
+            // Shortcuts
+            var data = this._data;
+            var dataWords = data.words;
+
+            var nBitsTotal = this._nDataBytes * 8;
+            var nBitsLeft = data.sigBytes * 8;
+
+            // Add padding
+            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
+            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
+            data.sigBytes = dataWords.length * 4;
+
+            // Hash final blocks
+            this._process();
+
+            // Return final computed hash
+            return this._hash;
+        },
+
+        clone: function () {
+            var clone = Hasher.clone.call(this);
+            clone._hash = this._hash.clone();
+
+            return clone;
+        }
+    });
+
+    /**
+     * Shortcut function to the hasher's object interface.
+     *
+     * @param {WordArray|string} message The message to hash.
+     *
+     * @return {WordArray} The hash.
+     *
+     * @static
+     *
+     * @example
+     *
+     *     var hash = CryptoJS.SHA256('message');
+     *     var hash = CryptoJS.SHA256(wordArray);
+     */
+    C.SHA256 = Hasher._createHelper(SHA256);
+
+    /**
+     * Shortcut function to the HMAC's object interface.
+     *
+     * @param {WordArray|string} message The message to hash.
+     * @param {WordArray|string} key The secret key.
+     *
+     * @return {WordArray} The HMAC.
+     *
+     * @static
+     *
+     * @example
+     *
+     *     var hmac = CryptoJS.HmacSHA256(message, key);
+     */
+    C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
+}(Math));
+
+exports.CryptoJS = C;
+module.exports = exports;
+/*
+CryptoJS v3.1.2
+code.google.com/p/crypto-js
+(c) 2009-2013 by Jeff Mott. All rights reserved.
+code.google.com/p/crypto-js/wiki/License
 */
-	
-/**
- * NOT WORKING!!!!!
- * 
- * Unsiged Long Number to Byte Array
- *//*
-DataUtils.byteArrayToUnsignedLong = function(//final byte [] 
-	src) {
-		if(LOG>4) console.log('INPUT IS ');
-		if(LOG>4) console.log(src);
-		
-		var value = 0;
-		for(var i = 0; i < src.length; i++) {
-			value = value << 8;
-			// Java will assume the byte is signed, so extend it and trim it.
-			
-			
-			var b = ((src[i]) & 0xFF );
-			value |= b;
-		}
-		
-		if(LOG>4) console.log('OUTPUT IS ');
-		
-		if(LOG>4) console.log(value);
-
-		return value;
-	}*/
-
-
-/**
- * Hex String to Byte Array
+(function () {
+    // Shortcuts
+    var C = CryptoJS;
+    var C_lib = C.lib;
+    var Base = C_lib.Base;
+    var C_enc = C.enc;
+    var Utf8 = C_enc.Utf8;
+    var C_algo = C.algo;
+
+    /**
+     * HMAC algorithm.
+     */
+    var HMAC = C_algo.HMAC = Base.extend({
+        /**
+         * Initializes a newly created HMAC.
+         *
+         * @param {Hasher} hasher The hash algorithm to use.
+         * @param {WordArray|string} key The secret key.
+         *
+         * @example
+         *
+         *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
+         */
+        init: function (hasher, key) {
+            // Init hasher
+            hasher = this._hasher = new hasher.init();
+
+            // Convert string to WordArray, else assume WordArray already
+            if (typeof key == 'string') {
+                key = Utf8.parse(key);
+            }
+
+            // Shortcuts
+            var hasherBlockSize = hasher.blockSize;
+            var hasherBlockSizeBytes = hasherBlockSize * 4;
+
+            // Allow arbitrary length keys
+            if (key.sigBytes > hasherBlockSizeBytes) {
+                key = hasher.finalize(key);
+            }
+
+            // Clamp excess bits
+            key.clamp();
+
+            // Clone key for inner and outer pads
+            var oKey = this._oKey = key.clone();
+            var iKey = this._iKey = key.clone();
+
+            // Shortcuts
+            var oKeyWords = oKey.words;
+            var iKeyWords = iKey.words;
+
+            // XOR keys with pad constants
+            for (var i = 0; i < hasherBlockSize; i++) {
+                oKeyWords[i] ^= 0x5c5c5c5c;
+                iKeyWords[i] ^= 0x36363636;
+            }
+            oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;
+
+            // Set initial values
+            this.reset();
+        },
+
+        /**
+         * Resets this HMAC to its initial state.
+         *
+         * @example
+         *
+         *     hmacHasher.reset();
+         */
+        reset: function () {
+            // Shortcut
+            var hasher = this._hasher;
+
+            // Reset
+            hasher.reset();
+            hasher.update(this._iKey);
+        },
+
+        /**
+         * Updates this HMAC with a message.
+         *
+         * @param {WordArray|string} messageUpdate The message to append.
+         *
+         * @return {HMAC} This HMAC instance.
+         *
+         * @example
+         *
+         *     hmacHasher.update('message');
+         *     hmacHasher.update(wordArray);
+         */
+        update: function (messageUpdate) {
+            this._hasher.update(messageUpdate);
+
+            // Chainable
+            return this;
+        },
+
+        /**
+         * Finalizes the HMAC computation.
+         * Note that the finalize operation is effectively a destructive, read-once operation.
+         *
+         * @param {WordArray|string} messageUpdate (Optional) A final message update.
+         *
+         * @return {WordArray} The HMAC.
+         *
+         * @example
+         *
+         *     var hmac = hmacHasher.finalize();
+         *     var hmac = hmacHasher.finalize('message');
+         *     var hmac = hmacHasher.finalize(wordArray);
+         */
+        finalize: function (messageUpdate) {
+            // Shortcut
+            var hasher = this._hasher;
+
+            // Compute HMAC
+            var innerHash = hasher.finalize(messageUpdate);
+            hasher.reset();
+            var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
+
+            return hmac;
+        }
+    });
+}());
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
  */
-	//THIS IS NOT WORKING
-/*
-DataUtils.HexStringtoByteArray = function(str) {
-    var byteArray = [];
-    for (var i = 0; i < str.length; i++)
-        if (str.charCodeAt(i) <= 0x7F)
-            byteArray.push(str.charCodeAt(i));
-        else {
-            var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
-            for (var j = 0; j < h.length; j++)
-                byteArray.push(parseInt(h[j], 16));
-        }
-    return byteArray;
-};
-*/
-
-/**
- * Uint8Array to Hex String
- */
-//http://ejohn.org/blog/numbers-hex-and-colors/
-DataUtils.toHex = function(args){
-	if (LOG>4) console.log('ABOUT TO CONVERT '+ args);
-	//console.log(args);
-  	var ret = "";
-  	for ( var i = 0; i < args.length; i++ )
-    	ret += (args[i] < 16 ? "0" : "") + args[i].toString(16);
-  	if (LOG>4) console.log('Converted to: ' + ret);
-  	return ret; //.toUpperCase();
-}
-
-/**
- * Raw string to hex string.
- */
-DataUtils.stringToHex = function(args){
-	var ret = "";
-	for (var i = 0; i < args.length; ++i) {
-		var value = args.charCodeAt(i);
-		ret += (value < 16 ? "0" : "") + value.toString(16);
-	}
-	return ret;
-}
-
-/**
- * Uint8Array to raw string.
- */
-DataUtils.toString = function(args){
-  //console.log(arguments);
-  var ret = "";
-  for ( var i = 0; i < args.length; i++ )
-    ret += String.fromCharCode(args[i]);
-  return ret;
-}
-
-/**
- * Hex String to Uint8Array.
- */
-DataUtils.toNumbers = function(str) {
-	if (typeof str == 'string') {
-		var ret = new Uint8Array(Math.floor(str.length / 2));
-        var i = 0;
-		str.replace(/(..)/g, function(str) {
-		    ret[i++] = parseInt(str, 16);
-		});
-		return ret;
-    }
-}
-
-/**
- * Hex String to raw string.
- */
-DataUtils.hexToRawString = function(str) {
-    if(typeof str =='string') {
-		var ret = "";
-		str.replace(/(..)/g, function(s) {
-			ret += String.fromCharCode(parseInt(s, 16));
-		});
-		return ret;
-    }
-}
-
-/**
- * Raw String to Uint8Array.
- */
-DataUtils.toNumbersFromString = function(str) {
-	var bytes = new Uint8Array(str.length);
-	for(var i=0;i<str.length;i++)
-		bytes[i] = str.charCodeAt(i);
-	return bytes;
-}
-
-/*
- * Encode str as utf8 and return as Uint8Array.
- * TODO: Use TextEncoder when available.
- */
-DataUtils.stringToUtf8Array = function(str) {
-    return DataUtils.toNumbersFromString(str2rstr_utf8(str));
-}
-
-/*
- * arrays is an array of Uint8Array. Return a new Uint8Array which is the concatenation of all.
- */
-DataUtils.concatArrays = function(arrays) {
-    var totalLength = 0;
-	for (var i = 0; i < arrays.length; ++i)
-        totalLength += arrays[i].length;
-    
-    var result = new Uint8Array(totalLength);
-    var offset = 0;
-	for (var i = 0; i < arrays.length; ++i) {
-        result.set(arrays[i], offset);
-        offset += arrays[i].length;
-    }
-    return result;
-    
-}
- 
-// TODO: Take Uint8Array and use TextDecoder when available.
-DataUtils.decodeUtf8 = function (utftext) {
-		var string = "";
-		var i = 0;
-		var c = 0;
-        var c1 = 0;
-        var c2 = 0;
- 
-		while ( i < utftext.length ) {
- 
-			c = utftext.charCodeAt(i);
- 
-			if (c < 128) {
-				string += String.fromCharCode(c);
-				i++;
-			}
-			else if((c > 191) && (c < 224)) {
-				c2 = utftext.charCodeAt(i+1);
-				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
-				i += 2;
-			}
-			else {
-				c2 = utftext.charCodeAt(i+1);
-				var c3 = utftext.charCodeAt(i+2);
-				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
-				i += 3;
-			}
- 
-		}
- 
-		return string;
-	};
-
-//NOT WORKING
-/*
-DataUtils.getUTF8StringFromBytes = function(bytes) {
-	
-	bytes = toString(bytes);
-
-    var ix = 0;
- 
-    if( bytes.slice(0,3) == "\xEF\xBB\xBF") {
-        ix = 3;
-    }
- 
-    var string = "";
-    for( ; ix < bytes.length; ix++ ) {
-        var byte1 = bytes[ix].charCodeAt(0);
-        if( byte1 < 0x80 ) {
-            string += String.fromCharCode(byte1);
-        } else if( byte1 >= 0xC2 && byte1 < 0xE0 ) {
-            var byte2 = bytes[++ix].charCodeAt(0);
-            string += String.fromCharCode(((byte1&0x1F)<<6) + (byte2&0x3F));
-        } else if( byte1 >= 0xE0 && byte1 < 0xF0 ) {
-            var byte2 = bytes[++ix].charCodeAt(0);
-            var byte3 = bytes[++ix].charCodeAt(0);
-            string += String.fromCharCode(((byte1&0xFF)<<12) + ((byte2&0x3F)<<6) + (byte3&0x3F));
-        } else if( byte1 >= 0xF0 && byte1 < 0xF5) {
-            var byte2 = bytes[++ix].charCodeAt(0);
-            var byte3 = bytes[++ix].charCodeAt(0);
-            var byte4 = bytes[++ix].charCodeAt(0);
-            var codepoint = ((byte1&0x07)<<18) + ((byte2&0x3F)<<12)+ ((byte3&0x3F)<<6) + (byte4&0x3F);
-            codepoint -= 0x10000;
-            string += String.fromCharCode(
-                (codepoint>>10) + 0xD800,
-                (codepoint&0x3FF) + 0xDC00
-            );
-        }
-    }
- 
-    return string;
-}*/
-
-/**
- * Return true if a1 and a2 are the same length with equal elements.
- */
-DataUtils.arraysEqual = function(a1, a2){
-    if (a1.length != a2.length)
-        return false;
-    
-    for (var i = 0; i < a1.length; ++i) {
-        if (a1[i] != a2[i])
-            return false;
-    }
-
-    return true;
-};
-
-/*
- * Convert the big endian Uint8Array to an unsigned int.
- * Don't check for overflow.
- */
-DataUtils.bigEndianToUnsignedInt = function(bytes) {
-    var result = 0;
-    for (var i = 0; i < bytes.length; ++i) {
-        result <<= 8;
-        result += bytes[i];
-    }
-    return result;
-};
-
-/*
- * Convert the int value to a new big endian Uint8Array and return.
- * If value is 0 or negative, return Uint8Array(0). 
- */
-DataUtils.nonNegativeIntToBigEndian = function(value) {
-    value = Math.round(value);
-    if (value <= 0)
-        return new Uint8Array(0);
-    
-    // Assume value is not over 64 bits.
-    var size = 8;
-    var result = new Uint8Array(size);
-    var i = 0;
-    while (value != 0) {
-        ++i;
-        result[size - i] = value & 0xff;
-        value >>= 8;
-    }
-    return result.subarray(size - i, size);
-};
-
-/*
- * Modify array to randomly shuffle the elements.
- */
-DataUtils.shuffle = function(array) {
-    for (var i = array.length - 1; i >= 1; --i) {
-        // j is from 0 to i.
-        var j = Math.floor(Math.random() * (i + 1));
-        var temp = array[i];
-        array[i] = array[j];
-        array[j] = temp;
-    }
-}
-/**
- * This file contains utilities to help encode and decode NDN objects.
- * author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- */
-
-function encodeToHexInterest(interest){
-    return DataUtils.toHex(encodeToBinaryInterest(interest));
-}
-
-
-function encodeToBinaryInterest(interest) {
-	var enc = new BinaryXMLEncoder();
-	interest.to_ndnb(enc);
-	
-	return enc.getReducedOstream();
-}
-
-
-function encodeToHexContentObject(co){
-    return DataUtils.toHex(encodeToBinaryContentObject(co));
-}
-
-function encodeToBinaryContentObject(co){
-	var enc = new BinaryXMLEncoder();
-	co.to_ndnb(enc);
-
-	return enc.getReducedOstream();
-}
-
-function encodeForwardingEntry(co){
-	var enc = new BinaryXMLEncoder();
- 
-	co.to_ndnb(enc);
-	
-	var bytes = enc.getReducedOstream();
-
-	return bytes;
-
-	
-}
-
-
-
-function decodeHexFaceInstance(result){
-	
-	var numbers = DataUtils.toNumbers(result);
-			
-	
-	var decoder = new BinaryXMLDecoder(numbers);
-	
-	if(LOG>3)console.log('DECODING HEX FACE INSTANCE  \n'+numbers);
-
-	var faceInstance = new FaceInstance();
-
-	faceInstance.from_ndnb(decoder);
-
-	return faceInstance;
-	
-}
-
-
-
-function decodeHexInterest(result){
-	var numbers = DataUtils.toNumbers(result);	
-	
-	var decoder = new BinaryXMLDecoder(numbers);
-	
-	if(LOG>3)console.log('DECODING HEX INTERST  \n'+numbers);
-
-	var interest = new Interest();
-
-	interest.from_ndnb(decoder);
-
-	return interest;
-	
-}
-
-
-
-function decodeHexContentObject(result){
-	var numbers = DataUtils.toNumbers(result);
-	
-	var decoder = new BinaryXMLDecoder(numbers);
-	
-	if(LOG>3)console.log('DECODED HEX CONTENT OBJECT \n'+numbers);
-	
-	var co = new ContentObject();
-
-	co.from_ndnb(decoder);
-
-	return co;
-	
-}
-
-
-
-function decodeHexForwardingEntry(result){
-	var numbers = DataUtils.toNumbers(result);
-
-	var decoder = new BinaryXMLDecoder(numbers);
-	
-	if(LOG>3)console.log('DECODED HEX FORWARDING ENTRY \n'+numbers);
-	
-	var forwardingEntry = new ForwardingEntry();
-
-	forwardingEntry.from_ndnb(decoder);
-
-	return forwardingEntry;
-	
-}
-
-/*
- * Decode the Uint8Array which holds SubjectPublicKeyInfo and return an RSAKey.
- */
-function decodeSubjectPublicKeyInfo(array) {
-    var hex = DataUtils.toHex(array).toLowerCase();
-    var a = _x509_getPublicKeyHexArrayFromCertHex(hex, _x509_getSubjectPublicKeyPosFromCertHex(hex, 0));
-    var rsaKey = new RSAKey();
-    rsaKey.setPublic(a[0], a[1]);
-    return rsaKey;
-}
-
-/* Return a user friendly HTML string with the contents of co.
-   This also outputs to console.log.
- */
-function contentObjectToHtml(/* ContentObject */ co) {
-    var output ="";
-			
-    if(co==-1)
-	output+= "NO CONTENT FOUND"
-    else if (co==-2)
-	output+= "CONTENT NAME IS EMPTY"
-    else{
-	if(co.name!=null && co.name.components!=null){
-	    output+= "NAME: " + co.name.to_uri();
-        
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	
-	if(co.content !=null){
-	    output += "CONTENT(ASCII): "+ DataUtils.toString(co.content);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	if(co.content !=null){
-	    output += "CONTENT(hex): "+ DataUtils.toHex(co.content);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	if(co.signature !=null && co.signature.signature!=null){
-	    output += "SIGNATURE(hex): "+ DataUtils.toHex(co.signature.signature);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	if(co.signedInfo !=null && co.signedInfo.publisher!=null && co.signedInfo.publisher.publisherPublicKeyDigest!=null){
-	    output += "Publisher Public Key Digest(hex): "+ DataUtils.toHex(co.signedInfo.publisher.publisherPublicKeyDigest);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	}
-	if(co.signedInfo !=null && co.signedInfo.timestamp!=null){
-	    var d = new Date();
-	    d.setTime( co.signedInfo.timestamp.msec );
-	    
-	    var bytes = [217, 185, 12, 225, 217, 185, 12, 225];
-	    
-	    output += "TimeStamp: "+d;
-	    output+= "<br />";
-	    output += "TimeStamp(number): "+ co.signedInfo.timestamp.msec;
-	    
-	    output+= "<br />";
-	}
-	if(co.signedInfo !=null && co.signedInfo.finalBlockID!=null){
-	    output += "FinalBlockID: "+ DataUtils.toHex(co.signedInfo.finalBlockID);
-	    output+= "<br />";
-	}
-	if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.certificate!=null){
-	    var certificateHex = DataUtils.toHex(co.signedInfo.locator.certificate).toLowerCase();
-	    var signature = DataUtils.toHex(co.signature.signature).toLowerCase();
-	    var input = DataUtils.toString(co.rawSignatureData);
-	    
-	    output += "Hex Certificate: "+ certificateHex ;
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	    
-	    var x509 = new X509();
-	    x509.readCertHex(certificateHex);
-	    output += "Public key (hex) modulus: " + x509.subjectPublicKeyRSA.n.toString(16) + "<br/>";
-	    output += "exponent: " + x509.subjectPublicKeyRSA.e.toString(16) + "<br/>";
-	    output += "<br/>";
-	    
-	    var result = x509.subjectPublicKeyRSA.verifyByteArray(co.rawSignatureData, null, signature);
-	    if(LOG>2) console.log('result is '+result);
-	    
-	    var n = x509.subjectPublicKeyRSA.n;
-	    var e =  x509.subjectPublicKeyRSA.e;
-	    
-	    if(LOG>2) console.log('PUBLIC KEY n after is ');
-	    if(LOG>2) console.log(n);
-
-	    if(LOG>2) console.log('EXPONENT e after is ');
-	    if(LOG>2) console.log(e);
-	    
-	    if(result)
-            output += 'SIGNATURE VALID';
-	    else
-            output += 'SIGNATURE INVALID';
-	    
-	    //output += "VALID: "+ toHex(co.signedInfo.locator.publicKey);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	    
-	    //if(LOG>4) console.log('str'[1]);
-	}
-	if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.publicKey!=null){
-	    var publickeyHex = DataUtils.toHex(co.signedInfo.locator.publicKey).toLowerCase();
-	    var publickeyString = DataUtils.toString(co.signedInfo.locator.publicKey);
-	    var signature = DataUtils.toHex(co.signature.signature).toLowerCase();
-	    var input = DataUtils.toString(co.rawSignatureData);
-	    
-	    var wit = null;
-	    var witHex = "";
-		if (co.signature.Witness != null) {
-			wit = new Witness();
-			wit.decode(co.signature.Witness);
-			witHex = DataUtils.toHex(co.signature.Witness);
-		}
-	    
-	    output += "Public key: " + publickeyHex;
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	    
-	    if(LOG>2) console.log(" ContentName + SignedInfo + Content = "+input);
-	    if(LOG>2) console.log(" PublicKeyHex = "+publickeyHex );
-	    if(LOG>2) console.log(" PublicKeyString = "+publickeyString );
-	    
-	    if(LOG>2) console.log(" Signature "+signature );
-	    if(LOG>2) console.log(" Witness "+witHex );
-	    
-	    if(LOG>2) console.log(" Signature NOW IS" );
-	    
-	    if(LOG>2) console.log(co.signature.signature);
-	   
-	    var rsakey = decodeSubjectPublicKeyInfo(co.signedInfo.locator.publicKey);
-
-	    output += "Public key (hex) modulus: " + rsakey.n.toString(16) + "<br/>";
-	    output += "exponent: " + rsakey.e.toString(16) + "<br/>";
-	    output += "<br/>";
-	   	    
-	    var result = rsakey.verifyByteArray(co.rawSignatureData, wit, signature);
-	    // var result = rsakey.verifyString(input, signature);
-	    
-	    if(LOG>2) console.log('PUBLIC KEY n after is ');
-	    if(LOG>2) console.log(rsakey.n);
-
-	    if(LOG>2) console.log('EXPONENT e after is ');
-	    if(LOG>2) console.log(rsakey.e);
-	    
-	    if(result)
-			output += 'SIGNATURE VALID';
-	    else
-			output += 'SIGNATURE INVALID';
-	    
-	    //output += "VALID: "+ toHex(co.signedInfo.locator.publicKey);
-	    
-	    output+= "<br />";
-	    output+= "<br />";
-	    
-	    //if(LOG>4) console.log('str'[1]);
-	}
-    }
-
-    return output;
-}
-
-
-/**
- * @author: Meki Cheraoui
- * See COPYING for copyright and distribution information.
- */
-
-var KeyManager = function KeyManager(){
-
-	
-//Certificate
-
-this.certificate = 'MIIBmzCCAQQCCQC32FyQa61S7jANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwd'+
-
-'heGVsY2R2MB4XDTEyMDQyODIzNDQzN1oXDTEyMDUyODIzNDQzN1owEjEQMA4GA1'+
-
-'UEAxMHYXhlbGNkdjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4X0wp9goq'+
-
-'xuECxdULcr2IHr9Ih4Iaypg0Wy39URIup8/CLzQmdsh3RYqd55hqonu5VTTpH3i'+
-
-'MLx6xZDVJAZ8OJi7pvXcQ2C4Re2kjL2c8SanI0RfDhlS1zJadfr1VhRPmpivcYa'+
-
-'wJ4aFuOLAi+qHFxtN7lhcGCgpW1OV60oXd58CAwEAATANBgkqhkiG9w0BAQUFAA'+
-
-'OBgQDLOrA1fXzSrpftUB5Ro6DigX1Bjkf7F5Bkd69hSVp+jYeJFBBlsILQAfSxU'+
-
-'ZPQtD+2Yc3iCmSYNyxqu9PcufDRJlnvB7PG29+L3y9lR37tetzUV9eTscJ7rdp8'+
-
-'Wt6AzpW32IJ/54yKNfP7S6ZIoIG+LP6EIxq6s8K1MXRt8uBJKw==';
-
-
-//this.publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQAB';
-this.publicKey ='30819F300D06092A864886F70D010101050003818D0030818902818100E17D30A7D828AB1B840B17542DCAF6207AFD221E086B2A60D16CB7F54448BA9F3F08BCD099DB21DD162A779E61AA89EEE554D3A47DE230BC7AC590D524067C3898BBA6F5DC4360B845EDA48CBD9CF126A723445F0E1952D7325A75FAF556144F9A98AF7186B0278685B8E2C08BEA87171B4DEE585C1828295B5395EB4A17779F0203010001';
-//Private Key
-
-this.privateKey ='MIICXQIBAAKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQABAoGAGkv6T6jC3WmhFZYL6CdCWvlc6gysmKrhjarrLTxgavtFY6R5g2ft5BXAsCCVbUkWxkIFSKqxpVNl0gKZCNGEzPDN6mHJOQI/h0rlxNIHAuGfoAbCzALnqmyZivhJAPGijAyKuU9tczsst5+Kpn+bn7ehzHQuj7iwJonS5WbojqECQQD851K8TpW2GrRizNgG4dx6orZxAaon/Jnl8lS7soXhllQty7qG+oDfzznmdMsiznCqEABzHUUKOVGE9RWPN3aRAkEA5D/w9N55d0ibnChFJlc8cUAoaqH+w+U3oQP2Lb6AZHJpLptN4y4b/uf5d4wYU5/i/gC7SSBH3wFhh9bjRLUDLwJAVOx8vN0Kqt7myfKNbCo19jxjVSlA8TKCn1Oznl/BU1I+rC4oUaEW25DjmX6IpAR8kq7S59ThVSCQPjxqY/A08QJBAIRaF2zGPITQk3r/VumemCvLWiRK/yG0noc9dtibqHOWbCtcXtOm/xDWjq+lis2i3ssOvYrvrv0/HcDY+Dv1An0CQQCLJtMsfSg4kvG/FRY5UMhtMuwo8ovYcMXt4Xv/LWaMhndD67b2UGawQCRqr5ghRTABWdDD/HuuMBjrkPsX0861';
-
-
-/*
-	this.certificate = 
-			'MIIBvTCCASYCCQD55fNzc0WF7TANBgkqhkiG9w0BAQUFADAjMQswCQYDVQQGEwJK'+
-			'UDEUMBIGA1UEChMLMDAtVEVTVC1SU0EwHhcNMTAwNTI4MDIwODUxWhcNMjAwNTI1'+
-			'MDIwODUxWjAjMQswCQYDVQQGEwJKUDEUMBIGA1UEChMLMDAtVEVTVC1SU0EwgZ8w'+
-			'DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANGEYXtfgDRlWUSDn3haY4NVVQiKI9Cz'+
-			'Thoua9+DxJuiseyzmBBe7Roh1RPqdvmtOHmEPbJ+kXZYhbozzPRbFGHCJyBfCLzQ'+
-			'fVos9/qUQ88u83b0SFA2MGmQWQAlRtLy66EkR4rDRwTj2DzR4EEXgEKpIvo8VBs/'+
-			'3+sHLF3ESgAhAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAEZ6mXFFq3AzfaqWHmCy1'+
-			'ARjlauYAa8ZmUFnLm0emg9dkVBJ63aEqARhtok6bDQDzSJxiLpCEF6G4b/Nv/M/M'+
-			'LyhP+OoOTmETMegAVQMq71choVJyOFE5BtQa6M/lCHEOya5QUfoRF2HF9EjRF44K'+
-			'3OK+u3ivTSj3zwjtpudY5Xo=';
-	
-	this.privateKey =
-			'MIICWwIBAAKBgQDRhGF7X4A0ZVlEg594WmODVVUIiiPQs04aLmvfg8SborHss5gQ'+
-			'Xu0aIdUT6nb5rTh5hD2yfpF2WIW6M8z0WxRhwicgXwi80H1aLPf6lEPPLvN29EhQ'+
-			'NjBpkFkAJUbS8uuhJEeKw0cE49g80eBBF4BCqSL6PFQbP9/rByxdxEoAIQIDAQAB'+
-			'AoGAA9/q3Zk6ib2GFRpKDLO/O2KMnAfR+b4XJ6zMGeoZ7Lbpi3MW0Nawk9ckVaX0'+
-			'ZVGqxbSIX5Cvp/yjHHpww+QbUFrw/gCjLiiYjM9E8C3uAF5AKJ0r4GBPl4u8K4bp'+
-			'bXeSxSB60/wPQFiQAJVcA5xhZVzqNuF3EjuKdHsw+dk+dPECQQDubX/lVGFgD/xY'+
-			'uchz56Yc7VHX+58BUkNSewSzwJRbcueqknXRWwj97SXqpnYfKqZq78dnEF10SWsr'+
-			'/NMKi+7XAkEA4PVqDv/OZAbWr4syXZNv/Mpl4r5suzYMMUD9U8B2JIRnrhmGZPzL'+
-			'x23N9J4hEJ+Xh8tSKVc80jOkrvGlSv+BxwJAaTOtjA3YTV+gU7Hdza53sCnSw/8F'+
-			'YLrgc6NOJtYhX9xqdevbyn1lkU0zPr8mPYg/F84m6MXixm2iuSz8HZoyzwJARi2p'+
-			'aYZ5/5B2lwroqnKdZBJMGKFpUDn7Mb5hiSgocxnvMkv6NjT66Xsi3iYakJII9q8C'+
-			'Ma1qZvT/cigmdbAh7wJAQNXyoizuGEltiSaBXx4H29EdXNYWDJ9SS5f070BRbAIl'+
-			'dqRh3rcNvpY6BKJqFapda1DjdcncZECMizT/GMrc1w==';
-			
-			*/
-};
-
-
-KeyManager.prototype.verify = function verify(message,signature){
-	
-	var input = message;
-
-	var  _PEM_X509CERT_STRING_ = this.certificate;
-	
-	var x509 = new X509();
-	
-	x509.readCertPEM(_PEM_X509CERT_STRING_);
-	
-	var result = x509.subjectPublicKeyRSA.verifyString(input, signature);
-	
-	return result;
-};
-
-KeyManager.prototype.sign= function sign(message){
-	
-	var input = message;
-		
-	var  _PEM_PRIVATE_KEY_STRING_ = this.privateKey;
-	
-	var rsa = new RSAKey();
-	
-	rsa.readPrivateKeyFromPEMString(_PEM_PRIVATE_KEY_STRING_);
-	
-	var hSig = rsa.signString(input, "sha256");
-	
-	return hSig;
-
-};
-
-
-
-var globalKeyManager = new KeyManager();
-//var KeyPair = { "public" : "PUBLIC KEY" , "private" : "PRIVATE KEY" };
-
-
-/** 
- * @author: Wentao Shang
- * See COPYING for copyright and distribution information.
- */
-
-var MerklePath = function MerkelPath() {
-	this.index = null;  // int
-	this.digestList = [];  // array of hex string
-};
-
-var Witness = function Witness() {
-	this.oid = null;  // string
-	this.path = new MerklePath();  // MerklePath
-};
-
-function parseOID(bytes, start, end) {
-    var s, n = 0, bits = 0;
-    for (var i = start; i < end; ++i) {
-        var v = bytes[i];
-        n = (n << 7) | (v & 0x7F);
-        bits += 7;
-        if (!(v & 0x80)) { // finished
-            if (s == undefined)
-                s = parseInt(n / 40) + "." + (n % 40);
-            else
-                s += "." + ((bits >= 31) ? "bigint" : n);
-            n = bits = 0;
-        }
-        s += String.fromCharCode();
-    }
-    return s;
-}
-
-function parseInteger(bytes, start, end) {
-    var n = 0;
-    for (var i = start; i < end; ++i)
-        n = (n << 8) | bytes[i];
-    return n;
-}
-
-Witness.prototype.decode = function(/* Uint8Array */ witness) {
-	/* The asn1.js decoder has some bug and 
-	 * cannot decode certain kind of witness.
-	 * So we use an alternative (and dirty) hack
-	 * to read witness from byte streams
-	 *      ------Wentao
-	 */
-	/*
-	var wit = DataUtils.toHex(witness).toLowerCase();
-	try {
-		var der = Hex.decode(wit);
-		var asn1 = ASN1.decode(der);
-	}
-	catch (e) {
-		console.log(e);
-		console.log(wit);
-	}
-	//console.log(asn1.toPrettyString());
-	
-	this.oid = asn1.sub[0].sub[0].content();  // OID
-	//console.log(this.oid);
-	this.path.index = asn1.sub[1].sub[0].sub[0].content();  // index
-	//console.log(this.path.index);
-	for (i = 0; i < asn1.sub[1].sub[0].sub[1].sub.length; i++) {
-		pos = asn1.sub[1].sub[0].sub[1].sub[i].stream.pos;
-		str = wit.substring(2 * pos + 4, 2 * pos + 68);
-		this.path.digestList.push(str);  // digest hex string
-		//console.log(str);
-	}
-	*/
-	
-	// FIXME: Need to be fixed to support arbitrary ASN1 encoding,
-	// But do we really nned that????  -------Wentao
-	
-	// The structure of Witness is fixed as follows:
-	// SEQUENCE  (2 elem)
-	//   SEQUENCE  (1 elem)
-	//     OBJECT IDENTIFIER  1.2.840.113550.11.1.2.2
-	//   OCTET STRING  (1 elem)
-	//     SEQUENCE  (2 elem)
-	//       INTEGER  index
-	//       SEQUENCE  (n elem)
-	//         OCTET STRING(32 byte) 345FB4B5E9A1D2FF450ECA87EB87601683027A1A...
-	//         OCTET STRING(32 byte) DBCEE5B7A6C2B851B029324197DDBD9A655723DC...
-	//         OCTET STRING(32 byte) 4C79B2D256E4CD657A27F01DCB51AC3C56A24E71...
-	//         OCTET STRING(32 byte) 7F7FB169604A87EAC94378F0BDB4FC5D5899AB88...
-	//         ......
-	// Hence we can follow this structure to extract witness fields at fixed level
-	// Tag numbers for ASN1:
-	//    SEQUENCE            0x10
-	//    OCT STRING          0x04
-	//    INTEGER             0x02
-	//    OBJECT IDENTIFIER   0x06
-	var i = 0;
-	var step = 0;  // count of sequence tag
-	while (i < witness.length) {
-		var len = 0;
-		
-		if (witness[i] == 0x30) {
-			// Sequence (constructed)
-			// There is no primitive sequence in Witness
-			if ((witness[i + 1] & 0x80) != 0) {
-				len = witness[i+1] & 0x7F;
-			}
-			step++;
-		} else if (witness[i] == 0x06) {
-			// Decode OID
-			len = witness[i+1];  // XXX: OID will not be longer than 127 bytes
-			this.oid = parseOID(witness, i + 2, i + 2 + len);
-			//console.log(this.oid);
-		} else if (witness[i] == 0x02) {
-			// Decode node index
-			len = witness[i+1];  // XXX: index will not be longer than 127 bytes
-			this.path.index = parseInteger(witness, i + 2, i + 2 + len);
-			//console.log(this.path.index);
-		} else if (witness[i] == 0x04) {
-			if ((witness[i + 1] & 0x80) != 0) {
-				len = witness[i+1] & 0x7F;
-			}
-			if (step == 4) {
-				// Start to decode digest hex string
-				len = witness[i+1];  // XXX: digest hex should always be 32 bytes
-				var str = DataUtils.toHex(witness.subarray(i + 2, i + 2 + len));
-				this.path.digestList.push(str);  // digest hex string
-				//console.log(str);
-			}
-		}
-		i = i + 2 + len;
-	}
-};
-/*
- * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
- * in FIPS 180-2
- * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
- * Distributed under the BSD License
- * See http://pajhome.org.uk/crypt/md5 for details.
- * Also http://anmar.eu.org/projects/jssha2/
- */
-
-/*
- * Configurable variables. You may need to tweak these to be compatible with
- * the server-side, but the defaults work in most cases.
- */
-var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
-var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
-
-/*
- * These are the functions you'll usually want to call
- * They take string arguments and return either hex or base-64 encoded strings
- */
-
-//@author axelcdv
-/**
- * Computes the Sha-256 hash of the given byte array
- * @param {byte[]} 
- * @return the hex string corresponding to the Sha-256 hash of the byte array
- */
-function hex_sha256_from_bytes(byteArray){
-	return rstr2hex(binb2rstr(binb_sha256( byteArray2binb(byteArray), byteArray.length * 8)));
-}
-
-function hex_sha256(s)    { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); }
-function b64_sha256(s)    { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); }
-function any_sha256(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); }
-function hex_hmac_sha256(k, d)
-  { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
-function b64_hmac_sha256(k, d)
-  { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
-function any_hmac_sha256(k, d, e)
-  { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
-
-	
-/*
-	function hex_sha256(s)    { return rstr2hex(rstr_sha256(s)); }
-function b64_sha256(s)    { return rstr2b64(rstr_sha256(s)); }
-function any_sha256(s, e) { return rstr2any(rstr_sha256(s), e); }
-function hex_hmac_sha256(k, d)
-  { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), d)); }
-function b64_hmac_sha256(k, d)
-  { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), d)); }
-function any_hmac_sha256(k, d, e)
-  { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), d), e); }
-*/
-	
-/*
- * Perform a simple self-test to see if the VM is working
- */
-function sha256_vm_test()
-{
-  return hex_sha256("abc").toLowerCase() ==
-            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
-}
-
-/**
- * Calculate the sha256 of a raw string
- * @param s: the raw string
- */
-function rstr_sha256(s)
-{
-  return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8));
-}
-
-/**
- * Calculate the HMAC-sha256 of a key and some data (raw strings)
- */
-function rstr_hmac_sha256(key, data)
-{
-  var bkey = rstr2binb(key);
-  if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8);
-
-  var ipad = Array(16), opad = Array(16);
-  for(var i = 0; i < 16; i++)
-  {
-    ipad[i] = bkey[i] ^ 0x36363636;
-    opad[i] = bkey[i] ^ 0x5C5C5C5C;
-  }
-
-  var hash = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
-  return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256));
-}
-
-/**
- * Convert a raw string to a hex string
- */
-function rstr2hex(input)
-{
-  try { hexcase } catch(e) { hexcase=0; }
-  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
-  var output = "";
-  var x;
-  for(var i = 0; i < input.length; i++)
-  {
-    x = input.charCodeAt(i);
-    output += hex_tab.charAt((x >>> 4) & 0x0F)
-           +  hex_tab.charAt( x        & 0x0F);
-  }
-  return output;
-}
-
-/*
- * Convert a raw string to a base-64 string
- */
-function rstr2b64(input)
-{
-  try { b64pad } catch(e) { b64pad=''; }
-  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-  var output = "";
-  var len = input.length;
-  for(var i = 0; i < len; i += 3)
-  {
-    var triplet = (input.charCodeAt(i) << 16)
-                | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
-                | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
-    for(var j = 0; j < 4; j++)
-    {
-      if(i * 8 + j * 6 > input.length * 8) output += b64pad;
-      else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
-    }
-  }
-  return output;
-}
-
-/*
- * Convert a raw string to an arbitrary string encoding
- */
-function rstr2any(input, encoding)
-{
-  var divisor = encoding.length;
-  var remainders = Array();
-  var i, q, x, quotient;
-
-  /* Convert to an array of 16-bit big-endian values, forming the dividend */
-  var dividend = Array(Math.ceil(input.length / 2));
-  for(i = 0; i < dividend.length; i++)
-  {
-    dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
-  }
-
-  /*
-   * Repeatedly perform a long division. The binary array forms the dividend,
-   * the length of the encoding is the divisor. Once computed, the quotient
-   * forms the dividend for the next step. We stop when the dividend is zero.
-   * All remainders are stored for later use.
-   */
-  while(dividend.length > 0)
-  {
-    quotient = Array();
-    x = 0;
-    for(i = 0; i < dividend.length; i++)
-    {
-      x = (x << 16) + dividend[i];
-      q = Math.floor(x / divisor);
-      x -= q * divisor;
-      if(quotient.length > 0 || q > 0)
-        quotient[quotient.length] = q;
-    }
-    remainders[remainders.length] = x;
-    dividend = quotient;
-  }
-
-  /* Convert the remainders to the output string */
-  var output = "";
-  for(i = remainders.length - 1; i >= 0; i--)
-    output += encoding.charAt(remainders[i]);
-
-  /* Append leading zero equivalents */
-  var full_length = Math.ceil(input.length * 8 /
-                                    (Math.log(encoding.length) / Math.log(2)))
-  for(i = output.length; i < full_length; i++)
-    output = encoding[0] + output;
-
-  return output;
-}
-
-/*
- * Encode a string as utf-8.
- * For efficiency, this assumes the input is valid utf-16.
- */
-function str2rstr_utf8(input)
-{
-  var output = "";
-  var i = -1;
-  var x, y;
-
-  while(++i < input.length)
-  {
-    /* Decode utf-16 surrogate pairs */
-    x = input.charCodeAt(i);
-    y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
-    if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
-    {
-      x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
-      i++;
-    }
-
-    /* Encode output as utf-8 */
-    if(x <= 0x7F)
-      output += String.fromCharCode(x);
-    else if(x <= 0x7FF)
-      output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
-                                    0x80 | ( x         & 0x3F));
-    else if(x <= 0xFFFF)
-      output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
-                                    0x80 | ((x >>> 6 ) & 0x3F),
-                                    0x80 | ( x         & 0x3F));
-    else if(x <= 0x1FFFFF)
-      output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
-                                    0x80 | ((x >>> 12) & 0x3F),
-                                    0x80 | ((x >>> 6 ) & 0x3F),
-                                    0x80 | ( x         & 0x3F));
-  }
-  return output;
-}
-
-/*
- * Encode a string as utf-16
- */
-function str2rstr_utf16le(input)
-{
-  var output = "";
-  for(var i = 0; i < input.length; i++)
-    output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
-                                  (input.charCodeAt(i) >>> 8) & 0xFF);
-  return output;
-}
-
-function str2rstr_utf16be(input)
-{
-  var output = "";
-  for(var i = 0; i < input.length; i++)
-    output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
-                                   input.charCodeAt(i)        & 0xFF);
-  return output;
-}
-
-/**
- * Convert a raw string to an array of big-endian words
- * Characters >255 have their high-byte silently ignored.
- */
-function rstr2binb(input)
-{
-  //console.log('Raw string comming is '+input);
-  var output = Array(input.length >> 2);
-  /* JavaScript automatically zeroizes a new array.
-  for(var i = 0; i < output.length; i++)
-    output[i] = 0;
-   */
-  for(var i = 0; i < input.length * 8; i += 8)
-    output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
-  return output;
-}
-
-/**
- * @author axelcdv
- * Convert a byte array to an array of big-endian words
- * @param {byte[]} input
- * @return the array of big-endian words
- */
-function byteArray2binb(input){
-	//console.log("Byte array coming is " + input);
-	var output = Array(input.length >> 2);
-      /* JavaScript automatically zeroizes a new array.
-	  for(var i = 0; i < output.length; i++)
-	    output[i] = 0;
-       */
-	  for(var i = 0; i < input.length * 8; i += 8)
-	    output[i>>5] |= (input[i / 8] & 0xFF) << (24 - i % 32);
-	  return output;
-}
-
-/*
- * Convert an array of big-endian words to a string
- */
-function binb2rstr(input)
-{
-  var output = "";
-  for(var i = 0; i < input.length * 32; i += 8)
-    output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
-  return output;
-}
-
-/*
- * Main sha256 function, with its support functions
- */
-function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
-function sha256_R (X, n) {return ( X >>> n );}
-function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
-function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
-function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
-function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
-function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
-function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
-function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
-function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
-function sha256_Gamma0512(x) {return (sha256_S(x, 1)  ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
-function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
-
-var sha256_K = new Array
-(
-  1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,
-  -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
-  1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
-  264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,
-  -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
-  113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
-  1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,
-  -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
-  430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
-  1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,
-  -1866530822, -1538233109, -1090935817, -965641998
-);
-
-function binb_sha256(m, l)
-{
-  var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534,
-                       1359893119, -1694144372, 528734635, 1541459225);
-  var W = new Array(64);
-
-  /* append padding */
-  m[l >> 5] |= 0x80 << (24 - l % 32);
-  m[((l + 64 >> 9) << 4) + 15] = l;
- 
-  for(var offset = 0; offset < m.length; offset += 16)
-    processBlock_sha256(m, offset, HASH, W);
-
-  return HASH;
-}
-
-/*
- * Process a block of 16 4-byte words in m starting at offset and update HASH.  
- * offset must be a multiple of 16 and less than m.length.  W is a scratchpad Array(64).
- */
-function processBlock_sha256(m, offset, HASH, W) {
-    var a, b, c, d, e, f, g, h;
-    var j, T1, T2;
-    
-    a = HASH[0];
-    b = HASH[1];
-    c = HASH[2];
-    d = HASH[3];
-    e = HASH[4];
-    f = HASH[5];
-    g = HASH[6];
-    h = HASH[7];
-
-    for(j = 0; j < 64; j++)
-    {
-      if (j < 16) W[j] = m[j + offset];
-      else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
-                                            sha256_Gamma0256(W[j - 15])), W[j - 16]);
-
-      T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
-                                                          sha256_K[j]), W[j]);
-      T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
-      h = g;
-      g = f;
-      f = e;
-      e = safe_add(d, T1);
-      d = c;
-      c = b;
-      b = a;
-      a = safe_add(T1, T2);
-    }
-
-    HASH[0] = safe_add(a, HASH[0]);
-    HASH[1] = safe_add(b, HASH[1]);
-    HASH[2] = safe_add(c, HASH[2]);
-    HASH[3] = safe_add(d, HASH[3]);
-    HASH[4] = safe_add(e, HASH[4]);
-    HASH[5] = safe_add(f, HASH[5]);
-    HASH[6] = safe_add(g, HASH[6]);
-    HASH[7] = safe_add(h, HASH[7]);
-}
-
-function safe_add (x, y)
-{
-  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
-  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
-  return (msw << 16) | (lsw & 0xFFFF);
-}
-
-/*
- * Create a Sha256, call update(data) multiple times, then call finalize().
- */
-var Sha256 = function Sha256() {
-    this.W = new Array(64);
-    this.hash = new Array(1779033703, -1150833019, 1013904242, -1521486534,
-                          1359893119, -1694144372, 528734635, 1541459225);
-    this.nTotalBytes = 0;
-    this.buffer = new Uint8Array(16 * 4);
-    this.nBufferBytes = 0;
-}
-
-/*
- * Update the hash with data, which is Uint8Array.
- */
-Sha256.prototype.update = function(data) {
-    this.nTotalBytes += data.length;
-    
-    if (this.nBufferBytes > 0) {
-        // Fill up the buffer and process it first.
-        var bytesNeeded = this.buffer.length - this.nBufferBytes;
-        if (data.length < bytesNeeded) {
-            this.buffer.set(data, this.nBufferBytes);
-            this.nBufferBytes += data.length;
-            return;
-        }
-        else {
-            this.buffer.set(data.subarray(0, bytesNeeded), this.nBufferBytes);
-            processBlock_sha256(byteArray2binb(this.buffer), 0, this.hash, this.W);
-            this.nBufferBytes = 0;
-            // Consume the bytes from data.
-            data = data.subarray(bytesNeeded, data.length);
-            if (data.length == 0)
-                return;
-        }
-    }
-    
-    // 2^6 is 16 * 4.
-    var nBlocks = data.length >> 6;
-    if (nBlocks > 0) {
-        var nBytes = nBlocks * 16 * 4;
-        var m = byteArray2binb(data.subarray(0, nBytes));
-        for(var offset = 0; offset < m.length; offset += 16)
-            processBlock_sha256(m, offset, this.hash, this.W);
-
-        data = data.subarray(nBytes, data.length);
-    }
-    
-    if (data.length > 0) {
-        // Save the remainder in the buffer.
-        this.buffer.set(data);
-        this.nBufferBytes = data.length;
-    }
-}
-
-/*
- * Finalize the hash and return the result as Uint8Array.
- * Only call this once.  Return values on subsequent calls are undefined.
- */
-Sha256.prototype.finalize = function() {
-    var m = byteArray2binb(this.buffer.subarray(0, this.nBufferBytes));
-    /* append padding */
-    var l = this.nBufferBytes * 8;
-    m[l >> 5] |= 0x80 << (24 - l % 32);
-    m[((l + 64 >> 9) << 4) + 15] = this.nTotalBytes * 8;
-
-    for(var offset = 0; offset < m.length; offset += 16)
-        processBlock_sha256(m, offset, this.hash, this.W);
-
-    return Sha256.binb2Uint8Array(this.hash);
-}
-
-/*
- * Convert an array of big-endian words to Uint8Array.
- */
-Sha256.binb2Uint8Array = function(input)
-{
-    var output = new Uint8Array(input.length * 4);
-    var iOutput = 0;
-    for (var i = 0; i < input.length * 32; i += 8)
-        output[iOutput++] = (input[i>>5] >>> (24 - i % 32)) & 0xFF;
-    return output;
-}
 var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 var b64pad="=";
 
@@ -5031,7 +1693,7 @@
     c = parseInt(h.substring(i,i+2),16);
     ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
   }
-  while((ret.length & 3) > 0) ret += b64pad;
+  if (b64pad) while((ret.length & 3) > 0) ret += b64pad;
   return ret;
 }
 
@@ -5041,9 +1703,10 @@
   var i;
   var k = 0; // b64 state, 0-3
   var slop;
+  var v;
   for(i = 0; i < s.length; ++i) {
     if(s.charAt(i) == b64pad) break;
-    var v = b64map.indexOf(s.charAt(i));
+    v = b64map.indexOf(s.charAt(i));
     if(v < 0) continue;
     if(k == 0) {
       ret += int2char(v >> 2);
@@ -5083,10 +1746,137 @@
   }
   return a;
 }
+
+exports.b64tohex = b64tohex;
+exports.b64toBA  = b64toBA;
+exports.hex2b64  = hex2b64;
+
+module.exports = exports;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// prng4.js - uses Arcfour as a PRNG
+
+function Arcfour() {
+  this.i = 0;
+  this.j = 0;
+  this.S = new Array();
+}
+
+// Initialize arcfour context from key, an array of ints, each from [0..255]
+function ARC4init(key) {
+  var i, j, t;
+  for(i = 0; i < 256; ++i)
+    this.S[i] = i;
+  j = 0;
+  for(i = 0; i < 256; ++i) {
+    j = (j + this.S[i] + key[i % key.length]) & 255;
+    t = this.S[i];
+    this.S[i] = this.S[j];
+    this.S[j] = t;
+  }
+  this.i = 0;
+  this.j = 0;
+}
+
+function ARC4next() {
+  var t;
+  this.i = (this.i + 1) & 255;
+  this.j = (this.j + this.S[this.i]) & 255;
+  t = this.S[this.i];
+  this.S[this.i] = this.S[this.j];
+  this.S[this.j] = t;
+  return this.S[(t + this.S[this.i]) & 255];
+}
+
+Arcfour.prototype.init = ARC4init;
+Arcfour.prototype.next = ARC4next;
+
+// Plug in your RNG constructor here
+function prng_newstate() {
+  return new Arcfour();
+}
+
+// Pool size must be a multiple of 4 and greater than 32.
+// An array of bytes the size of the pool will be passed to init()
+var rng_psize = 256;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// Random number generator - requires a PRNG backend, e.g. prng4.js
+
+// For best results, put code like
+// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
+// in your main HTML document.
+
+var rng_state;
+var rng_pool;
+var rng_pptr;
+
+// Mix in a 32-bit integer into the pool
+function rng_seed_int(x) {
+  rng_pool[rng_pptr++] ^= x & 255;
+  rng_pool[rng_pptr++] ^= (x >> 8) & 255;
+  rng_pool[rng_pptr++] ^= (x >> 16) & 255;
+  rng_pool[rng_pptr++] ^= (x >> 24) & 255;
+  if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
+}
+
+// Mix in the current time (w/milliseconds) into the pool
+function rng_seed_time() {
+  rng_seed_int(new Date().getTime());
+}
+
+// Initialize the pool with junk if needed.
+if(rng_pool == null) {
+  rng_pool = new Array();
+  rng_pptr = 0;
+  var t;
+  if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
+    // Extract entropy (256 bits) from NS4 RNG if available
+    var z = window.crypto.random(32);
+    for(t = 0; t < z.length; ++t)
+      rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
+  }  
+  while(rng_pptr < rng_psize) {  // extract some randomness from Math.random()
+    t = Math.floor(65536 * Math.random());
+    rng_pool[rng_pptr++] = t >>> 8;
+    rng_pool[rng_pptr++] = t & 255;
+  }
+  rng_pptr = 0;
+  rng_seed_time();
+  //rng_seed_int(window.screenX);
+  //rng_seed_int(window.screenY);
+}
+
+function rng_get_byte() {
+  if(rng_state == null) {
+    rng_seed_time();
+    rng_state = prng_newstate();
+    rng_state.init(rng_pool);
+    for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
+      rng_pool[rng_pptr] = 0;
+    rng_pptr = 0;
+    //rng_pool = null;
+  }
+  // TODO: allow reseeding after first request
+  return rng_state.next();
+}
+
+function rng_get_bytes(ba) {
+  var i;
+  for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
+}
+
+function SecureRandom() {}
+
+SecureRandom.prototype.nextBytes = rng_get_bytes;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
 // Depends on jsbn.js and rng.js
 
 // Version 1.1: support utf-8 encoding in pkcs1pad2
 
+var intShim = require("jsbn");
+
 // convert a (hex) string to a bignum object
 function parseBigInt(str,r) {
   return new BigInteger(str,r);
@@ -5109,11 +1899,7 @@
     return b.toString(16);
 }
 
-/**
- * PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
- * @param s: the string to encode
- * @param n: the size in byte
- */ 
+// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
 function pkcs1pad2(s,n) {
   if(n < s.length + 11) { // TODO: fix for utf-8
     alert("Message too long for RSA");
@@ -5149,10 +1935,65 @@
   return new BigInteger(ba);
 }
 
-/** 
- * "empty" RSA key constructor
- * @returns {RSAKey}
- */
+// PKCS#1 (OAEP) mask generation function
+function oaep_mgf1_arr(seed, len, hash)
+{
+    var mask = '', i = 0;
+
+    while (mask.length < len)
+    {
+        mask += hash(String.fromCharCode.apply(String, seed.concat([
+                (i & 0xff000000) >> 24,
+                (i & 0x00ff0000) >> 16,
+                (i & 0x0000ff00) >> 8,
+                i & 0x000000ff])));
+        i += 1;
+    }
+
+    return mask;
+}
+
+var SHA1_SIZE = 20;
+
+// PKCS#1 (OAEP) pad input string s to n bytes, and return a bigint
+function oaep_pad(s, n, hash)
+{
+    if (s.length + 2 * SHA1_SIZE + 2 > n)
+    {
+        throw "Message too long for RSA";
+    }
+
+    var PS = '', i;
+
+    for (i = 0; i < n - s.length - 2 * SHA1_SIZE - 2; i += 1)
+    {
+        PS += '\x00';
+    }
+
+    var DB = rstr_sha1('') + PS + '\x01' + s;
+    var seed = new Array(SHA1_SIZE);
+    new SecureRandom().nextBytes(seed);
+    
+    var dbMask = oaep_mgf1_arr(seed, DB.length, hash || rstr_sha1);
+    var maskedDB = [];
+
+    for (i = 0; i < DB.length; i += 1)
+    {
+        maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+    }
+
+    var seedMask = oaep_mgf1_arr(maskedDB, seed.length, rstr_sha1);
+    var maskedSeed = [0];
+
+    for (i = 0; i < seed.length; i += 1)
+    {
+        maskedSeed[i + 1] = seed[i] ^ seedMask.charCodeAt(i);
+    }
+
+    return new BigInteger(maskedSeed.concat(maskedDB));
+}
+
+// "empty" RSA key constructor
 function RSAKey() {
   this.n = null;
   this.e = 0;
@@ -5164,14 +2005,15 @@
   this.coeff = null;
 }
 
-/** 
- * Set the public key fields N and e from hex strings
- * @param N
- * @param E
- * @returns {RSASetPublic}
- */
+// Set the public key fields N and e from hex strings
 function RSASetPublic(N,E) {
-  if(N != null && E != null && N.length > 0 && E.length > 0) {
+  this.isPublic = true;
+  if (typeof N !== "string") 
+  {
+    this.n = N;
+    this.e = E;
+  }
+  else if(N != null && E != null && N.length > 0 && E.length > 0) {
     this.n = parseBigInt(N,16);
     this.e = parseInt(E,16);
   }
@@ -5179,18 +2021,12 @@
     alert("Invalid RSA public key");
 }
 
-/** 
- * Perform raw public operation on "x": return x^e (mod n)
- * @param x
- * @returns x^e (mod n)
- */
+// Perform raw public operation on "x": return x^e (mod n)
 function RSADoPublic(x) {
   return x.modPowInt(this.e, this.n);
 }
 
-/**
- * Return the PKCS#1 RSA encryption of "text" as an even-length hex string
- */ 
+// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
 function RSAEncrypt(text) {
   var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
   if(m == null) return null;
@@ -5200,6 +2036,16 @@
   if((h.length & 1) == 0) return h; else return "0" + h;
 }
 
+// Return the PKCS#1 OAEP RSA encryption of "text" as an even-length hex string
+function RSAEncryptOAEP(text, hash) {
+  var m = oaep_pad(text, (this.n.bitLength()+7)>>3, hash);
+  if(m == null) return null;
+  var c = this.doPublic(m);
+  if(c == null) return null;
+  var h = c.toString(16);
+  if((h.length & 1) == 0) return h; else return "0" + h;
+}
+
 // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
 //function RSAEncryptB64(text) {
 //  var h = this.encrypt(text);
@@ -5212,11 +2058,23 @@
 // public
 RSAKey.prototype.setPublic = RSASetPublic;
 RSAKey.prototype.encrypt = RSAEncrypt;
+RSAKey.prototype.encryptOAEP = RSAEncryptOAEP;
 //RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
+
+RSAKey.prototype.type = "RSA";
+
+exports.RSAKey = RSAKey;
+module.exports = exports;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
 // Depends on rsa.js and jsbn2.js
 
 // Version 1.1: support utf-8 decoding in pkcs1unpad2
 
+var intShim = require("jsbn");
+var BigInteger = intShim.BigInteger ? intShim.BigInteger : intShim ;
+var RSAKey = require('./rsa.js').RSAKey;
+
 // Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
 function pkcs1unpad2(d,n) {
   var b = d.toByteArray();
@@ -5245,9 +2103,101 @@
   return ret;
 }
 
+// PKCS#1 (OAEP) mask generation function
+function oaep_mgf1_str(seed, len, hash)
+{
+    var mask = '', i = 0;
+
+    while (mask.length < len)
+    {
+        mask += hash(seed + String.fromCharCode.apply(String, [
+                (i & 0xff000000) >> 24,
+                (i & 0x00ff0000) >> 16,
+                (i & 0x0000ff00) >> 8,
+                i & 0x000000ff]));
+        i += 1;
+    }
+
+    return mask;
+}
+
+var SHA1_SIZE = 20;
+
+// Undo PKCS#1 (OAEP) padding and, if valid, return the plaintext
+function oaep_unpad(d, n, hash)
+{
+    d = d.toByteArray();
+
+    var i;
+
+    for (i = 0; i < d.length; i += 1)
+    {
+        d[i] &= 0xff;
+    }
+
+    while (d.length < n)
+    {
+        d.unshift(0);
+    }
+
+    d = String.fromCharCode.apply(String, d);
+
+    if (d.length < 2 * SHA1_SIZE + 2)
+    {
+        throw "Cipher too short";
+    }
+
+    var maskedSeed = d.substr(1, SHA1_SIZE)
+    var maskedDB = d.substr(SHA1_SIZE + 1);
+
+    var seedMask = oaep_mgf1_str(maskedDB, SHA1_SIZE, hash || rstr_sha1);
+    var seed = [], i;
+
+    for (i = 0; i < maskedSeed.length; i += 1)
+    {
+        seed[i] = maskedSeed.charCodeAt(i) ^ seedMask.charCodeAt(i);
+    }
+
+    var dbMask = oaep_mgf1_str(String.fromCharCode.apply(String, seed),
+                           d.length - SHA1_SIZE, rstr_sha1);
+
+    var DB = [];
+
+    for (i = 0; i < maskedDB.length; i += 1)
+    {
+        DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+    }
+
+    DB = String.fromCharCode.apply(String, DB);
+
+    if (DB.substr(0, SHA1_SIZE) !== rstr_sha1(''))
+    {
+        throw "Hash mismatch";
+    }
+
+    DB = DB.substr(SHA1_SIZE);
+
+    var first_one = DB.indexOf('\x01');
+    var last_zero = (first_one != -1) ? DB.substr(0, first_one).lastIndexOf('\x00') : -1;
+
+    if (last_zero + 1 != first_one)
+    {
+        throw "Malformed data";
+    }
+
+    return DB.substr(first_one + 1);
+}
+
 // Set the private key fields N, e, and d from hex strings
 function RSASetPrivate(N,E,D) {
-  if(N != null && E != null && N.length > 0 && E.length > 0) {
+  this.isPrivate = true;
+  if (typeof N !== "string")
+  {
+    this.n = N;
+    this.e = E;
+    this.d = D;
+  }
+  else if(N != null && E != null && N.length > 0 && E.length > 0) {
     this.n = parseBigInt(N,16);
     this.e = parseInt(E,16);
     this.d = parseBigInt(D,16);
@@ -5258,7 +2208,13 @@
 
 // Set the private key fields N, e, d and CRT params from hex strings
 function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
-  if(N != null && E != null && N.length > 0 && E.length > 0) {
+  this.isPrivate = true;
+  if (N == null) throw "RSASetPrivateEx N == null";
+  if (E == null) throw "RSASetPrivateEx E == null";
+  if (N.length == 0) throw "RSASetPrivateEx N.length == 0";
+  if (E.length == 0) throw "RSASetPrivateEx E.length == 0";
+
+  if (N != null && E != null && N.length > 0 && E.length > 0) {
     this.n = parseBigInt(N,16);
     this.e = parseInt(E,16);
     this.d = parseBigInt(D,16);
@@ -5267,14 +2223,12 @@
     this.dmp1 = parseBigInt(DP,16);
     this.dmq1 = parseBigInt(DQ,16);
     this.coeff = parseBigInt(C,16);
+  } else {
+    alert("Invalid RSA private key in RSASetPrivateEx");
   }
-  else
-    alert("Invalid RSA private key");
 }
 
-/**
- * Generate a new random private key B bits long, using public expt E
- */
+// Generate a new random private key B bits long, using public expt E
 function RSAGenerate(B,E) {
   var rng = new SecureRandom();
   var qs = B>>1;
@@ -5306,12 +2260,10 @@
       break;
     }
   }
+  this.isPrivate = true;
 }
 
-/**
- * Perform raw private operation on "x": return x^d (mod n)
- * @return x^d (mod n)
- */ 
+// Perform raw private operation on "x": return x^d (mod n)
 function RSADoPrivate(x) {
   if(this.p == null || this.q == null)
     return x.modPow(this.d, this.n);
@@ -5338,6 +2290,15 @@
   return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
 }
 
+// Return the PKCS#1 OAEP RSA decryption of "ctext".
+// "ctext" is an even-length hex string and the output is a plain string.
+function RSADecryptOAEP(ctext, hash) {
+  var c = parseBigInt(ctext, 16);
+  var m = this.doPrivate(c);
+  if(m == null) return null;
+  return oaep_unpad(m, (this.n.bitLength()+7)>>3, hash);
+}
+
 // Return the PKCS#1 RSA decryption of "ctext".
 // "ctext" is a Base64-encoded string and the output is a plain string.
 //function RSAB64Decrypt(ctext) {
@@ -5353,16 +2314,1256 @@
 RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
 RSAKey.prototype.generate = RSAGenerate;
 RSAKey.prototype.decrypt = RSADecrypt;
+RSAKey.prototype.decryptOAEP = RSADecryptOAEP;
 //RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
+
+exports.RSAKey = RSAKey;
+module.exports = exports;
+/*! crypto-1.1.7.js (c) 2013-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * crypto.js - Cryptographic Algorithm Provider class
+ *
+ * Copyright (c) 2013-2015 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license
+ *
+ * The above copyright and license notice shall be 
+ * included in all copies or substantial portions of the Software.
+ */
+
+/**
+ * @fileOverview
+ * @name crypto-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version 1.1.7 (2015-Oct-11)
+ * @since jsrsasign 2.2
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ */
+
+var CryptoJS = require('./sha256.js').CryptoJS
+  , intShim = require('jsbn');
+
+
+/** 
+ * kjur's class library name space
+ * @name KJUR
+ * @namespace kjur's class library name space
+ */
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+/**
+ * kjur's cryptographic algorithm provider library name space
+ * <p>
+ * This namespace privides following crytpgrahic classes.
+ * <ul>
+ * <li>{@link KJUR.crypto.MessageDigest} - Java JCE(cryptograhic extension) style MessageDigest class</li>
+ * <li>{@link KJUR.crypto.Signature} - Java JCE(cryptograhic extension) style Signature class</li>
+ * <li>{@link KJUR.crypto.Util} - cryptographic utility functions and properties</li>
+ * </ul>
+ * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
+ * </p>
+ * @name KJUR.crypto
+ * @namespace
+ */
+if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
+
+/**
+ * static object for cryptographic function utilities
+ * @name KJUR.crypto.Util
+ * @class static object for cryptographic function utilities
+ * @property {Array} DIGESTINFOHEAD PKCS#1 DigestInfo heading hexadecimal bytes for each hash algorithms
+ * @property {Array} DEFAULTPROVIDER associative array of default provider name for each hash and signature algorithms
+ * @description
+ */
+KJUR.crypto.Util = new function() {
+    this.DIGESTINFOHEAD = {
+	'sha1':      "3021300906052b0e03021a05000414",
+        'sha224':    "302d300d06096086480165030402040500041c",
+	'sha256':    "3031300d060960864801650304020105000420",
+	'sha384':    "3041300d060960864801650304020205000430",
+	'sha512':    "3051300d060960864801650304020305000440",
+	'md2':       "3020300c06082a864886f70d020205000410",
+	'md5':       "3020300c06082a864886f70d020505000410",
+	'ripemd160': "3021300906052b2403020105000414"
+    };
+
+    /*
+     * @since crypto 1.1.1
+     */
+    this.DEFAULTPROVIDER = {
+	'md5':			'cryptojs',
+	'sha1':			'cryptojs',
+	'sha224':		'cryptojs',
+	'sha256':		'cryptojs',
+	'sha384':		'cryptojs',
+	'sha512':		'cryptojs',
+	'ripemd160':		'cryptojs',
+	'hmacmd5':		'cryptojs',
+	'hmacsha1':		'cryptojs',
+	'hmacsha224':		'cryptojs',
+	'hmacsha256':		'cryptojs',
+	'hmacsha384':		'cryptojs',
+	'hmacsha512':		'cryptojs',
+	'hmacripemd160':	'cryptojs',
+
+	'MD5withRSA':		'cryptojs/jsrsa',
+	'SHA1withRSA':		'cryptojs/jsrsa',
+	'SHA224withRSA':	'cryptojs/jsrsa',
+	'SHA256withRSA':	'cryptojs/jsrsa',
+	'SHA384withRSA':	'cryptojs/jsrsa',
+	'SHA512withRSA':	'cryptojs/jsrsa',
+	'RIPEMD160withRSA':	'cryptojs/jsrsa',
+
+	'MD5withECDSA':		'cryptojs/jsrsa',
+	'SHA1withECDSA':	'cryptojs/jsrsa',
+	'SHA224withECDSA':	'cryptojs/jsrsa',
+	'SHA256withECDSA':	'cryptojs/jsrsa',
+	'SHA384withECDSA':	'cryptojs/jsrsa',
+	'SHA512withECDSA':	'cryptojs/jsrsa',
+	'RIPEMD160withECDSA':	'cryptojs/jsrsa',
+
+	'SHA1withDSA':		'cryptojs/jsrsa',
+	'SHA224withDSA':	'cryptojs/jsrsa',
+	'SHA256withDSA':	'cryptojs/jsrsa',
+
+	'MD5withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA1withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA224withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA256withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA384withRSAandMGF1':		'cryptojs/jsrsa',
+	'SHA512withRSAandMGF1':		'cryptojs/jsrsa',
+	'RIPEMD160withRSAandMGF1':	'cryptojs/jsrsa'
+    };
+
+    /*
+     * @since crypto 1.1.2
+     */
+    this.CRYPTOJSMESSAGEDIGESTNAME = {
+	'md5':		'CryptoJS.algo.MD5',
+	'sha1':		'CryptoJS.algo.SHA1',
+	'sha224':	'CryptoJS.algo.SHA224',
+	'sha256':	'CryptoJS.algo.SHA256',
+	'sha384':	'CryptoJS.algo.SHA384',
+	'sha512':	'CryptoJS.algo.SHA512',
+	'ripemd160':	'CryptoJS.algo.RIPEMD160'
+    };
+
+    /**
+     * get hexadecimal DigestInfo
+     * @name getDigestInfoHex
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} hHash hexadecimal hash value
+     * @param {String} alg hash algorithm name (ex. 'sha1')
+     * @return {String} hexadecimal string DigestInfo ASN.1 structure
+     */
+    this.getDigestInfoHex = function(hHash, alg) {
+	if (typeof this.DIGESTINFOHEAD[alg] == "undefined")
+	    throw "alg not supported in Util.DIGESTINFOHEAD: " + alg;
+	return this.DIGESTINFOHEAD[alg] + hHash;
+    };
+
+    /**
+     * get PKCS#1 padded hexadecimal DigestInfo
+     * @name getPaddedDigestInfoHex
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} hHash hexadecimal hash value of message to be signed
+     * @param {String} alg hash algorithm name (ex. 'sha1')
+     * @param {Integer} keySize key bit length (ex. 1024)
+     * @return {String} hexadecimal string of PKCS#1 padded DigestInfo
+     */
+    this.getPaddedDigestInfoHex = function(hHash, alg, keySize) {
+	var hDigestInfo = this.getDigestInfoHex(hHash, alg);
+	var pmStrLen = keySize / 4; // minimum PM length
+
+	if (hDigestInfo.length + 22 > pmStrLen) // len(0001+ff(*8)+00+hDigestInfo)=22
+	    throw "key is too short for SigAlg: keylen=" + keySize + "," + alg;
+
+	var hHead = "0001";
+	var hTail = "00" + hDigestInfo;
+	var hMid = "";
+	var fLen = pmStrLen - hHead.length - hTail.length;
+	for (var i = 0; i < fLen; i += 2) {
+	    hMid += "ff";
+	}
+	var hPaddedMessage = hHead + hMid + hTail;
+	return hPaddedMessage;
+    };
+
+    /**
+     * get hexadecimal hash of string with specified algorithm
+     * @name hashString
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @param {String} alg hash algorithm name
+     * @return {String} hexadecimal string of hash value
+     * @since 1.1.1
+     */
+    this.hashString = function(s, alg) {
+        var md = new KJUR.crypto.MessageDigest({'alg': alg});
+        return md.digestString(s);
+    };
+
+    /**
+     * get hexadecimal hash of hexadecimal string with specified algorithm
+     * @name hashHex
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} sHex input hexadecimal string to be hashed
+     * @param {String} alg hash algorithm name
+     * @return {String} hexadecimal string of hash value
+     * @since 1.1.1
+     */
+    this.hashHex = function(sHex, alg) {
+        var md = new KJUR.crypto.MessageDigest({'alg': alg});
+        return md.digestHex(sHex);
+    };
+
+    /**
+     * get hexadecimal SHA1 hash of string
+     * @name sha1
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.sha1 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha1', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    /**
+     * get hexadecimal SHA256 hash of string
+     * @name sha256
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.sha256 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    this.sha256Hex = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
+        return md.digestHex(s);
+    };
+
+    /**
+     * get hexadecimal SHA512 hash of string
+     * @name sha512
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.sha512 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    this.sha512Hex = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
+        return md.digestHex(s);
+    };
+
+    /**
+     * get hexadecimal MD5 hash of string
+     * @name md5
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.md5 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'md5', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    /**
+     * get hexadecimal RIPEMD160 hash of string
+     * @name ripemd160
+     * @memberOf KJUR.crypto.Util
+     * @function
+     * @param {String} s input string to be hashed
+     * @return {String} hexadecimal string of hash value
+     * @since 1.0.3
+     */
+    this.ripemd160 = function(s) {
+        var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'});
+        return md.digestString(s);
+    };
+
+    /*
+     * @since 1.1.2
+     */
+    this.getCryptoJSMDByName = function(s) {
+	
+    };
+};
+
+/**
+ * MessageDigest class which is very similar to java.security.MessageDigest class
+ * @name KJUR.crypto.MessageDigest
+ * @class MessageDigest class which is very similar to java.security.MessageDigest class
+ * @param {Array} params parameters for constructor
+ * @description
+ * <br/>
+ * Currently this supports following algorithm and providers combination:
+ * <ul>
+ * <li>md5 - cryptojs</li>
+ * <li>sha1 - cryptojs</li>
+ * <li>sha224 - cryptojs</li>
+ * <li>sha256 - cryptojs</li>
+ * <li>sha384 - cryptojs</li>
+ * <li>sha512 - cryptojs</li>
+ * <li>ripemd160 - cryptojs</li>
+ * <li>sha256 - sjcl (NEW from crypto.js 1.0.4)</li>
+ * </ul>
+ * @example
+ * // CryptoJS provider sample
+ * var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"});
+ * md.updateString('aaa')
+ * var mdHex = md.digest()
+ *
+ * // SJCL(Stanford JavaScript Crypto Library) provider sample
+ * var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only
+ * md.updateString('aaa')
+ * var mdHex = md.digest()
+ */
+KJUR.crypto.MessageDigest = function(params) {
+    var md = null;
+    var algName = null;
+    var provName = null;
+
+    /**
+     * set hash algorithm and provider
+     * @name setAlgAndProvider
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} alg hash algorithm name
+     * @param {String} prov provider name
+     * @description
+     * @example
+     * // for SHA1
+     * md.setAlgAndProvider('sha1', 'cryptojs');
+     * // for RIPEMD160
+     * md.setAlgAndProvider('ripemd160', 'cryptojs');
+     */
+    this.setAlgAndProvider = function(alg, prov) {
+	if (alg != null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
+
+	// for cryptojs
+	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(alg) != -1 &&
+	    prov == 'cryptojs') {
+	    try {
+		this.md = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[alg]).create();
+	    } catch (ex) {
+		throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
+	    }
+	    this.updateString = function(str) {
+		this.md.update(str);
+	    };
+	    this.updateHex = function(hex) {
+		var wHex = CryptoJS.enc.Hex.parse(hex);
+		this.md.update(wHex);
+	    };
+	    this.digest = function() {
+		var hash = this.md.finalize();
+		return hash.toString(CryptoJS.enc.Hex);
+	    };
+	    this.digestString = function(str) {
+		this.updateString(str);
+		return this.digest();
+	    };
+	    this.digestHex = function(hex) {
+		this.updateHex(hex);
+		return this.digest();
+	    };
+	}
+	if (':sha256:'.indexOf(alg) != -1 &&
+	    prov == 'sjcl') {
+	    try {
+		this.md = new sjcl.hash.sha256();
+	    } catch (ex) {
+		throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
+	    }
+	    this.updateString = function(str) {
+		this.md.update(str);
+	    };
+	    this.updateHex = function(hex) {
+		var baHex = sjcl.codec.hex.toBits(hex);
+		this.md.update(baHex);
+	    };
+	    this.digest = function() {
+		var hash = this.md.finalize();
+		return sjcl.codec.hex.fromBits(hash);
+	    };
+	    this.digestString = function(str) {
+		this.updateString(str);
+		return this.digest();
+	    };
+	    this.digestHex = function(hex) {
+		this.updateHex(hex);
+		return this.digest();
+	    };
+	}
+    };
+
+    /**
+     * update digest by specified string
+     * @name updateString
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} str string to update
+     * @description
+     * @example
+     * md.updateString('New York');
+     */
+    this.updateString = function(str) {
+	throw "updateString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    /**
+     * update digest by specified hexadecimal string
+     * @name updateHex
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} hex hexadecimal string to update
+     * @description
+     * @example
+     * md.updateHex('0afe36');
+     */
+    this.updateHex = function(hex) {
+	throw "updateHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    /**
+     * completes hash calculation and returns hash result
+     * @name digest
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @description
+     * @example
+     * md.digest()
+     */
+    this.digest = function() {
+	throw "digest() not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    /**
+     * performs final update on the digest using string, then completes the digest computation
+     * @name digestString
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} str string to final update
+     * @description
+     * @example
+     * md.digestString('aaa')
+     */
+    this.digestString = function(str) {
+	throw "digestString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    /**
+     * performs final update on the digest using hexadecimal string, then completes the digest computation
+     * @name digestHex
+     * @memberOf KJUR.crypto.MessageDigest
+     * @function
+     * @param {String} hex hexadecimal string to final update
+     * @description
+     * @example
+     * md.digestHex('0f2abd')
+     */
+    this.digestHex = function(hex) {
+	throw "digestHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+    };
+
+    if (params !== undefined) {
+	if (params['alg'] !== undefined) {
+	    this.algName = params['alg'];
+	    if (params['prov'] === undefined)
+		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+	    this.setAlgAndProvider(this.algName, this.provName);
+	}
+    }
+};
+
+/**
+ * Mac(Message Authentication Code) class which is very similar to java.security.Mac class 
+ * @name KJUR.crypto.Mac
+ * @class Mac class which is very similar to java.security.Mac class
+ * @param {Array} params parameters for constructor
+ * @description
+ * <br/>
+ * Currently this supports following algorithm and providers combination:
+ * <ul>
+ * <li>hmacmd5 - cryptojs</li>
+ * <li>hmacsha1 - cryptojs</li>
+ * <li>hmacsha224 - cryptojs</li>
+ * <li>hmacsha256 - cryptojs</li>
+ * <li>hmacsha384 - cryptojs</li>
+ * <li>hmacsha512 - cryptojs</li>
+ * </ul>
+ * NOTE: HmacSHA224 and HmacSHA384 issue was fixed since jsrsasign 4.1.4.
+ * Please use 'ext/cryptojs-312-core-fix*.js' instead of 'core.js' of original CryptoJS
+ * to avoid those issue.
+ * <br/>
+ * NOTE2: Hmac signature bug was fixed in jsrsasign 4.9.0 by providing CryptoJS
+ * bug workaround.
+ * <br/>
+ * Please see {@link KJUR.crypto.Mac.setPassword}, how to provide password
+ * in various ways in detail.
+ * @example
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", "pass": "pass"});
+ * mac.updateString('aaa')
+ * var macHex = md.doFinal()
+ *
+ * // other password representation 
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"hex":  "6161"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"utf8": "aa"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"rstr": "\x61\x61"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64":  "Mi02/+...a=="}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64u": "Mi02_-...a"}});
+ */
+KJUR.crypto.Mac = function(params) {
+    var mac = null;
+    var pass = null;
+    var algName = null;
+    var provName = null;
+    var algProv = null;
+
+    this.setAlgAndProvider = function(alg, prov) {
+	alg = alg.toLowerCase();
+
+	if (alg == null) alg = "hmacsha1";
+
+	alg = alg.toLowerCase();
+        if (alg.substr(0, 4) != "hmac") {
+	    throw "setAlgAndProvider unsupported HMAC alg: " + alg;
+	}
+
+	if (prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
+	this.algProv = alg + "/" + prov;
+
+	var hashAlg = alg.substr(4);
+
+	// for cryptojs
+	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(hashAlg) != -1 &&
+	    prov == 'cryptojs') {
+	    try {
+		var mdObj = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[hashAlg]);
+		this.mac = CryptoJS.algo.HMAC.create(mdObj, this.pass);
+	    } catch (ex) {
+		throw "setAlgAndProvider hash alg set fail hashAlg=" + hashAlg + "/" + ex;
+	    }
+	    this.updateString = function(str) {
+		this.mac.update(str);
+	    };
+	    this.updateHex = function(hex) {
+		var wHex = CryptoJS.enc.Hex.parse(hex);
+		this.mac.update(wHex);
+	    };
+	    this.doFinal = function() {
+		var hash = this.mac.finalize();
+		return hash.toString(CryptoJS.enc.Hex);
+	    };
+	    this.doFinalString = function(str) {
+		this.updateString(str);
+		return this.doFinal();
+	    };
+	    this.doFinalHex = function(hex) {
+		this.updateHex(hex);
+		return this.doFinal();
+	    };
+	}
+    };
+
+    /**
+     * update digest by specified string
+     * @name updateString
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {String} str string to update
+     * @description
+     * @example
+     * md.updateString('New York');
+     */
+    this.updateString = function(str) {
+	throw "updateString(str) not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * update digest by specified hexadecimal string
+     * @name updateHex
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {String} hex hexadecimal string to update
+     * @description
+     * @example
+     * md.updateHex('0afe36');
+     */
+    this.updateHex = function(hex) {
+	throw "updateHex(hex) not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * completes hash calculation and returns hash result
+     * @name doFinal
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @description
+     * @example
+     * md.digest()
+     */
+    this.doFinal = function() {
+	throw "digest() not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * performs final update on the digest using string, then completes the digest computation
+     * @name doFinalString
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {String} str string to final update
+     * @description
+     * @example
+     * md.digestString('aaa')
+     */
+    this.doFinalString = function(str) {
+	throw "digestString(str) not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * performs final update on the digest using hexadecimal string, 
+     * then completes the digest computation
+     * @name doFinalHex
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {String} hex hexadecimal string to final update
+     * @description
+     * @example
+     * md.digestHex('0f2abd')
+     */
+    this.doFinalHex = function(hex) {
+	throw "digestHex(hex) not supported for this alg/prov: " + this.algProv;
+    };
+
+    /**
+     * set password for Mac
+     * @name setPassword
+     * @memberOf KJUR.crypto.Mac
+     * @function
+     * @param {Object} pass password for Mac
+     * @since crypto 1.1.7 jsrsasign 4.9.0
+     * @description
+     * This method will set password for (H)Mac internally.
+     * Argument 'pass' can be specified as following:
+     * <ul>
+     * <li>even length string of 0..9, a..f or A-F: implicitly specified as hexadecimal string</li>
+     * <li>not above string: implicitly specified as raw string</li>
+     * <li>{rstr: "\x65\x70"}: explicitly specified as raw string</li>
+     * <li>{hex: "6570"}: explicitly specified as hexacedimal string</li>
+     * <li>{utf8: "秘密"}: explicitly specified as UTF8 string</li>
+     * <li>{b64: "Mi78..=="}: explicitly specified as Base64 string</li>
+     * <li>{b64u: "Mi7-_"}: explicitly specified as Base64URL string</li>
+     * </ul>
+     * It is *STRONGLY RECOMMENDED* that explicit representation of password argument
+     * to avoid ambiguity. For example string  "6161" can mean a string "6161" or 
+     * a hexadecimal string of "aa" (i.e. \x61\x61).
+     * @example
+     * mac = KJUR.crypto.Mac({'alg': 'hmacsha256'});
+     * // set password by implicit raw string
+     * mac.setPassword("\x65\x70\xb9\x0b");
+     * mac.setPassword("password");
+     * // set password by implicit hexadecimal string
+     * mac.setPassword("6570b90b");
+     * mac.setPassword("6570B90B");
+     * // set password by explicit raw string
+     * mac.setPassword({"rstr": "\x65\x70\xb9\x0b"});
+     * // set password by explicit hexadecimal string
+     * mac.setPassword({"hex": "6570b90b"});
+     * // set password by explicit utf8 string
+     * mac.setPassword({"utf8": "passwordパスワード");
+     * // set password by explicit Base64 string
+     * mac.setPassword({"b64": "Mb+c3f/=="});
+     * // set password by explicit Base64URL string
+     * mac.setPassword({"b64u": "Mb-c3f_"});
+     */
+    this.setPassword = function(pass) {
+	// internal this.pass shall be CryptoJS DWord Object for CryptoJS bug
+	// work around. CrytoJS HMac password can be passed by
+	// raw string as described in the manual however it doesn't
+	// work properly in some case. If password was passed
+	// by CryptoJS DWord which is not described in the manual
+	// it seems to work. (fixed since crypto 1.1.7)
+
+	if (typeof pass == 'string') {
+	    var hPass = pass;
+	    if (pass.length % 2 == 1 || ! pass.match(/^[0-9A-Fa-f]+$/)) { // raw str
+		hPass = rstrtohex(pass);
+	    }
+	    this.pass = CryptoJS.enc.Hex.parse(hPass);
+	    return;
+	}
+
+	if (typeof pass != 'object')
+	    throw "KJUR.crypto.Mac unsupported password type: " + pass;
+	
+	var hPass = null;
+	if (pass.hex  !== undefined) {
+	    if (pass.hex.length % 2 != 0 || ! pass.hex.match(/^[0-9A-Fa-f]+$/))
+		throw "Mac: wrong hex password: " + pass.hex;
+	    hPass = pass.hex;
+	}
+	if (pass.utf8 !== undefined) hPass = utf8tohex(pass.utf8);
+	if (pass.rstr !== undefined) hPass = rstrtohex(pass.rstr);
+	if (pass.b64  !== undefined) hPass = b64tohex(pass.b64);
+	if (pass.b64u !== undefined) hPass = b64utohex(pass.b64u);
+
+	if (hPass == null)
+	    throw "KJUR.crypto.Mac unsupported password type: " + pass;
+
+	this.pass = CryptoJS.enc.Hex.parse(hPass);
+    };
+
+    if (params !== undefined) {
+	if (params.pass !== undefined) {
+	    this.setPassword(params.pass);
+	}
+	if (params.alg !== undefined) {
+	    this.algName = params.alg;
+	    if (params['prov'] === undefined)
+		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+	    this.setAlgAndProvider(this.algName, this.provName);
+	}
+    }
+};
+
+/**
+ * Signature class which is very similar to java.security.Signature class
+ * @name KJUR.crypto.Signature
+ * @class Signature class which is very similar to java.security.Signature class
+ * @param {Array} params parameters for constructor
+ * @property {String} state Current state of this signature object whether 'SIGN', 'VERIFY' or null
+ * @description
+ * <br/>
+ * As for params of constructor's argument, it can be specify following attributes:
+ * <ul>
+ * <li>alg - signature algorithm name (ex. {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}with{RSA,ECDSA,DSA})</li>
+ * <li>provider - currently 'cryptojs/jsrsa' only</li>
+ * </ul>
+ * <h4>SUPPORTED ALGORITHMS AND PROVIDERS</h4>
+ * This Signature class supports following signature algorithm and provider names:
+ * <ul>
+ * <li>MD5withRSA - cryptojs/jsrsa</li>
+ * <li>SHA1withRSA - cryptojs/jsrsa</li>
+ * <li>SHA224withRSA - cryptojs/jsrsa</li>
+ * <li>SHA256withRSA - cryptojs/jsrsa</li>
+ * <li>SHA384withRSA - cryptojs/jsrsa</li>
+ * <li>SHA512withRSA - cryptojs/jsrsa</li>
+ * <li>RIPEMD160withRSA - cryptojs/jsrsa</li>
+ * <li>MD5withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA1withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA224withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA256withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA384withECDSA - cryptojs/jsrsa</li>
+ * <li>SHA512withECDSA - cryptojs/jsrsa</li>
+ * <li>RIPEMD160withECDSA - cryptojs/jsrsa</li>
+ * <li>MD5withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA1withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA224withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA256withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA384withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA512withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>RIPEMD160withRSAandMGF1 - cryptojs/jsrsa</li>
+ * <li>SHA1withDSA - cryptojs/jsrsa</li>
+ * <li>SHA224withDSA - cryptojs/jsrsa</li>
+ * <li>SHA256withDSA - cryptojs/jsrsa</li>
+ * </ul>
+ * Here are supported elliptic cryptographic curve names and their aliases for ECDSA:
+ * <ul>
+ * <li>secp256k1</li>
+ * <li>secp256r1, NIST P-256, P-256, prime256v1</li>
+ * <li>secp384r1, NIST P-384, P-384</li>
+ * </ul>
+ * NOTE1: DSA signing algorithm is also supported since crypto 1.1.5.
+ * <h4>EXAMPLES</h4>
+ * @example
+ * // RSA signature generation
+ * var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
+ * sig.init(prvKeyPEM);
+ * sig.updateString('aaa');
+ * var hSigVal = sig.sign();
+ *
+ * // DSA signature validation
+ * var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withDSA"});
+ * sig2.init(certPEM);
+ * sig.updateString('aaa');
+ * var isValid = sig2.verify(hSigVal);
+ * 
+ * // ECDSA signing
+ * var sig = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
+ * sig.init(prvKeyPEM);
+ * sig.updateString('aaa');
+ * var sigValueHex = sig.sign();
+ *
+ * // ECDSA verifying
+ * var sig2 = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
+ * sig.init(certPEM);
+ * sig.updateString('aaa');
+ * var isValid = sig.verify(sigValueHex);
+ */
+KJUR.crypto.Signature = function(params) {
+    var prvKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for signing
+    var pubKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for verifying
+
+    var md = null; // KJUR.crypto.MessageDigest object
+    var sig = null;
+    var algName = null;
+    var provName = null;
+    var algProvName = null;
+    var mdAlgName = null;
+    var pubkeyAlgName = null;	// rsa,ecdsa,rsaandmgf1(=rsapss)
+    var state = null;
+    var pssSaltLen = -1;
+    var initParams = null;
+
+    var sHashHex = null; // hex hash value for hex
+    var hDigestInfo = null;
+    var hPaddedDigestInfo = null;
+    var hSign = null;
+
+    this._setAlgNames = function() {
+	if (this.algName.match(/^(.+)with(.+)$/)) {
+	    this.mdAlgName = RegExp.$1.toLowerCase();
+	    this.pubkeyAlgName = RegExp.$2.toLowerCase();
+	}
+    };
+
+    this._zeroPaddingOfSignature = function(hex, bitLength) {
+	var s = "";
+	var nZero = bitLength / 4 - hex.length;
+	for (var i = 0; i < nZero; i++) {
+	    s = s + "0";
+	}
+	return s + hex;
+    };
+
+    /**
+     * set signature algorithm and provider
+     * @name setAlgAndProvider
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} alg signature algorithm name
+     * @param {String} prov provider name
+     * @description
+     * @example
+     * md.setAlgAndProvider('SHA1withRSA', 'cryptojs/jsrsa');
+     */
+    this.setAlgAndProvider = function(alg, prov) {
+	this._setAlgNames();
+	if (prov != 'cryptojs/jsrsa')
+	    throw "provider not supported: " + prov;
+
+	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(this.mdAlgName) != -1) {
+	    try {
+		this.md = new KJUR.crypto.MessageDigest({'alg':this.mdAlgName});
+	    } catch (ex) {
+		throw "setAlgAndProvider hash alg set fail alg=" +
+                      this.mdAlgName + "/" + ex;
+	    }
+
+	    this.init = function(keyparam, pass) {
+		var keyObj = null;
+		try {
+		    if (pass === undefined) {
+			keyObj = KEYUTIL.getKey(keyparam);
+		    } else {
+			keyObj = KEYUTIL.getKey(keyparam, pass);
+		    }
+		} catch (ex) {
+		    throw "init failed:" + ex;
+		}
+
+		if (keyObj.isPrivate === true) {
+		    this.prvKey = keyObj;
+		    this.state = "SIGN";
+		} else if (keyObj.isPublic === true) {
+		    this.pubKey = keyObj;
+		    this.state = "VERIFY";
+		} else {
+		    throw "init failed.:" + keyObj;
+		}
+	    };
+
+	    this.initSign = function(params) {
+		if (typeof params['ecprvhex'] == 'string' &&
+                    typeof params['eccurvename'] == 'string') {
+		    this.ecprvhex = params['ecprvhex'];
+		    this.eccurvename = params['eccurvename'];
+		} else {
+		    this.prvKey = params;
+		}
+		this.state = "SIGN";
+	    };
+
+	    this.initVerifyByPublicKey = function(params) {
+		if (typeof params['ecpubhex'] == 'string' &&
+		    typeof params['eccurvename'] == 'string') {
+		    this.ecpubhex = params['ecpubhex'];
+		    this.eccurvename = params['eccurvename'];
+		} else if (params instanceof KJUR.crypto.ECDSA) {
+		    this.pubKey = params;
+		} else if (params instanceof RSAKey) {
+		    this.pubKey = params;
+		}
+		this.state = "VERIFY";
+	    };
+
+	    this.initVerifyByCertificatePEM = function(certPEM) {
+		var x509 = new X509();
+		x509.readCertPEM(certPEM);
+		this.pubKey = x509.subjectPublicKeyRSA;
+		this.state = "VERIFY";
+	    };
+
+	    this.updateString = function(str) {
+		this.md.updateString(str);
+	    };
+
+	    this.updateHex = function(hex) {
+		this.md.updateHex(hex);
+	    };
+
+	    this.sign = function() {
+		this.sHashHex = this.md.digest();
+		if (typeof this.ecprvhex != "undefined" &&
+		    typeof this.eccurvename != "undefined") {
+		    var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename});
+		    this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
+		} else if (this.prvKey instanceof RSAKey &&
+		           this.pubkeyAlgName == "rsaandmgf1") {
+		    this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex,
+								    this.mdAlgName,
+								    this.pssSaltLen);
+		} else if (this.prvKey instanceof RSAKey &&
+			   this.pubkeyAlgName == "rsa") {
+		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex,
+								 this.mdAlgName);
+		} else if (this.prvKey instanceof KJUR.crypto.ECDSA) {
+		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
+		} else if (this.prvKey instanceof KJUR.crypto.DSA) {
+		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
+		} else {
+		    throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
+		}
+		return this.hSign;
+	    };
+	    this.signString = function(str) {
+		this.updateString(str);
+		return this.sign();
+	    };
+	    this.signHex = function(hex) {
+		this.updateHex(hex);
+		return this.sign();
+	    };
+	    this.verify = function(hSigVal) {
+	        this.sHashHex = this.md.digest();
+		if (typeof this.ecpubhex != "undefined" &&
+		    typeof this.eccurvename != "undefined") {
+		    var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename});
+		    return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
+		} else if (this.pubKey instanceof RSAKey &&
+			   this.pubkeyAlgName == "rsaandmgf1") {
+		    return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal, 
+								this.mdAlgName,
+								this.pssSaltLen);
+		} else if (this.pubKey instanceof RSAKey &&
+			   this.pubkeyAlgName == "rsa") {
+		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+		} else if (this.pubKey instanceof KJUR.crypto.ECDSA) {
+		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+		} else if (this.pubKey instanceof KJUR.crypto.DSA) {
+		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+		} else {
+		    throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
+		}
+	    };
+	}
+    };
+
+    /**
+     * Initialize this object for signing or verifying depends on key
+     * @name init
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {Object} key specifying public or private key as plain/encrypted PKCS#5/8 PEM file, certificate PEM or {@link RSAKey}, {@link KJUR.crypto.DSA} or {@link KJUR.crypto.ECDSA} object
+     * @param {String} pass (OPTION) passcode for encrypted private key
+     * @since crypto 1.1.3
+     * @description
+     * This method is very useful initialize method for Signature class since
+     * you just specify key then this method will automatically initialize it
+     * using {@link KEYUTIL.getKey} method.
+     * As for 'key',  following argument type are supported:
+     * <h5>signing</h5>
+     * <ul>
+     * <li>PEM formatted PKCS#8 encrypted RSA/ECDSA private key concluding "BEGIN ENCRYPTED PRIVATE KEY"</li>
+     * <li>PEM formatted PKCS#5 encrypted RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" and ",ENCRYPTED"</li>
+     * <li>PEM formatted PKCS#8 plain RSA/ECDSA private key concluding "BEGIN PRIVATE KEY"</li>
+     * <li>PEM formatted PKCS#5 plain RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" without ",ENCRYPTED"</li>
+     * <li>RSAKey object of private key</li>
+     * <li>KJUR.crypto.ECDSA object of private key</li>
+     * <li>KJUR.crypto.DSA object of private key</li>
+     * </ul>
+     * <h5>verification</h5>
+     * <ul>
+     * <li>PEM formatted PKCS#8 RSA/EC/DSA public key concluding "BEGIN PUBLIC KEY"</li>
+     * <li>PEM formatted X.509 certificate with RSA/EC/DSA public key concluding
+     *     "BEGIN CERTIFICATE", "BEGIN X509 CERTIFICATE" or "BEGIN TRUSTED CERTIFICATE".</li>
+     * <li>RSAKey object of public key</li>
+     * <li>KJUR.crypto.ECDSA object of public key</li>
+     * <li>KJUR.crypto.DSA object of public key</li>
+     * </ul>
+     * @example
+     * sig.init(sCertPEM)
+     */
+    this.init = function(key, pass) {
+	throw "init(key, pass) not supported for this alg:prov=" +
+	      this.algProvName;
+    };
+
+    /**
+     * Initialize this object for verifying with a public key
+     * @name initVerifyByPublicKey
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {Object} param RSAKey object of public key or associative array for ECDSA
+     * @since 1.0.2
+     * @deprecated from crypto 1.1.5. please use init() method instead.
+     * @description
+     * Public key information will be provided as 'param' parameter and the value will be
+     * following:
+     * <ul>
+     * <li>{@link RSAKey} object for RSA verification</li>
+     * <li>associative array for ECDSA verification
+     *     (ex. <code>{'ecpubhex': '041f..', 'eccurvename': 'secp256r1'}</code>)
+     * </li>
+     * </ul>
+     * @example
+     * sig.initVerifyByPublicKey(rsaPrvKey)
+     */
+    this.initVerifyByPublicKey = function(rsaPubKey) {
+	throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" +
+	      this.algProvName;
+    };
+
+    /**
+     * Initialize this object for verifying with a certficate
+     * @name initVerifyByCertificatePEM
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} certPEM PEM formatted string of certificate
+     * @since 1.0.2
+     * @deprecated from crypto 1.1.5. please use init() method instead.
+     * @description
+     * @example
+     * sig.initVerifyByCertificatePEM(certPEM)
+     */
+    this.initVerifyByCertificatePEM = function(certPEM) {
+	throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" +
+	    this.algProvName;
+    };
+
+    /**
+     * Initialize this object for signing
+     * @name initSign
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {Object} param RSAKey object of public key or associative array for ECDSA
+     * @deprecated from crypto 1.1.5. please use init() method instead.
+     * @description
+     * Private key information will be provided as 'param' parameter and the value will be
+     * following:
+     * <ul>
+     * <li>{@link RSAKey} object for RSA signing</li>
+     * <li>associative array for ECDSA signing
+     *     (ex. <code>{'ecprvhex': '1d3f..', 'eccurvename': 'secp256r1'}</code>)</li>
+     * </ul>
+     * @example
+     * sig.initSign(prvKey)
+     */
+    this.initSign = function(prvKey) {
+	throw "initSign(prvKey) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * Updates the data to be signed or verified by a string
+     * @name updateString
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} str string to use for the update
+     * @description
+     * @example
+     * sig.updateString('aaa')
+     */
+    this.updateString = function(str) {
+	throw "updateString(str) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * Updates the data to be signed or verified by a hexadecimal string
+     * @name updateHex
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} hex hexadecimal string to use for the update
+     * @description
+     * @example
+     * sig.updateHex('1f2f3f')
+     */
+    this.updateHex = function(hex) {
+	throw "updateHex(hex) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * Returns the signature bytes of all data updates as a hexadecimal string
+     * @name sign
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @return the signature bytes as a hexadecimal string
+     * @description
+     * @example
+     * var hSigValue = sig.sign()
+     */
+    this.sign = function() {
+	throw "sign() not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * performs final update on the sign using string, then returns the signature bytes of all data updates as a hexadecimal string
+     * @name signString
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} str string to final update
+     * @return the signature bytes of a hexadecimal string
+     * @description
+     * @example
+     * var hSigValue = sig.signString('aaa')
+     */
+    this.signString = function(str) {
+	throw "digestString(str) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * performs final update on the sign using hexadecimal string, then returns the signature bytes of all data updates as a hexadecimal string
+     * @name signHex
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} hex hexadecimal string to final update
+     * @return the signature bytes of a hexadecimal string
+     * @description
+     * @example
+     * var hSigValue = sig.signHex('1fdc33')
+     */
+    this.signHex = function(hex) {
+	throw "digestHex(hex) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    /**
+     * verifies the passed-in signature.
+     * @name verify
+     * @memberOf KJUR.crypto.Signature
+     * @function
+     * @param {String} str string to final update
+     * @return {Boolean} true if the signature was verified, otherwise false
+     * @description
+     * @example
+     * var isValid = sig.verify('1fbcefdca4823a7(snip)')
+     */
+    this.verify = function(hSigVal) {
+	throw "verify(hSigVal) not supported for this alg:prov=" + this.algProvName;
+    };
+
+    this.initParams = params;
+
+    if (params !== undefined) {
+	if (params['alg'] !== undefined) {
+	    this.algName = params['alg'];
+	    if (params['prov'] === undefined) {
+		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+	    } else {
+		this.provName = params['prov'];
+	    }
+	    this.algProvName = this.algName + ":" + this.provName;
+	    this.setAlgAndProvider(this.algName, this.provName);
+	    this._setAlgNames();
+	}
+
+	if (params['psssaltlen'] !== undefined) this.pssSaltLen = params['psssaltlen'];
+
+	if (params['prvkeypem'] !== undefined) {
+	    if (params['prvkeypas'] !== undefined) {
+		throw "both prvkeypem and prvkeypas parameters not supported";
+	    } else {
+		try {
+		    var prvKey = new RSAKey();
+		    prvKey.readPrivateKeyFromPEMString(params['prvkeypem']);
+		    this.initSign(prvKey);
+		} catch (ex) {
+		    throw "fatal error to load pem private key: " + ex;
+		}
+	    }
+	}
+    }
+};
+
+/**
+ * static object for cryptographic function utilities
+ * @name KJUR.crypto.OID
+ * @class static object for cryptography related OIDs
+ * @property {Array} oidhex2name key value of hexadecimal OID and its name
+ *           (ex. '2a8648ce3d030107' and 'secp256r1')
+ * @since crypto 1.1.3
+ * @description
+ */
+
+
+KJUR.crypto.OID = new function() {
+    this.oidhex2name = {
+	'2a864886f70d010101': 'rsaEncryption',
+	'2a8648ce3d0201': 'ecPublicKey',
+	'2a8648ce380401': 'dsa',
+	'2a8648ce3d030107': 'secp256r1',
+	'2b8104001f': 'secp192k1',
+	'2b81040021': 'secp224r1',
+	'2b8104000a': 'secp256k1',
+	'2b81040023': 'secp521r1',
+	'2b81040022': 'secp384r1',
+	'2a8648ce380403': 'SHA1withDSA', // 1.2.840.10040.4.3
+	'608648016503040301': 'SHA224withDSA', // 2.16.840.1.101.3.4.3.1
+	'608648016503040302': 'SHA256withDSA'  // 2.16.840.1.101.3.4.3.2
+    };
+};
+
+exports.KJUR = KJUR;
+module.exports = exports;
 /*! rsapem-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
  */
 //
 // rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
 //              to RSAKey class.
 //
-// version: 1.1 (2012-May-10)
+// version: 1.1.1 (2013-Apr-12)
 //
-// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
+// Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
 //
 // This software is licensed under the terms of the MIT License.
 // http://kjur.github.com/jsrsasign/license/
@@ -5381,6 +3582,18 @@
 //   new lines from PEM formatted RSA private key string.
 //
 
+/**
+ * @fileOverview
+ * @name rsapem-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version 1.1
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ */
+
+var ASN1HEX = require('./asn1hex-1.1.js').ASN1HEX;
+var b64tohex = require('./base64.js').b64tohex;
+var RSAKey = require('./rsa2.js').RSAKey;
+
 function _rsapem_pemToBase64(sPEMPrivateKey) {
   var s = sPEMPrivateKey;
   s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
@@ -5421,6 +3634,19 @@
 }
 
 /**
+ * read RSA private key from a ASN.1 hexadecimal string
+ * @name readPrivateKeyFromASN1HexString
+ * @memberOf RSAKey#
+ * @function
+ * @param {String} keyHex ASN.1 hexadecimal string of PKCS#1 private key.
+ * @since 1.1.1
+ */
+function _rsapem_readPrivateKeyFromASN1HexString(keyHex) {
+  var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
+  this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
+}
+
+/**
  * read PKCS#1 private key from a string
  * @name readPrivateKeyFromPEMString
  * @memberOf RSAKey#
@@ -5435,70 +3661,37 @@
 }
 
 RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
-/*! rsasign-1.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
+RSAKey.prototype.readPrivateKeyFromASN1HexString = _rsapem_readPrivateKeyFromASN1HexString;
+
+exports.RSAKey = RSAKey;
+module.exports = exports;
+/*! rsasign-1.2.7.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
  */
-//
-// rsa-sign.js - adding signing functions to RSAKey class.
-//
-//
-// version: 1.2.1 (08 May 2012)
-//
-// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
-//
-// This software is licensed under the terms of the MIT License.
-// http://kjur.github.com/jsrsasign/license/
-//
-// The above copyright and license notice shall be 
-// included in all copies or substantial portions of the Software.
-
-//
-// Depends on:
-//   function sha1.hex(s) of sha1.js
-//   jsbn.js
-//   jsbn2.js
-//   rsa.js
-//   rsa2.js
-//
-
-// keysize / pmstrlen
-//  512 /  128
-// 1024 /  256
-// 2048 /  512
-// 4096 / 1024
+/*
+ * rsa-sign.js - adding signing functions to RSAKey class.
+ *
+ * version: 1.2.7 (2013 Aug 25)
+ *
+ * Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license/
+ *
+ * The above copyright and license notice shall be 
+ * included in all copies or substantial portions of the Software.
+ */
 
 /**
- * @property {Dictionary} _RSASIGN_DIHEAD
- * @description Array of head part of hexadecimal DigestInfo value for hash algorithms.
- * You can add any DigestInfo hash algorith for signing.
- * See PKCS#1 v2.1 spec (p38).
+ * @fileOverview
+ * @name rsasign-1.2.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version rsasign 1.2.7
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
  */
-var _RSASIGN_DIHEAD = [];
-_RSASIGN_DIHEAD['sha1'] =      "3021300906052b0e03021a05000414";
-_RSASIGN_DIHEAD['sha256'] =    "3031300d060960864801650304020105000420";
-_RSASIGN_DIHEAD['sha384'] =    "3041300d060960864801650304020205000430";
-_RSASIGN_DIHEAD['sha512'] =    "3051300d060960864801650304020305000440";
-_RSASIGN_DIHEAD['md2'] =       "3020300c06082a864886f70d020205000410";
-_RSASIGN_DIHEAD['md5'] =       "3020300c06082a864886f70d020505000410";
-_RSASIGN_DIHEAD['ripemd160'] = "3021300906052b2403020105000414";
 
-/**
- * @property {Dictionary} _RSASIGN_HASHHEXFUNC
- * @description Array of functions which calculate hash and returns it as hexadecimal.
- * You can add any hash algorithm implementations.
- */
-var _RSASIGN_HASHHEXFUNC = [];
-_RSASIGN_HASHHEXFUNC['sha1'] =      function(s){return hex_sha1(s);};  // http://pajhome.org.uk/crypt/md5/md5.html
-_RSASIGN_HASHHEXFUNC['sha256'] =    function(s){return hex_sha256(s);} // http://pajhome.org.uk/crypt/md5/md5.html
-_RSASIGN_HASHHEXFUNC['sha512'] =    function(s){return hex_sha512(s);} // http://pajhome.org.uk/crypt/md5/md5.html
-_RSASIGN_HASHHEXFUNC['md5'] =       function(s){return hex_md5(s);};   // http://pajhome.org.uk/crypt/md5/md5.html
-_RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return hex_rmd160(s);};   // http://pajhome.org.uk/crypt/md5/md5.html
-
-//@author axelcdv
-var _RSASIGN_HASHBYTEFUNC = [];
-_RSASIGN_HASHBYTEFUNC['sha256'] = 	function(byteArray){return hex_sha256_from_bytes(byteArray);};
-
-//_RSASIGN_HASHHEXFUNC['sha1'] =   function(s){return sha1.hex(s);}   // http://user1.matsumoto.ne.jp/~goma/js/hash.html
-//_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;}    // http://user1.matsumoto.ne.jp/~goma/js/hash.html
+var intShim = require('jsbn');
+var BigInteger = intShim.BigInteger ? intShim.BigInteger : intShim;
+var RSAKey = require('./rsapem-1.1.js').RSAKey
 
 var _RE_HEXDECONLY = new RegExp("");
 _RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
@@ -5508,134 +3701,176 @@
 // ========================================================================
 
 function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
-  var pmStrLen = keySize / 4;
-  var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
-  var sHashHex = hashFunc(s);
+    var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
+    var sHashHex = hashFunc(s);
 
-  var sHead = "0001";
-  var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
-  var sMid = "";
-  var fLen = pmStrLen - sHead.length - sTail.length;
-  for (var i = 0; i < fLen; i += 2) {
-    sMid += "ff";
-  }
-  sPaddedMessageHex = sHead + sMid + sTail;
-  return sPaddedMessageHex;
-}
-
-
-//@author: Meki Cheraoui
-function _rsasign_getHexPaddedDigestInfoForStringHEX(s, keySize, hashAlg) {
-  var pmStrLen = keySize / 4;
-  var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
-  var sHashHex = hashFunc(s);
-
-  var sHead = "0001";
-  var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
-  var sMid = "";
-  var fLen = pmStrLen - sHead.length - sTail.length;
-  for (var i = 0; i < fLen; i += 2) {
-    sMid += "ff";
-  }
-  sPaddedMessageHex = sHead + sMid + sTail;
-  return sPaddedMessageHex;
-}
-
-/**
- * Apply padding, then computes the hash of the given byte array, according to the key size and with the hash algorithm
- * @param byteArray (byte[])
- * @param keySize (int)
- * @param hashAlg the hash algorithm to apply (string)
- * @return the hash of byteArray
- */
-function _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, keySize, hashAlg){
-	var pmStrLen = keySize / 4;
-	var hashFunc = _RSASIGN_HASHBYTEFUNC[hashAlg];
-	var sHashHex = hashFunc(byteArray); //returns hex hash
-	
-	var sHead = "0001";
-	  var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
-	  var sMid = "";
-	  var fLen = pmStrLen - sHead.length - sTail.length;
-	  for (var i = 0; i < fLen; i += 2) {
-	    sMid += "ff";
-	  }
-	  sPaddedMessageHex = sHead + sMid + sTail;
-	  return sPaddedMessageHex;
+    return KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, keySize);
 }
 
 function _zeroPaddingOfSignature(hex, bitLength) {
-  var s = "";
-  var nZero = bitLength / 4 - hex.length;
-  for (var i = 0; i < nZero; i++) {
-    s = s + "0";
-  }
-  return s + hex;
+    var s = "";
+    var nZero = bitLength / 4 - hex.length;
+    for (var i = 0; i < nZero; i++) {
+	s = s + "0";
+    }
+    return s + hex;
 }
 
 /**
  * sign for a message string with RSA private key.<br/>
  * @name signString
- * @memberOf RSAKey#
+ * @memberOf RSAKey
  * @function
  * @param {String} s message string to be signed.
  * @param {String} hashAlg hash algorithm name for signing.<br/>
  * @return returns hexadecimal string of signature value.
  */
 function _rsasign_signString(s, hashAlg) {
-  //alert("this.n.bitLength() = " + this.n.bitLength());
-  var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
-  var biPaddedMessage = parseBigInt(hPM, 16);
-  var biSign = this.doPrivate(biPaddedMessage);
-  var hexSign = biSign.toString(16);
-  return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
-}
+    var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
+    var sHashHex = hashFunc(s);
 
-//@author: ucla-cs
-function _rsasign_signStringHEX(s, hashAlg) {
-  //alert("this.n.bitLength() = " + this.n.bitLength());
-  var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
-  var biPaddedMessage = parseBigInt(hPM, 16);
-  var biSign = this.doPrivate(biPaddedMessage);
-  var hexSign = biSign.toString(16);
-  return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
+    return this.signWithMessageHash(sHashHex, hashAlg);
 }
 
-
 /**
- * Sign a message byteArray with an RSA private key
- * @name signByteArray
- * @memberOf RSAKey#
+ * sign hash value of message to be signed with RSA private key.<br/>
+ * @name signWithMessageHash
+ * @memberOf RSAKey
  * @function
- * @param {byte[]} byteArray
- * @param {Sring} hashAlg the hash algorithm to apply
- * @param {RSAKey} rsa key to sign with: hack because the context is lost here
- * @return hexadecimal string of signature value
+ * @param {String} sHashHex hexadecimal string of hash value of message to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.<br/>
+ * @return returns hexadecimal string of signature value.
+ * @since rsasign 1.2.6
  */
-function _rsasign_signByteArray(byteArray, hashAlg, rsaKey) {
-	var hPM = _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, rsaKey.n.bitLength(), hashAlg); ///hack because the context is lost here
-	var biPaddedMessage = parseBigInt(hPM, 16);
-	var biSign = rsaKey.doPrivate(biPaddedMessage); //hack because the context is lost here
-	var hexSign = biSign.toString(16);
-	return _zeroPaddingOfSignature(hexSign, rsaKey.n.bitLength()); //hack because the context is lost here
+function _rsasign_signWithMessageHash(sHashHex, hashAlg) {
+    var hPM = KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, this.n.bitLength());
+    var biPaddedMessage = parseBigInt(hPM, 16);
+    var biSign = this.doPrivate(biPaddedMessage);
+    var hexSign = biSign.toString(16);
+    return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
 }
 
-/**
- * Sign a byte array with the Sha-256 algorithm
- * @param {byte[]} byteArray
- * @return hexadecimal string of signature value
- */
-function _rsasign_signByteArrayWithSHA256(byteArray){
-	return _rsasign_signByteArray(byteArray, 'sha256', this); //Hack because the context is lost in the next function
-}
-
-
 function _rsasign_signStringWithSHA1(s) {
-  return _rsasign_signString(s, 'sha1');
+    return _rsasign_signString.call(this, s, 'sha1');
 }
 
 function _rsasign_signStringWithSHA256(s) {
-  return _rsasign_signString(s, 'sha256');
+    return _rsasign_signString.call(this, s, 'sha256');
+}
+
+// PKCS#1 (PSS) mask generation function
+function pss_mgf1_str(seed, len, hash) {
+    var mask = '', i = 0;
+
+    while (mask.length < len) {
+        mask += hextorstr(hash(rstrtohex(seed + String.fromCharCode.apply(String, [
+                (i & 0xff000000) >> 24,
+                (i & 0x00ff0000) >> 16,
+                (i & 0x0000ff00) >> 8,
+                i & 0x000000ff]))));
+        i += 1;
+    }
+
+    return mask;
+}
+
+/**
+ * sign for a message string with RSA private key by PKCS#1 PSS signing.<br/>
+ * @name signStringPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} s message string to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ *        There are two special values:
+ *        <ul>
+ *        <li>-1: sets the salt length to the digest length</li>
+ *        <li>-2: sets the salt length to maximum permissible value
+ *           (i.e. keybytelen - hashbytelen - 2)</li>
+ *        </ul>
+ *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns hexadecimal string of signature value.
+ */
+function _rsasign_signStringPSS(s, hashAlg, sLen) {
+    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); } 
+    var hHash = hashFunc(rstrtohex(s));
+
+    if (sLen === undefined) sLen = -1;
+    return this.signWithMessageHashPSS(hHash, hashAlg, sLen);
+}
+
+/**
+ * sign hash value of message with RSA private key by PKCS#1 PSS signing.<br/>
+ * @name signWithMessageHashPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} hHash hexadecimal hash value of message to be signed.
+ * @param {String} hashAlg hash algorithm name for signing.
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ *        There are two special values:
+ *        <ul>
+ *        <li>-1: sets the salt length to the digest length</li>
+ *        <li>-2: sets the salt length to maximum permissible value
+ *           (i.e. keybytelen - hashbytelen - 2)</li>
+ *        </ul>
+ *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns hexadecimal string of signature value.
+ * @since rsasign 1.2.6
+ */
+function _rsasign_signWithMessageHashPSS(hHash, hashAlg, sLen) {
+    var mHash = hextorstr(hHash);
+    var hLen = mHash.length;
+    var emBits = this.n.bitLength() - 1;
+    var emLen = Math.ceil(emBits / 8);
+    var i;
+    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); } 
+
+    if (sLen === -1 || sLen === undefined) {
+        sLen = hLen; // same as hash length
+    } else if (sLen === -2) {
+        sLen = emLen - hLen - 2; // maximum
+    } else if (sLen < -2) {
+        throw "invalid salt length";
+    }
+
+    if (emLen < (hLen + sLen + 2)) {
+        throw "data too long";
+    }
+
+    var salt = '';
+
+    if (sLen > 0) {
+        salt = new Array(sLen);
+        new SecureRandom().nextBytes(salt);
+        salt = String.fromCharCode.apply(String, salt);
+    }
+
+    var H = hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt)));
+    var PS = [];
+
+    for (i = 0; i < emLen - sLen - hLen - 2; i += 1) {
+        PS[i] = 0x00;
+    }
+
+    var DB = String.fromCharCode.apply(String, PS) + '\x01' + salt;
+    var dbMask = pss_mgf1_str(H, DB.length, hashFunc);
+    var maskedDB = [];
+
+    for (i = 0; i < DB.length; i += 1) {
+        maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+    }
+
+    var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
+    maskedDB[0] &= ~mask;
+
+    for (i = 0; i < hLen; i++) {
+        maskedDB.push(H.charCodeAt(i));
+    }
+
+    maskedDB.push(0xbc);
+
+    return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(maskedDB)).toString(16),
+				   this.n.bitLength());
 }
 
 // ========================================================================
@@ -5643,47 +3878,47 @@
 // ========================================================================
 
 function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
-  var rsa = new RSAKey();
-  rsa.setPublic(hN, hE);
-  var biDecryptedSig = rsa.doPublic(biSig);
-  return biDecryptedSig;
+    var rsa = new RSAKey();
+    rsa.setPublic(hN, hE);
+    var biDecryptedSig = rsa.doPublic(biSig);
+    return biDecryptedSig;
 }
 
 function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
-  var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
-  var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
-  return hDigestInfo;
+    var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
+    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+    return hDigestInfo;
 }
 
 function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
-  for (var algName in _RSASIGN_DIHEAD) {
-    var head = _RSASIGN_DIHEAD[algName];
-    var len = head.length;
-    if (hDigestInfo.substring(0, len) == head) {
-      var a = [algName, hDigestInfo.substring(len)];
-      return a;
+    for (var algName in KJUR.crypto.Util.DIGESTINFOHEAD) {
+	var head = KJUR.crypto.Util.DIGESTINFOHEAD[algName];
+	var len = head.length;
+	if (hDigestInfo.substring(0, len) == head) {
+	    var a = [algName, hDigestInfo.substring(len)];
+	    return a;
+	}
     }
-  }
-  return [];
+    return [];
 }
 
 function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
-  var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
-  var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
-  if (digestInfoAry.length == 0) return false;
-  var algName = digestInfoAry[0];
-  var diHashValue = digestInfoAry[1];
-  var ff = _RSASIGN_HASHHEXFUNC[algName];
-  var msgHashValue = ff(sMsg);
-  return (diHashValue == msgHashValue);
+    var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
+    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
+    if (digestInfoAry.length == 0) return false;
+    var algName = digestInfoAry[0];
+    var diHashValue = digestInfoAry[1];
+    var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
+    var msgHashValue = ff(sMsg);
+    return (diHashValue == msgHashValue);
 }
 
 function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
-  var biSig = parseBigInt(hSig, 16);
-  var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
-						this.n.toString(16),
-						this.e.toString(16));
-  return result;
+    var biSig = parseBigInt(hSig, 16);
+    var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
+						  this.n.toString(16),
+						  this.e.toString(16));
+    return result;
 }
 
 /**
@@ -5697,661 +3932,1410 @@
  * @return returns 1 if valid, otherwise 0
  */
 function _rsasign_verifyString(sMsg, hSig) {
-  hSig = hSig.replace(_RE_HEXDECONLY, '');
+    hSig = hSig.replace(_RE_HEXDECONLY, '');
+    hSig = hSig.replace(/[ \n]+/g, "");
+    var biSig = parseBigInt(hSig, 16);
+    if (biSig.bitLength() > this.n.bitLength()) return 0;
+    var biDecryptedSig = this.doPublic(biSig);
+    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
   
-  if(LOG>3)console.log('n is '+this.n);
-  if(LOG>3)console.log('e is '+this.e);
-  
-  if (hSig.length != this.n.bitLength() / 4) return 0;
-  hSig = hSig.replace(/[ \n]+/g, "");
-  var biSig = parseBigInt(hSig, 16);
-  var biDecryptedSig = this.doPublic(biSig);
-  var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
-  var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
-  
-  if (digestInfoAry.length == 0) return false;
-  var algName = digestInfoAry[0];
-  var diHashValue = digestInfoAry[1];
-  var ff = _RSASIGN_HASHHEXFUNC[algName];
-  var msgHashValue = ff(sMsg);
-  return (diHashValue == msgHashValue);
+    if (digestInfoAry.length == 0) return false;
+    var algName = digestInfoAry[0];
+    var diHashValue = digestInfoAry[1];
+    var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
+    var msgHashValue = ff(sMsg);
+    return (diHashValue == msgHashValue);
 }
 
 /**
- * verifies a sigature for a message byte array with RSA public key.<br/>
- * @name verifyByteArray
- * @memberOf RSAKey#
+ * verifies a sigature for a message string with RSA public key.<br/>
+ * @name verifyWithMessageHash
+ * @memberOf RSAKey
  * @function
- * @param {byte[]} byteArray message byte array to be verified.
- * @param {String} hSig hexadecimal string of signature.<br/>
+ * @param {String} sHashHex hexadecimal hash value of message to be verified.
+ * @param {String} hSig hexadecimal string of siganture.<br/>
  *                 non-hexadecimal charactors including new lines will be ignored.
- * @return returns 1 if valid, otherwise 0 
+ * @return returns 1 if valid, otherwise 0
+ * @since rsasign 1.2.6
  */
-function _rsasign_verifyByteArray(byteArray, witness, hSig) {
-	hSig = hSig.replace(_RE_HEXDECONLY, '');
-	  
-	  if(LOG>3)console.log('n is '+this.n);
-	  if(LOG>3)console.log('e is '+this.e);
-	  
-	  if (hSig.length != this.n.bitLength() / 4) return 0;
-	  hSig = hSig.replace(/[ \n]+/g, "");
-	  var biSig = parseBigInt(hSig, 16);
-	  var biDecryptedSig = this.doPublic(biSig);
-	  var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
-	  var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
-	  
-	  if (digestInfoAry.length == 0) return false;
-	  var algName = digestInfoAry[0];
-	  var diHashValue = digestInfoAry[1];
-	  var msgHashValue = null;
-	  
-	  if (witness == null) {
-	  	var ff = _RSASIGN_HASHBYTEFUNC[algName];
-	  	msgHashValue = ff(byteArray);
-	  } else {
-	  	// Compute merkle hash
-		  var h = hex_sha256_from_bytes(byteArray);
-		  var index = witness.path.index;
-		  for (var i = witness.path.digestList.length - 1; i >= 0; i--) {
-		  	var str = "";
-		  	if (index % 2 == 0) {
-		  		str = h + witness.path.digestList[i];
-		  	} else {
-		  		str = witness.path.digestList[i] + h;
-		  	}
-		  	h = hex_sha256_from_bytes(DataUtils.toNumbers(str));
-		  	index = Math.floor(index / 2);
-		  }
-		  msgHashValue = hex_sha256_from_bytes(DataUtils.toNumbers(h));
-	  }
-	  //console.log(diHashValue);
-	  //console.log(msgHashValue);
-	  return (diHashValue == msgHashValue);
+function _rsasign_verifyWithMessageHash(sHashHex, hSig) {
+    hSig = hSig.replace(_RE_HEXDECONLY, '');
+    hSig = hSig.replace(/[ \n]+/g, "");
+    var biSig = parseBigInt(hSig, 16);
+    if (biSig.bitLength() > this.n.bitLength()) return 0;
+    var biDecryptedSig = this.doPublic(biSig);
+    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
+  
+    if (digestInfoAry.length == 0) return false;
+    var algName = digestInfoAry[0];
+    var diHashValue = digestInfoAry[1];
+    return (diHashValue == sHashHex);
 }
 
+/**
+ * verifies a sigature for a message string with RSA public key by PKCS#1 PSS sign.<br/>
+ * @name verifyStringPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} sMsg message string to be verified.
+ * @param {String} hSig hexadecimal string of signature value
+ * @param {String} hashAlg hash algorithm name
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ *        There are two special values:
+ *        <ul>
+ *        <li>-1: sets the salt length to the digest length</li>
+ *        <li>-2: sets the salt length to maximum permissible value
+ *           (i.e. keybytelen - hashbytelen - 2)</li>
+ *        </ul>
+ *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
+ * @return returns true if valid, otherwise false
+ */
+function _rsasign_verifyStringPSS(sMsg, hSig, hashAlg, sLen) {
+    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
+    var hHash = hashFunc(rstrtohex(sMsg));
 
+    if (sLen === undefined) sLen = -1;
+    return this.verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen);
+}
+
+/**
+ * verifies a sigature for a hash value of message string with RSA public key by PKCS#1 PSS sign.<br/>
+ * @name verifyWithMessageHashPSS
+ * @memberOf RSAKey
+ * @function
+ * @param {String} hHash hexadecimal hash value of message string to be verified.
+ * @param {String} hSig hexadecimal string of signature value
+ * @param {String} hashAlg hash algorithm name
+ * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
+ *        There are two special values:
+ *        <ul>
+ *        <li>-1: sets the salt length to the digest length</li>
+ *        <li>-2: sets the salt length to maximum permissible value
+ *           (i.e. keybytelen - hashbytelen - 2)</li>
+ *        </ul>
+ *        DEFAULT is -1 (NOTE: OpenSSL's default is -2.)
+ * @return returns true if valid, otherwise false
+ * @since rsasign 1.2.6
+ */
+function _rsasign_verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen) {
+    var biSig = new BigInteger(hSig, 16);
+
+    if (biSig.bitLength() > this.n.bitLength()) {
+        return false;
+    }
+
+    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
+    var mHash = hextorstr(hHash);
+    var hLen = mHash.length;
+    var emBits = this.n.bitLength() - 1;
+    var emLen = Math.ceil(emBits / 8);
+    var i;
+
+    if (sLen === -1 || sLen === undefined) {
+        sLen = hLen; // same as hash length
+    } else if (sLen === -2) {
+        sLen = emLen - hLen - 2; // recover
+    } else if (sLen < -2) {
+        throw "invalid salt length";
+    }
+
+    if (emLen < (hLen + sLen + 2)) {
+        throw "data too long";
+    }
+
+    var em = this.doPublic(biSig).toByteArray();
+
+    for (i = 0; i < em.length; i += 1) {
+        em[i] &= 0xff;
+    }
+
+    while (em.length < emLen) {
+        em.unshift(0);
+    }
+
+    if (em[emLen -1] !== 0xbc) {
+        throw "encoded message does not end in 0xbc";
+    }
+
+    em = String.fromCharCode.apply(String, em);
+
+    var maskedDB = em.substr(0, emLen - hLen - 1);
+    var H = em.substr(maskedDB.length, hLen);
+
+    var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
+
+    if ((maskedDB.charCodeAt(0) & mask) !== 0) {
+        throw "bits beyond keysize not zero";
+    }
+
+    var dbMask = pss_mgf1_str(H, maskedDB.length, hashFunc);
+    var DB = [];
+
+    for (i = 0; i < maskedDB.length; i += 1) {
+        DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+    }
+
+    DB[0] &= ~mask;
+
+    var checkLen = emLen - hLen - sLen - 2;
+
+    for (i = 0; i < checkLen; i += 1) {
+        if (DB[i] !== 0x00) {
+            throw "leftmost octets not zero";
+        }
+    }
+
+    if (DB[checkLen] !== 0x01) {
+        throw "0x01 marker not found";
+    }
+
+    return H === hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
+				     String.fromCharCode.apply(String, DB.slice(-sLen)))));
+}
+
+RSAKey.prototype.signWithMessageHash = _rsasign_signWithMessageHash;
 RSAKey.prototype.signString = _rsasign_signString;
-
-RSAKey.prototype.signByteArray = _rsasign_signByteArray; //@author axelcdv
-RSAKey.prototype.signByteArrayWithSHA256 = _rsasign_signByteArrayWithSHA256; //@author axelcdv
-
 RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
 RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
 RSAKey.prototype.sign = _rsasign_signString;
 RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
 RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
 
+RSAKey.prototype.signWithMessageHashPSS = _rsasign_signWithMessageHashPSS;
+RSAKey.prototype.signStringPSS = _rsasign_signStringPSS;
+RSAKey.prototype.signPSS = _rsasign_signStringPSS;
+RSAKey.SALT_LEN_HLEN = -1;
+RSAKey.SALT_LEN_MAX = -2;
 
-/*RSAKey.prototype.signStringHEX = _rsasign_signStringHEX;
-RSAKey.prototype.signStringWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
-RSAKey.prototype.signStringWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
-RSAKey.prototype.signHEX = _rsasign_signStringHEX;
-RSAKey.prototype.signWithSHA1HEX = _rsasign_signStringWithSHA1HEX;
-RSAKey.prototype.signWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
-*/
-
-RSAKey.prototype.verifyByteArray = _rsasign_verifyByteArray;
+RSAKey.prototype.verifyWithMessageHash = _rsasign_verifyWithMessageHash;
 RSAKey.prototype.verifyString = _rsasign_verifyString;
 RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
 RSAKey.prototype.verify = _rsasign_verifyString;
 RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
 
-/*
-RSAKey.prototype.verifyStringHEX = _rsasign_verifyStringHEX;
-RSAKey.prototype.verifyHexSignatureForMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
-RSAKey.prototype.verifyHEX = _rsasign_verifyStringHEX;
-RSAKey.prototype.verifyHexSignatureForByteArrayMessageHEX = _rsasign_verifyHexSignatureForMessageHEX;
-*/
-	
-	
+RSAKey.prototype.verifyWithMessageHashPSS = _rsasign_verifyWithMessageHashPSS;
+RSAKey.prototype.verifyStringPSS = _rsasign_verifyStringPSS;
+RSAKey.prototype.verifyPSS = _rsasign_verifyStringPSS;
+RSAKey.SALT_LEN_RECOVER = -2;
+
 /**
  * @name RSAKey
- * @class
+ * @class key of RSA public key algorithm
  * @description Tom Wu's RSA Key class and extension
  */
-/*! asn1hex-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
- */
-//
-// asn1hex.js - Hexadecimal represented ASN.1 string library
-//
-// version: 1.1 (09-May-2012)
-//
-// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
-//
-// This software is licensed under the terms of the MIT License.
-// http://kjur.github.com/jsrsasign/license/
-//
-// The above copyright and license notice shall be 
-// included in all copies or substantial portions of the Software.
-//
-// Depends on:
-//
 
-// MEMO:
-//   f('3082025b02...', 2) ... 82025b ... 3bytes
-//   f('020100', 2) ... 01 ... 1byte
-//   f('0203001...', 2) ... 03 ... 1byte
-//   f('02818003...', 2) ... 8180 ... 2bytes
-//   f('3080....0000', 2) ... 80 ... -1
-//
-//   Requirements:
-//   - ASN.1 type octet length MUST be 1. 
-//     (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
-//   - 
-/**
- * get byte length for ASN.1 L(length) bytes
- * @name getByteLengthOfL_AtObj
- * @memberOf ASN1HEX
- * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return byte length for ASN.1 L(length) bytes
+exports.RSAKey = RSAKey;
+module.exports = exports;
+/*! ecdsa-modified-1.0.4.js (c) Stephan Thomas, Kenji Urushima | github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
  */
-function _asnhex_getByteLengthOfL_AtObj(s, pos) {
-  if (s.substring(pos + 2, pos + 3) != '8') return 1;
-  var i = parseInt(s.substring(pos + 3, pos + 4));
-  if (i == 0) return -1; 		// length octet '80' indefinite length
-  if (0 < i && i < 10) return i + 1;	// including '8?' octet;
-  return -2;				// malformed format
-}
-
+/*
+ * ecdsa-modified.js - modified Bitcoin.ECDSA class
+ * 
+ * Copyright (c) 2013 Stefan Thomas (github.com/justmoon)
+ *                    Kenji Urushima (kenji.urushima@gmail.com)
+ * LICENSE
+ *   https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
+ */
 
 /**
- * get hexadecimal string for ASN.1 L(length) bytes
- * @name getHexOfL_AtObj
- * @memberOf ASN1HEX
- * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return {String} hexadecimal string for ASN.1 L(length) bytes
+ * @fileOverview
+ * @name ecdsa-modified-1.0.js
+ * @author Stefan Thomas (github.com/justmoon) and Kenji Urushima (kenji.urushima@gmail.com)
+ * @version 1.0.4 (2013-Oct-06)
+ * @since jsrsasign 4.0
+ * @license <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE">MIT License</a>
  */
-function _asnhex_getHexOfL_AtObj(s, pos) {
-  var len = _asnhex_getByteLengthOfL_AtObj(s, pos);
-  if (len < 1) return '';
-  return s.substring(pos + 2, pos + 2 + len * 2);
-}
 
-//
-//   getting ASN.1 length value at the position 'idx' of
-//   hexa decimal string 's'.
-//
-//   f('3082025b02...', 0) ... 82025b ... ???
-//   f('020100', 0) ... 01 ... 1
-//   f('0203001...', 0) ... 03 ... 3
-//   f('02818003...', 0) ... 8180 ... 128
-/**
- * get integer value of ASN.1 length for ASN.1 data
- * @name getIntOfL_AtObj
- * @memberOf ASN1HEX
- * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return ASN.1 L(length) integer value
- */
-function _asnhex_getIntOfL_AtObj(s, pos) {
-  var hLength = _asnhex_getHexOfL_AtObj(s, pos);
-  if (hLength == '') return -1;
-  var bi;
-  if (parseInt(hLength.substring(0, 1)) < 8) {
-     bi = parseBigInt(hLength, 16);
-  } else {
-     bi = parseBigInt(hLength.substring(2), 16);
-  }
-  return bi.intValue();
-}
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
 
 /**
- * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
- * @name getStartPosOfV_AtObj
- * @memberOf ASN1HEX
- * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
+ * class for EC key generation,  ECDSA signing and verifcation
+ * @name KJUR.crypto.ECDSA
+ * @class class for EC key generation,  ECDSA signing and verifcation
+ * @description
+ * <p>
+ * CAUTION: Most of the case, you don't need to use this class except
+ * for generating an EC key pair. Please use {@link KJUR.crypto.Signature} class instead.
+ * </p>
+ * <p>
+ * This class was originally developped by Stefan Thomas for Bitcoin JavaScript library.
+ * (See {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/src/ecdsa.js})
+ * Currently this class supports following named curves and their aliases.
+ * <ul>
+ * <li>secp256r1, NIST P-256, P-256, prime256v1 (*)</li>
+ * <li>secp256k1 (*)</li>
+ * <li>secp384r1, NIST P-384, P-384 (*)</li>
+ * </ul>
+ * </p>
  */
-function _asnhex_getStartPosOfV_AtObj(s, pos) {
-  var l_len = _asnhex_getByteLengthOfL_AtObj(s, pos);
-  if (l_len < 0) return l_len;
-  return pos + (l_len + 1) * 2;
-}
+KJUR.crypto.ECDSA = function(params) {
+    var curveName = "secp256r1";	// curve name default
+    var ecparams = null;
+    var prvKeyHex = null;
+    var pubKeyHex = null;
+
+    var rng = new SecureRandom();
+
+    var P_OVER_FOUR = null;
+
+    this.type = "EC";
+
+    function implShamirsTrick(P, k, Q, l) {
+	var m = Math.max(k.bitLength(), l.bitLength());
+	var Z = P.add2D(Q);
+	var R = P.curve.getInfinity();
+
+	for (var i = m - 1; i >= 0; --i) {
+	    R = R.twice2D();
+
+	    R.z = BigInteger.ONE;
+
+	    if (k.testBit(i)) {
+		if (l.testBit(i)) {
+		    R = R.add2D(Z);
+		} else {
+		    R = R.add2D(P);
+		}
+	    } else {
+		if (l.testBit(i)) {
+		    R = R.add2D(Q);
+		}
+	    }
+	}
+	
+	return R;
+    };
+
+    //===========================
+    // PUBLIC METHODS
+    //===========================
+    this.getBigRandom = function (limit) {
+	return new BigInteger(limit.bitLength(), rng)
+	.mod(limit.subtract(BigInteger.ONE))
+	.add(BigInteger.ONE)
+	;
+    };
+
+    this.setNamedCurve = function(curveName) {
+	this.ecparams = KJUR.crypto.ECParameterDB.getByName(curveName);
+	this.prvKeyHex = null;
+	this.pubKeyHex = null;
+	this.curveName = curveName;
+    }
+
+    this.setPrivateKeyHex = function(prvKeyHex) {
+        this.isPrivate = true;
+	this.prvKeyHex = prvKeyHex;
+    }
+
+    this.setPublicKeyHex = function(pubKeyHex) {
+        this.isPublic = true;
+	this.pubKeyHex = pubKeyHex;
+    }
+
+    /**
+     * generate a EC key pair
+     * @name generateKeyPairHex
+     * @memberOf KJUR.crypto.ECDSA
+     * @function
+     * @return {Array} associative array of hexadecimal string of private and public key
+     * @since ecdsa-modified 1.0.1
+     * @example
+     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+     * var keypair = ec.generateKeyPairHex();
+     * var pubhex = keypair.ecpubhex; // hexadecimal string of EC private key (=d)
+     * var prvhex = keypair.ecprvhex; // hexadecimal string of EC public key
+     */
+    this.generateKeyPairHex = function() {
+	var biN = this.ecparams['n'];
+	var biPrv = this.getBigRandom(biN);
+	var epPub = this.ecparams['G'].multiply(biPrv);
+	var biX = epPub.getX().toBigInteger();
+	var biY = epPub.getY().toBigInteger();
+
+	var charlen = this.ecparams['keylen'] / 4;
+	var hPrv = ("0000000000" + biPrv.toString(16)).slice(- charlen);
+	var hX   = ("0000000000" + biX.toString(16)).slice(- charlen);
+	var hY   = ("0000000000" + biY.toString(16)).slice(- charlen);
+	var hPub = "04" + hX + hY;
+
+	this.setPrivateKeyHex(hPrv);
+	this.setPublicKeyHex(hPub);
+	return {'ecprvhex': hPrv, 'ecpubhex': hPub};
+    };
+
+    this.signWithMessageHash = function(hashHex) {
+	return this.signHex(hashHex, this.prvKeyHex);
+    };
+
+    /**
+     * signing to message hash
+     * @name signHex
+     * @memberOf KJUR.crypto.ECDSA
+     * @function
+     * @param {String} hashHex hexadecimal string of hash value of signing message
+     * @param {String} privHex hexadecimal string of EC private key
+     * @return {String} hexadecimal string of ECDSA signature
+     * @since ecdsa-modified 1.0.1
+     * @example
+     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+     * var sigValue = ec.signHex(hash, prvKey);
+     */
+    this.signHex = function (hashHex, privHex) {
+	var d = new BigInteger(privHex, 16);
+	var n = this.ecparams['n'];
+	var e = new BigInteger(hashHex, 16);
+
+	do {
+	    var k = this.getBigRandom(n);
+	    var G = this.ecparams['G'];
+	    var Q = G.multiply(k);
+	    var r = Q.getX().toBigInteger().mod(n);
+	} while (r.compareTo(BigInteger.ZERO) <= 0);
+
+	var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+
+	return KJUR.crypto.ECDSA.biRSSigToASN1Sig(r, s);
+    };
+
+    this.sign = function (hash, priv) {
+	var d = priv;
+	var n = this.ecparams['n'];
+	var e = BigInteger.fromByteArrayUnsigned(hash);
+
+	do {
+	    var k = this.getBigRandom(n);
+	    var G = this.ecparams['G'];
+	    var Q = G.multiply(k);
+	    var r = Q.getX().toBigInteger().mod(n);
+	} while (r.compareTo(BigInteger.ZERO) <= 0);
+
+	var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+	return this.serializeSig(r, s);
+    };
+
+    this.verifyWithMessageHash = function(hashHex, sigHex) {
+	return this.verifyHex(hashHex, sigHex, this.pubKeyHex);
+    };
+
+    /**
+     * verifying signature with message hash and public key
+     * @name verifyHex
+     * @memberOf KJUR.crypto.ECDSA
+     * @function
+     * @param {String} hashHex hexadecimal string of hash value of signing message
+     * @param {String} sigHex hexadecimal string of signature value
+     * @param {String} pubkeyHex hexadecimal string of public key
+     * @return {Boolean} true if the signature is valid, otherwise false
+     * @since ecdsa-modified 1.0.1
+     * @example
+     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+     * var result = ec.verifyHex(msgHashHex, sigHex, pubkeyHex);
+     */
+    this.verifyHex = function(hashHex, sigHex, pubkeyHex) {
+	var r,s;
+
+	var obj = KJUR.crypto.ECDSA.parseSigHex(sigHex);
+	r = obj.r;
+	s = obj.s;
+
+	var Q;
+	Q = ECPointFp.decodeFromHex(this.ecparams['curve'], pubkeyHex);
+	var e = new BigInteger(hashHex, 16);
+
+	return this.verifyRaw(e, r, s, Q);
+    };
+
+    this.verify = function (hash, sig, pubkey) {
+	var r,s;
+	if (Bitcoin.Util.isArray(sig)) {
+	    var obj = this.parseSig(sig);
+	    r = obj.r;
+	    s = obj.s;
+	} else if ("object" === typeof sig && sig.r && sig.s) {
+	    r = sig.r;
+	    s = sig.s;
+	} else {
+	    throw "Invalid value for signature";
+	}
+
+	var Q;
+	if (pubkey instanceof ECPointFp) {
+	    Q = pubkey;
+	} else if (Bitcoin.Util.isArray(pubkey)) {
+	    Q = ECPointFp.decodeFrom(this.ecparams['curve'], pubkey);
+	} else {
+	    throw "Invalid format for pubkey value, must be byte array or ECPointFp";
+	}
+	var e = BigInteger.fromByteArrayUnsigned(hash);
+
+	return this.verifyRaw(e, r, s, Q);
+    };
+
+    this.verifyRaw = function (e, r, s, Q) {
+	var n = this.ecparams['n'];
+	var G = this.ecparams['G'];
+
+	if (r.compareTo(BigInteger.ONE) < 0 ||
+	    r.compareTo(n) >= 0)
+	    return false;
+
+	if (s.compareTo(BigInteger.ONE) < 0 ||
+	    s.compareTo(n) >= 0)
+	    return false;
+
+	var c = s.modInverse(n);
+
+	var u1 = e.multiply(c).mod(n);
+	var u2 = r.multiply(c).mod(n);
+
+	// TODO(!!!): For some reason Shamir's trick isn't working with
+	// signed message verification!? Probably an implementation
+	// error!
+	//var point = implShamirsTrick(G, u1, Q, u2);
+	var point = G.multiply(u1).add(Q.multiply(u2));
+
+	var v = point.getX().toBigInteger().mod(n);
+
+	return v.equals(r);
+    };
+
+    /**
+     * Serialize a signature into DER format.
+     *
+     * Takes two BigIntegers representing r and s and returns a byte array.
+     */
+    this.serializeSig = function (r, s) {
+	var rBa = r.toByteArraySigned();
+	var sBa = s.toByteArraySigned();
+
+	var sequence = [];
+	sequence.push(0x02); // INTEGER
+	sequence.push(rBa.length);
+	sequence = sequence.concat(rBa);
+
+	sequence.push(0x02); // INTEGER
+	sequence.push(sBa.length);
+	sequence = sequence.concat(sBa);
+
+	sequence.unshift(sequence.length);
+	sequence.unshift(0x30); // SEQUENCE
+	return sequence;
+    };
+
+    /**
+     * Parses a byte array containing a DER-encoded signature.
+     *
+     * This function will return an object of the form:
+     *
+     * {
+     *   r: BigInteger,
+     *   s: BigInteger
+     * }
+     */
+    this.parseSig = function (sig) {
+	var cursor;
+	if (sig[0] != 0x30)
+	    throw new Error("Signature not a valid DERSequence");
+
+	cursor = 2;
+	if (sig[cursor] != 0x02)
+	    throw new Error("First element in signature must be a DERInteger");;
+	var rBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
+
+	cursor += 2+sig[cursor+1];
+	if (sig[cursor] != 0x02)
+	    throw new Error("Second element in signature must be a DERInteger");
+	var sBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
+
+	cursor += 2+sig[cursor+1];
+
+	//if (cursor != sig.length)
+	//  throw new Error("Extra bytes in signature");
+
+	var r = BigInteger.fromByteArrayUnsigned(rBa);
+	var s = BigInteger.fromByteArrayUnsigned(sBa);
+
+	return {r: r, s: s};
+    };
+
+    this.parseSigCompact = function (sig) {
+	if (sig.length !== 65) {
+	    throw "Signature has the wrong length";
+	}
+
+	// Signature is prefixed with a type byte storing three bits of
+	// information.
+	var i = sig[0] - 27;
+	if (i < 0 || i > 7) {
+	    throw "Invalid signature type";
+	}
+
+	var n = this.ecparams['n'];
+	var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n);
+	var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n);
+
+	return {r: r, s: s, i: i};
+    };
+
+    /*
+     * Recover a public key from a signature.
+     *
+     * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
+     * Key Recovery Operation".
+     *
+     * http://www.secg.org/download/aid-780/sec1-v2.pdf
+     */
+    /*
+    recoverPubKey: function (r, s, hash, i) {
+	// The recovery parameter i has two bits.
+	i = i & 3;
+
+	// The less significant bit specifies whether the y coordinate
+	// of the compressed point is even or not.
+	var isYEven = i & 1;
+
+	// The more significant bit specifies whether we should use the
+	// first or second candidate key.
+	var isSecondKey = i >> 1;
+
+	var n = this.ecparams['n'];
+	var G = this.ecparams['G'];
+	var curve = this.ecparams['curve'];
+	var p = curve.getQ();
+	var a = curve.getA().toBigInteger();
+	var b = curve.getB().toBigInteger();
+
+	// We precalculate (p + 1) / 4 where p is if the field order
+	if (!P_OVER_FOUR) {
+	    P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4));
+	}
+
+	// 1.1 Compute x
+	var x = isSecondKey ? r.add(n) : r;
+
+	// 1.3 Convert x to point
+	var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p);
+	var beta = alpha.modPow(P_OVER_FOUR, p);
+
+	var xorOdd = beta.isEven() ? (i % 2) : ((i+1) % 2);
+	// If beta is even, but y isn't or vice versa, then convert it,
+	// otherwise we're done and y == beta.
+	var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta);
+
+	// 1.4 Check that nR is at infinity
+	var R = new ECPointFp(curve,
+			      curve.fromBigInteger(x),
+			      curve.fromBigInteger(y));
+	R.validate();
+
+	// 1.5 Compute e from M
+	var e = BigInteger.fromByteArrayUnsigned(hash);
+	var eNeg = BigInteger.ZERO.subtract(e).mod(n);
+
+	// 1.6 Compute Q = r^-1 (sR - eG)
+	var rInv = r.modInverse(n);
+	var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv);
+
+	Q.validate();
+	if (!this.verifyRaw(e, r, s, Q)) {
+	    throw "Pubkey recovery unsuccessful";
+	}
+
+	var pubKey = new Bitcoin.ECKey();
+	pubKey.pub = Q;
+	return pubKey;
+    },
+    */
+
+    /*
+     * Calculate pubkey extraction parameter.
+     *
+     * When extracting a pubkey from a signature, we have to
+     * distinguish four different cases. Rather than putting this
+     * burden on the verifier, Bitcoin includes a 2-bit value with the
+     * signature.
+     *
+     * This function simply tries all four cases and returns the value
+     * that resulted in a successful pubkey recovery.
+     */
+    /*
+    calcPubkeyRecoveryParam: function (address, r, s, hash) {
+	for (var i = 0; i < 4; i++) {
+	    try {
+		var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i);
+		if (pubkey.getBitcoinAddress().toString() == address) {
+		    return i;
+		}
+	    } catch (e) {}
+	}
+	throw "Unable to find valid recovery factor";
+    }
+    */
+
+    if (params !== undefined) {
+	if (params['curve'] !== undefined) {
+	    this.curveName = params['curve'];
+	}
+    }
+    if (this.curveName === undefined) this.curveName = curveName;
+    this.setNamedCurve(this.curveName);
+    if (params !== undefined) {
+	if (params['prv'] !== undefined) this.setPrivateKeyHex(params['prv']);
+	if (params['pub'] !== undefined) this.setPublicKeyHex(params['pub']);
+    }
+};
 
 /**
- * get hexadecimal string of ASN.1 V(value)
- * @name getHexOfV_AtObj
- * @memberOf ASN1HEX
+ * parse ASN.1 DER encoded ECDSA signature
+ * @name parseSigHex
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return {String} hexadecimal string of ASN.1 value.
+ * @static
+ * @param {String} sigHex hexadecimal string of ECDSA signature value
+ * @return {Array} associative array of signature field r and s of BigInteger
+ * @since ecdsa-modified 1.0.1
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var sig = ec.parseSigHex('30...');
+ * var biR = sig.r; // BigInteger object for 'r' field of signature.
+ * var biS = sig.s; // BigInteger object for 's' field of signature.
  */
-function _asnhex_getHexOfV_AtObj(s, pos) {
-  var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
-  var len = _asnhex_getIntOfL_AtObj(s, pos);
-  return s.substring(pos1, pos1 + len * 2);
-}
+KJUR.crypto.ECDSA.parseSigHex = function(sigHex) {
+    var p = KJUR.crypto.ECDSA.parseSigHexInHexRS(sigHex);
+    var biR = new BigInteger(p.r, 16);
+    var biS = new BigInteger(p.s, 16);
+    
+    return {'r': biR, 's': biS};
+};
 
 /**
- * get hexadecimal string of ASN.1 TLV at
- * @name getHexOfTLV_AtObj
- * @memberOf ASN1HEX
+ * parse ASN.1 DER encoded ECDSA signature
+ * @name parseSigHexInHexRS
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return {String} hexadecimal string of ASN.1 TLV.
- * @since 1.1
+ * @static
+ * @param {String} sigHex hexadecimal string of ECDSA signature value
+ * @return {Array} associative array of signature field r and s in hexadecimal
+ * @since ecdsa-modified 1.0.3
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var sig = ec.parseSigHexInHexRS('30...');
+ * var hR = sig.r; // hexadecimal string for 'r' field of signature.
+ * var hS = sig.s; // hexadecimal string for 's' field of signature.
  */
-function _asnhex_getHexOfTLV_AtObj(s, pos) {
-  var hT = s.substr(pos, 2);
-  var hL = _asnhex_getHexOfL_AtObj(s, pos);
-  var hV = _asnhex_getHexOfV_AtObj(s, pos);
-  return hT + hL + hV;
-}
+KJUR.crypto.ECDSA.parseSigHexInHexRS = function(sigHex) {
+    // 1. ASN.1 Sequence Check
+    if (sigHex.substr(0, 2) != "30")
+	throw "signature is not a ASN.1 sequence";
+
+    // 2. Items of ASN.1 Sequence Check
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(sigHex, 0);
+    if (a.length != 2)
+	throw "number of signature ASN.1 sequence elements seem wrong";
+    
+    // 3. Integer check
+    var iTLV1 = a[0];
+    var iTLV2 = a[1];
+    if (sigHex.substr(iTLV1, 2) != "02")
+	throw "1st item of sequene of signature is not ASN.1 integer";
+    if (sigHex.substr(iTLV2, 2) != "02")
+	throw "2nd item of sequene of signature is not ASN.1 integer";
+
+    // 4. getting value
+    var hR = ASN1HEX.getHexOfV_AtObj(sigHex, iTLV1);
+    var hS = ASN1HEX.getHexOfV_AtObj(sigHex, iTLV2);
+    
+    return {'r': hR, 's': hS};
+};
 
 /**
- * get next sibling starting index for ASN.1 object string
- * @name getPosOfNextSibling_AtObj
- * @memberOf ASN1HEX
+ * convert hexadecimal ASN.1 encoded signature to concatinated signature
+ * @name asn1SigToConcatSig
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} pos string index
- * @return next sibling starting index for ASN.1 object string
+ * @static
+ * @param {String} asn1Hex hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @return {String} r-s concatinated format of ECDSA signature value
+ * @since ecdsa-modified 1.0.3
  */
-function _asnhex_getPosOfNextSibling_AtObj(s, pos) {
-  var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
-  var len = _asnhex_getIntOfL_AtObj(s, pos);
-  return pos1 + len * 2;
-}
+KJUR.crypto.ECDSA.asn1SigToConcatSig = function(asn1Sig) {
+    var pSig = KJUR.crypto.ECDSA.parseSigHexInHexRS(asn1Sig);
+    var hR = pSig.r;
+    var hS = pSig.s;
+
+    if (hR.substr(0, 2) == "00" && (((hR.length / 2) * 8) % (16 * 8)) == 8) 
+	hR = hR.substr(2);
+
+    if (hS.substr(0, 2) == "00" && (((hS.length / 2) * 8) % (16 * 8)) == 8) 
+	hS = hS.substr(2);
+
+    if ((((hR.length / 2) * 8) % (16 * 8)) != 0)
+	throw "unknown ECDSA sig r length error";
+
+    if ((((hS.length / 2) * 8) % (16 * 8)) != 0)
+	throw "unknown ECDSA sig s length error";
+
+    return hR + hS;
+};
 
 /**
- * get array of indexes of child ASN.1 objects
- * @name getPosArrayOfChildren_AtObj
- * @memberOf ASN1HEX
+ * convert hexadecimal concatinated signature to ASN.1 encoded signature
+ * @name concatSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} s hexadecimal string of ASN.1 DER encoded data
- * @param {Number} start string index of ASN.1 object
- * @return {Array of Number} array of indexes for childen of ASN.1 objects
+ * @static
+ * @param {String} concatSig r-s concatinated format of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
  */
-function _asnhex_getPosArrayOfChildren_AtObj(h, pos) {
-  var a = new Array();
-  var p0 = _asnhex_getStartPosOfV_AtObj(h, pos);
-  a.push(p0);
+KJUR.crypto.ECDSA.concatSigToASN1Sig = function(concatSig) {
+    if ((((concatSig.length / 2) * 8) % (16 * 8)) != 0)
+	throw "unknown ECDSA concatinated r-s sig  length error";
 
-  var len = _asnhex_getIntOfL_AtObj(h, pos);
-  var p = p0;
-  var k = 0;
-  while (1) {
-    var pNext = _asnhex_getPosOfNextSibling_AtObj(h, p);
-    if (pNext == null || (pNext - p0  >= (len * 2))) break;
-    if (k >= 200) break;
-
-    a.push(pNext);
-    p = pNext;
-
-    k++;
-  }
-
-  return a;
-}
+    var hR = concatSig.substr(0, concatSig.length / 2);
+    var hS = concatSig.substr(concatSig.length / 2);
+    return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(hR, hS);
+};
 
 /**
- * get string index of nth child object of ASN.1 object refered by h, idx
- * @name getNthChildIndex_AtObj
- * @memberOf ASN1HEX
+ * convert hexadecimal R and S value of signature to ASN.1 encoded signature
+ * @name hexRSSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} h hexadecimal string of ASN.1 DER encoded data
- * @param {Number} idx start string index of ASN.1 object
- * @param {Number} nth for child
- * @return {Number} string index of nth child.
- * @since 1.1
+ * @static
+ * @param {String} hR hexadecimal string of R field of ECDSA signature value
+ * @param {String} hS hexadecimal string of S field of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
  */
-function _asnhex_getNthChildIndex_AtObj(h, idx, nth) {
-  var a = _asnhex_getPosArrayOfChildren_AtObj(h, idx);
-  return a[nth];
-}
-
-// ========== decendant methods ==============================
+KJUR.crypto.ECDSA.hexRSSigToASN1Sig = function(hR, hS) {
+    var biR = new BigInteger(hR, 16);
+    var biS = new BigInteger(hS, 16);
+    return KJUR.crypto.ECDSA.biRSSigToASN1Sig(biR, biS);
+};
 
 /**
- * get string index of nth child object of ASN.1 object refered by h, idx
- * @name getDecendantIndexByNthList
- * @memberOf ASN1HEX
+ * convert R and S BigInteger object of signature to ASN.1 encoded signature
+ * @name biRSSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
  * @function
- * @param {String} h hexadecimal string of ASN.1 DER encoded data
- * @param {Number} currentIndex start string index of ASN.1 object
- * @param {Array of Number} nthList array list of nth
- * @return {Number} string index refered by nthList
- * @since 1.1
+ * @static
+ * @param {BigInteger} biR BigInteger object of R field of ECDSA signature value
+ * @param {BigInteger} biS BIgInteger object of S field of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
  */
-function _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList) {
-  if (nthList.length == 0) {
-    return currentIndex;
-  }
-  var firstNth = nthList.shift();
-  var a = _asnhex_getPosArrayOfChildren_AtObj(h, currentIndex);
-  return _asnhex_getDecendantIndexByNthList(h, a[firstNth], nthList);
-}
+KJUR.crypto.ECDSA.biRSSigToASN1Sig = function(biR, biS) {
+    var derR = new KJUR.asn1.DERInteger({'bigint': biR});
+    var derS = new KJUR.asn1.DERInteger({'bigint': biS});
+    var derSeq = new KJUR.asn1.DERSequence({'array': [derR, derS]});
+    return derSeq.getEncodedHex();
+};
+
+/*! asn1hex-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * asn1hex.js - Hexadecimal represented ASN.1 string library
+ *
+ * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license/
+ *
+ * The above copyright and license notice shall be 
+ * included in all copies or substantial portions of the Software.
+ */
 
 /**
- * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
- * @name getDecendantHexTLVByNthList
- * @memberOf ASN1HEX
- * @function
- * @param {String} h hexadecimal string of ASN.1 DER encoded data
- * @param {Number} currentIndex start string index of ASN.1 object
- * @param {Array of Number} nthList array list of nth
- * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
- * @since 1.1
+ * @fileOverview
+ * @name asn1hex-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version asn1hex 1.1.6 (2015-Jun-11)
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
  */
-function _asnhex_getDecendantHexTLVByNthList(h, currentIndex, nthList) {
-  var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
-  return _asnhex_getHexOfTLV_AtObj(h, idx);
-}
 
-/**
- * get hexadecimal string of ASN.1 V refered by current index and nth index list.
- * @name getDecendantHexVByNthList
- * @memberOf ASN1HEX
- * @function
- * @param {String} h hexadecimal string of ASN.1 DER encoded data
- * @param {Number} currentIndex start string index of ASN.1 object
- * @param {Array of Number} nthList array list of nth
- * @return {Number} hexadecimal string of ASN.1 V refered by nthList
- * @since 1.1
+/*
+ * MEMO:
+ *   f('3082025b02...', 2) ... 82025b ... 3bytes
+ *   f('020100', 2) ... 01 ... 1byte
+ *   f('0203001...', 2) ... 03 ... 1byte
+ *   f('02818003...', 2) ... 8180 ... 2bytes
+ *   f('3080....0000', 2) ... 80 ... -1
+ *
+ *   Requirements:
+ *   - ASN.1 type octet length MUST be 1. 
+ *     (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
  */
-function _asnhex_getDecendantHexVByNthList(h, currentIndex, nthList) {
-  var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
-  return _asnhex_getHexOfV_AtObj(h, idx);
-}
-
-// ========== class definition ==============================
 
 /**
  * ASN.1 DER encoded hexadecimal string utility class
+ * @name ASN1HEX
  * @class ASN.1 DER encoded hexadecimal string utility class
- * @author Kenji Urushima
- * @version 1.1 (09 May 2012)
- * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
- * @since 1.1
+ * @since jsrsasign 1.1
  */
-function ASN1HEX() {
-  return ASN1HEX;
-}
+var intShim = require('jsbn');
 
-ASN1HEX.getByteLengthOfL_AtObj = _asnhex_getByteLengthOfL_AtObj;
-ASN1HEX.getHexOfL_AtObj = _asnhex_getHexOfL_AtObj;
-ASN1HEX.getIntOfL_AtObj = _asnhex_getIntOfL_AtObj;
-ASN1HEX.getStartPosOfV_AtObj = _asnhex_getStartPosOfV_AtObj;
-ASN1HEX.getHexOfV_AtObj = _asnhex_getHexOfV_AtObj;
-ASN1HEX.getHexOfTLV_AtObj = _asnhex_getHexOfTLV_AtObj;
-ASN1HEX.getPosOfNextSibling_AtObj = _asnhex_getPosOfNextSibling_AtObj;
-ASN1HEX.getPosArrayOfChildren_AtObj = _asnhex_getPosArrayOfChildren_AtObj;
-ASN1HEX.getNthChildIndex_AtObj = _asnhex_getNthChildIndex_AtObj;
-ASN1HEX.getDecendantIndexByNthList = _asnhex_getDecendantIndexByNthList;
-ASN1HEX.getDecendantHexVByNthList = _asnhex_getDecendantHexVByNthList;
-ASN1HEX.getDecendantHexTLVByNthList = _asnhex_getDecendantHexTLVByNthList;
-/*! x509-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
+var ASN1HEX = new function() {
+    /**
+     * get byte length for ASN.1 L(length) bytes
+     * @name getByteLengthOfL_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return byte length for ASN.1 L(length) bytes
+     */
+    this.getByteLengthOfL_AtObj = function(s, pos) {
+        if (s.substring(pos + 2, pos + 3) != '8') return 1;
+        var i = parseInt(s.substring(pos + 3, pos + 4));
+        if (i == 0) return -1;          // length octet '80' indefinite length
+        if (0 < i && i < 10) return i + 1;      // including '8?' octet;
+        return -2;                              // malformed format
+    };
+
+    /**
+     * get hexadecimal string for ASN.1 L(length) bytes
+     * @name getHexOfL_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return {String} hexadecimal string for ASN.1 L(length) bytes
+     */
+    this.getHexOfL_AtObj = function(s, pos) {
+        var len = this.getByteLengthOfL_AtObj(s, pos);
+        if (len < 1) return '';
+        return s.substring(pos + 2, pos + 2 + len * 2);
+    };
+
+    //   getting ASN.1 length value at the position 'idx' of
+    //   hexa decimal string 's'.
+    //
+    //   f('3082025b02...', 0) ... 82025b ... ???
+    //   f('020100', 0) ... 01 ... 1
+    //   f('0203001...', 0) ... 03 ... 3
+    //   f('02818003...', 0) ... 8180 ... 128
+    /**
+     * get integer value of ASN.1 length for ASN.1 data
+     * @name getIntOfL_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return ASN.1 L(length) integer value
+     */
+    this.getIntOfL_AtObj = function(s, pos) {
+        var hLength = this.getHexOfL_AtObj(s, pos);
+        if (hLength == '') return -1;
+        var bi;
+        if (parseInt(hLength.substring(0, 1)) < 8) {
+            bi = new BigInteger(hLength, 16);
+        } else {
+            bi = new BigInteger(hLength.substring(2), 16);
+        }
+        return bi.intValue();
+    };
+
+    /**
+     * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
+     * @name getStartPosOfV_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     */
+    this.getStartPosOfV_AtObj = function(s, pos) {
+        var l_len = this.getByteLengthOfL_AtObj(s, pos);
+        if (l_len < 0) return l_len;
+        return pos + (l_len + 1) * 2;
+    };
+
+    /**
+     * get hexadecimal string of ASN.1 V(value)
+     * @name getHexOfV_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return {String} hexadecimal string of ASN.1 value.
+     */
+    this.getHexOfV_AtObj = function(s, pos) {
+        var pos1 = this.getStartPosOfV_AtObj(s, pos);
+        var len = this.getIntOfL_AtObj(s, pos);
+        return s.substring(pos1, pos1 + len * 2);
+    };
+
+    /**
+     * get hexadecimal string of ASN.1 TLV at
+     * @name getHexOfTLV_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return {String} hexadecimal string of ASN.1 TLV.
+     * @since 1.1
+     */
+    this.getHexOfTLV_AtObj = function(s, pos) {
+        var hT = s.substr(pos, 2);
+        var hL = this.getHexOfL_AtObj(s, pos);
+        var hV = this.getHexOfV_AtObj(s, pos);
+        return hT + hL + hV;
+    };
+
+    /**
+     * get next sibling starting index for ASN.1 object string
+     * @name getPosOfNextSibling_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} pos string index
+     * @return next sibling starting index for ASN.1 object string
+     */
+    this.getPosOfNextSibling_AtObj = function(s, pos) {
+        var pos1 = this.getStartPosOfV_AtObj(s, pos);
+        var len = this.getIntOfL_AtObj(s, pos);
+        return pos1 + len * 2;
+    };
+
+    /**
+     * get array of indexes of child ASN.1 objects
+     * @name getPosArrayOfChildren_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} s hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} start string index of ASN.1 object
+     * @return {Array of Number} array of indexes for childen of ASN.1 objects
+     */
+    this.getPosArrayOfChildren_AtObj = function(h, pos) {
+        var a = new Array();
+        var p0 = this.getStartPosOfV_AtObj(h, pos);
+        a.push(p0);
+
+        var len = this.getIntOfL_AtObj(h, pos);
+        var p = p0;
+        var k = 0;
+        while (1) {
+            var pNext = this.getPosOfNextSibling_AtObj(h, p);
+            if (pNext == null || (pNext - p0  >= (len * 2))) break;
+            if (k >= 200) break;
+            
+            a.push(pNext);
+            p = pNext;
+            
+            k++;
+        }
+        
+        return a;
+    };
+
+    /**
+     * get string index of nth child object of ASN.1 object refered by h, idx
+     * @name getNthChildIndex_AtObj
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} h hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} idx start string index of ASN.1 object
+     * @param {Number} nth for child
+     * @return {Number} string index of nth child.
+     * @since 1.1
+     */
+    this.getNthChildIndex_AtObj = function(h, idx, nth) {
+        var a = this.getPosArrayOfChildren_AtObj(h, idx);
+        return a[nth];
+    };
+
+    // ========== decendant methods ==============================
+    /**
+     * get string index of nth child object of ASN.1 object refered by h, idx
+     * @name getDecendantIndexByNthList
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} h hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} currentIndex start string index of ASN.1 object
+     * @param {Array of Number} nthList array list of nth
+     * @return {Number} string index refered by nthList
+     * @since 1.1
+     * @example
+     * The "nthList" is a index list of structured ASN.1 object
+     * reference. Here is a sample structure and "nthList"s which
+     * refers each objects.
+     *
+     * SQUENCE               - 
+     *   SEQUENCE            - [0]
+     *     IA5STRING 000     - [0, 0]
+     *     UTF8STRING 001    - [0, 1]
+     *   SET                 - [1]
+     *     IA5STRING 010     - [1, 0]
+     *     UTF8STRING 011    - [1, 1]
+     */
+    this.getDecendantIndexByNthList = function(h, currentIndex, nthList) {
+        if (nthList.length == 0) {
+            return currentIndex;
+        }
+        var firstNth = nthList.shift();
+        var a = this.getPosArrayOfChildren_AtObj(h, currentIndex);
+        return this.getDecendantIndexByNthList(h, a[firstNth], nthList);
+    };
+
+    /**
+     * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
+     * @name getDecendantHexTLVByNthList
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} h hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} currentIndex start string index of ASN.1 object
+     * @param {Array of Number} nthList array list of nth
+     * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
+     * @since 1.1
+     */
+    this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) {
+        var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
+        return this.getHexOfTLV_AtObj(h, idx);
+    };
+
+    /**
+     * get hexadecimal string of ASN.1 V refered by current index and nth index list.
+     * @name getDecendantHexVByNthList
+     * @memberOf ASN1HEX
+     * @function
+     * @param {String} h hexadecimal string of ASN.1 DER encoded data
+     * @param {Number} currentIndex start string index of ASN.1 object
+     * @param {Array of Number} nthList array list of nth
+     * @return {Number} hexadecimal string of ASN.1 V refered by nthList
+     * @since 1.1
+     */
+    this.getDecendantHexVByNthList = function(h, currentIndex, nthList) {
+        var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
+        return this.getHexOfV_AtObj(h, idx);
+    };
+};
+
+/*
+ * @since asn1hex 1.1.4
  */
-// 
-// x509.js - X509 class to read subject public key from certificate.
-//
-// version: 1.1 (10-May-2012)
-//
-// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
-//
-// This software is licensed under the terms of the MIT License.
-// http://kjur.github.com/jsrsasign/license
-//
-// The above copyright and license notice shall be 
-// included in all copies or substantial portions of the Software.
-// 
-
-// Depends:
-//   base64.js
-//   rsa.js
-//   asn1hex.js
-
-function _x509_pemToBase64(sCertPEM) {
-  var s = sCertPEM;
-  s = s.replace("-----BEGIN CERTIFICATE-----", "");
-  s = s.replace("-----END CERTIFICATE-----", "");
-  s = s.replace(/[ \n]+/g, "");
-  return s;
-}
-
-function _x509_pemToHex(sCertPEM) {
-  var b64Cert = _x509_pemToBase64(sCertPEM);
-  var hCert = b64tohex(b64Cert);
-  return hCert;
-}
-
-function _x509_getHexTbsCertificateFromCert(hCert) {
-  var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
-  return pTbsCert;
-}
-
-// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
-// NOTE: v1 and v3 supported
-function _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert) {
-  var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
-  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert); 
-  if (a.length < 1) return -1;
-  if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
-    if (a.length < 6) return -1;
-    return a[6];
-  } else {
-    if (a.length < 5) return -1;
-    return a[5];
-  }
-}
-
-// NOTE: Without BITSTRING encapsulation.
-// If pInfo is supplied, it is the position in hCert of the SubjectPublicKeyInfo.
-function _x509_getSubjectPublicKeyPosFromCertHex(hCert, pInfo) {
-  if (pInfo == null)
-      pInfo = _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert);
-  if (pInfo == -1) return -1;    
-  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo); 
-  
-  if (a.length != 2) return -1;
-  var pBitString = a[1];
-  if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
-  var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
-
-  if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
-  return pBitStringV + 2;
-}
-
-// If p is supplied, it is the public key position in hCert.
-function _x509_getPublicKeyHexArrayFromCertHex(hCert, p) {
-  if (p == null)
-      p = _x509_getSubjectPublicKeyPosFromCertHex(hCert);
-  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 
-  //var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a[3]); 
-  if(LOG>4){
-	  console.log('a is now');
-	  console.log(a);
-  }
-  
-  //if (a.length != 2) return [];
-  if (a.length < 2) return [];
-
-  var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
-  var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
-  if (hN != null && hE != null) {
-    return [hN, hE];
-  } else {
-    return [];
-  }
-}
-
-function _x509_getPublicKeyHexArrayFromCertPEM(sCertPEM) {
-  var hCert = _x509_pemToHex(sCertPEM);
-  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
-  return a;
-}
-
-// ===== get basic fields from hex =====================================
-/**
- * get hexadecimal string of serialNumber field of certificate.<br/>
- * @name getSerialNumberHex
- * @memberOf X509#
- * @function
- */
-function _x509_getSerialNumberHex() {
-  return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
-}
+ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) {
+    var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
+    if (idx === undefined) {
+        throw "can't find nthList object";
+    }
+    if (checkingTag !== undefined) {
+        if (h.substr(idx, 2) != checkingTag) {
+            throw "checking tag doesn't match: " + 
+                h.substr(idx,2) + "!=" + checkingTag;
+        }
+    }
+    return this.getHexOfV_AtObj(h, idx);
+};
 
 /**
- * get hexadecimal string of issuer field of certificate.<br/>
- * @name getIssuerHex
- * @memberOf X509#
+ * get OID string from hexadecimal encoded value
+ * @name hextooidstr
+ * @memberOf ASN1HEX
  * @function
+ * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value
+ * @return {String} OID string (ex. '1.2.3.4.567')
+ * @since asn1hex 1.1.5
  */
-function _x509_getIssuerHex() {
-  return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
-}
+ASN1HEX.hextooidstr = function(hex) {
+    var zeroPadding = function(s, len) {
+        if (s.length >= len) return s;
+        return new Array(len - s.length + 1).join('0') + s;
+    };
+
+    var a = [];
+
+    // a[0], a[1]
+    var hex0 = hex.substr(0, 2);
+    var i0 = parseInt(hex0, 16);
+    a[0] = new String(Math.floor(i0 / 40));
+    a[1] = new String(i0 % 40);
+
+    // a[2]..a[n]
+   var hex1 = hex.substr(2);
+    var b = [];
+    for (var i = 0; i < hex1.length / 2; i++) {
+    b.push(parseInt(hex1.substr(i * 2, 2), 16));
+    }
+    var c = [];
+    var cbin = "";
+    for (var i = 0; i < b.length; i++) {
+        if (b[i] & 0x80) {
+            cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
+        } else {
+            cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
+            c.push(new String(parseInt(cbin, 2)));
+            cbin = "";
+        }
+    }
+
+    var s = a.join(".");
+    if (c.length > 0) s = s + "." + c.join(".");
+    return s;
+};
 
 /**
- * get string of issuer field of certificate.<br/>
- * @name getIssuerString
- * @memberOf X509#
+ * get string of simple ASN.1 dump from hexadecimal ASN.1 data
+ * @name dump
+ * @memberOf ASN1HEX
  * @function
+ * @param {String} hex hexadecmal string of ASN.1 data
+ * @param {Array} associative array of flags for dump (OPTION)
+ * @param {Number} idx string index for starting dump (OPTION)
+ * @param {String} indent string (OPTION)
+ * @return {String} string of simple ASN.1 dump
+ * @since jsrsasign 4.8.3 asn1hex 1.1.6
+ * @description
+ * This method will get an ASN.1 dump from
+ * hexadecmal string of ASN.1 DER encoded data.
+ * Here are features:
+ * <ul>
+ * <li>ommit long hexadecimal string</li>
+ * <li>dump encapsulated OCTET STRING (good for X.509v3 extensions)</li>
+ * <li>structured/primitive context specific tag support (i.e. [0], [3] ...)</li>
+ * <li>automatic decode for implicit primitive context specific tag 
+ * (good for X.509v3 extension value)
+ *   <ul>
+ *   <li>if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.</li>
+ *   <li>if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag
+ *   value will be encoded as utf8 string</li>
+ *   <li>otherwise it shows as hexadecimal string</li>
+ *   </ul>
+ * </li>
+ * </ul>
+ * @example
+ * // ASN.1 INTEGER
+ * ASN1HEX.dump('0203012345')
+ * &darr;
+ * INTEGER 012345
+ * // ASN.1 Object Identifier
+ * ASN1HEX.dump('06052b0e03021a')
+ * &darr;
+ * ObjectIdentifier sha1 (1 3 14 3 2 26)
+ * // ASN.1 SEQUENCE
+ * ASN1HEX.dump('3006020101020102')
+ * &darr;
+ * SEQUENCE
+ *   INTEGER 01
+ *   INTEGER 02
+ * // ASN.1 DUMP FOR X.509 CERTIFICATE
+ * ASN1HEX.dump(X509.pemToHex(certPEM))
+ * &darr;
+ * SEQUENCE
+ *   SEQUENCE
+ *     [0]
+ *       INTEGER 02
+ *     INTEGER 0c009310d206dbe337553580118ddc87
+ *     SEQUENCE
+ *       ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11)
+ *       NULL
+ *     SEQUENCE
+ *       SET
+ *         SEQUENCE
+ *           ObjectIdentifier countryName (2 5 4 6)
+ *           PrintableString 'US'
+ *             :
  */
-function _x509_getIssuerString() {
-  return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
-}
+ASN1HEX.dump = function(hex, flags, idx, indent) {
+    var _skipLongHex = function(hex, limitNumOctet) {
+	if (hex.length <= limitNumOctet * 2) {
+	    return hex;
+	} else {
+	    var s = hex.substr(0, limitNumOctet) + 
+		    "..(total " + hex.length / 2 + "bytes).." +
+		    hex.substr(hex.length - limitNumOctet, limitNumOctet);
+	    return s;
+	};
+    };
+
+    if (flags === undefined) flags = { "ommit_long_octet": 32 };
+    if (idx === undefined) idx = 0;
+    if (indent === undefined) indent = "";
+    var skipLongHex = flags.ommit_long_octet;
+
+    if (hex.substr(idx, 2) == "01") {
+	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	if (v == "00") {
+	    return indent + "BOOLEAN FALSE\n";
+	} else {
+	    return indent + "BOOLEAN TRUE\n";
+	}
+    }
+    if (hex.substr(idx, 2) == "02") {
+	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n";
+    }
+    if (hex.substr(idx, 2) == "03") {
+	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n";
+    }
+    if (hex.substr(idx, 2) == "04") {
+	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	if (ASN1HEX.isASN1HEX(v)) {
+	    var s = indent + "OCTETSTRING, encapsulates\n";
+	    s = s + ASN1HEX.dump(v, flags, 0, indent + "  ");
+	    return s;
+	} else {
+	    return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n";
+	}
+    }
+    if (hex.substr(idx, 2) == "05") {
+	return indent + "NULL\n";
+    }
+    if (hex.substr(idx, 2) == "06") {
+	var hV = ASN1HEX.getHexOfV_AtObj(hex, idx);
+        var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV);
+        var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
+	var oidSpc = oidDot.replace(/\./g, ' ');
+        if (oidName != '') {
+  	    return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n";
+	} else {
+  	    return indent + "ObjectIdentifier (" + oidSpc + ")\n";
+	}
+    }
+    if (hex.substr(idx, 2) == "0c") {
+	return indent + "UTF8String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
+    }
+    if (hex.substr(idx, 2) == "13") {
+	return indent + "PrintableString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
+    }
+    if (hex.substr(idx, 2) == "14") {
+	return indent + "TeletexString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
+    }
+    if (hex.substr(idx, 2) == "16") {
+	return indent + "IA5String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
+    }
+    if (hex.substr(idx, 2) == "17") {
+	return indent + "UTCTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n";
+    }
+    if (hex.substr(idx, 2) == "18") {
+	return indent + "GeneralizedTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n";
+    }
+    if (hex.substr(idx, 2) == "30") {
+	if (hex.substr(idx, 4) == "3000") {
+	    return indent + "SEQUENCE {}\n";
+	}
+
+	var s = indent + "SEQUENCE\n";
+	var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
+
+	var flagsTemp = flags;
+	
+	if ((aIdx.length == 2 || aIdx.length == 3) &&
+	    hex.substr(aIdx[0], 2) == "06" &&
+	    hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension
+	    var oidHex = ASN1HEX.getHexOfV_AtObj(hex, aIdx[0]);
+	    var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(oidHex);
+	    var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
+
+	    var flagsClone = JSON.parse(JSON.stringify(flags));
+	    flagsClone.x509ExtName = oidName;
+	    flagsTemp = flagsClone;
+	}
+	
+	for (var i = 0; i < aIdx.length; i++) {
+	    s = s + ASN1HEX.dump(hex, flagsTemp, aIdx[i], indent + "  ");
+	}
+	return s;
+    }
+    if (hex.substr(idx, 2) == "31") {
+	var s = indent + "SET\n";
+	var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
+	for (var i = 0; i < aIdx.length; i++) {
+	    s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + "  ");
+	}
+	return s;
+    }
+    var tag = parseInt(hex.substr(idx, 2), 16);
+    if ((tag & 128) != 0) { // context specific 
+	var tagNumber = tag & 31;
+	if ((tag & 32) != 0) { // structured tag
+	    var s = indent + "[" + tagNumber + "]\n";
+	    var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
+	    for (var i = 0; i < aIdx.length; i++) {
+		s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + "  ");
+	    }
+	    return s;
+	} else { // primitive tag
+	    var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
+	    if (v.substr(0, 8) == "68747470") { // http
+		v = hextoutf8(v);
+	    }
+	    if (flags.x509ExtName === "subjectAltName" &&
+		tagNumber == 2) {
+		v = hextoutf8(v);
+	    }
+	    
+	    var s = indent + "[" + tagNumber + "] " + v + "\n";
+	    return s;
+	}
+    }
+    return indent + "UNKNOWN(" + hex.substr(idx, 2) + ") " + ASN1HEX.getHexOfV_AtObj(hex, idx) + "\n";
+};
 
 /**
- * get hexadecimal string of subject field of certificate.<br/>
- * @name getSubjectHex
- * @memberOf X509#
+ * check wheather the string is ASN.1 hexadecimal string or not
+ * @name isASN1HEX
+ * @memberOf ASN1HEX
  * @function
+ * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not
+ * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false
+ * @since jsrsasign 4.8.3 asn1hex 1.1.6
+ * @description
+ * This method checks wheather the argument 'hex' is a hexadecimal string of
+ * ASN.1 data or not.
+ * @example
+ * ASN1HEX.isASN1HEX('0203012345') &rarr; true // PROPER ASN.1 INTEGER
+ * ASN1HEX.isASN1HEX('0203012345ff') &rarr; false // TOO LONG VALUE
+ * ASN1HEX.isASN1HEX('02030123') &rarr; false // TOO SHORT VALUE
+ * ASN1HEX.isASN1HEX('fa3bcd') &rarr; false // WRONG FOR ASN.1
  */
-function _x509_getSubjectHex() {
-  return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
-}
+ASN1HEX.isASN1HEX = function(hex) {
+    if (hex.length % 2 == 1) return false;
+
+    var intL = ASN1HEX.getIntOfL_AtObj(hex, 0);
+    var tV = hex.substr(0, 2);
+    var lV = ASN1HEX.getHexOfL_AtObj(hex, 0);
+    var hVLength = hex.length - tV.length - lV.length;
+    if (hVLength == intL * 2) return true;
+
+    return false;
+};
+
+exports.ASN1HEX = ASN1HEX;
+module.exports = exports;
+/*! x509-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/* 
+ * x509.js - X509 class to read subject public key from certificate.
+ *
+ * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * http://kjur.github.com/jsrsasign/license
+ *
+ * The above copyright and license notice shall be 
+ * included in all copies or substantial portions of the Software.
+ */
 
 /**
- * get string of subject field of certificate.<br/>
- * @name getSubjectString
- * @memberOf X509#
- * @function
+ * @fileOverview
+ * @name x509-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version x509 1.1.6 (2015-May-20)
+ * @since jsrsasign 1.x.x
+ * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
  */
-function _x509_getSubjectString() {
-  return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
-}
 
-/**
- * get notBefore field string of certificate.<br/>
- * @name getNotBefore
- * @memberOf X509#
- * @function
+/*
+ * Depends:
+ *   base64.js
+ *   rsa.js
+ *   asn1hex.js
  */
-function _x509_getNotBefore() {
-  var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
-  s = s.replace(/(..)/g, "%$1");
-  s = decodeURIComponent(s);
-  return s;
-}
-
-/**
- * get notAfter field string of certificate.<br/>
- * @name getNotAfter
- * @memberOf X509#
- * @function
- */
-function _x509_getNotAfter() {
-  var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
-  s = s.replace(/(..)/g, "%$1");
-  s = decodeURIComponent(s);
-  return s;
-}
-
-// ===== read certificate =====================================
-
-_x509_DN_ATTRHEX = {
-    "0603550406": "C",
-    "060355040a": "O",
-    "060355040b": "OU",
-    "0603550403": "CN",
-    "0603550405": "SN",
-    "0603550408": "ST",
-    "0603550407": "L" };
-
-function _x509_hex2dn(hDN) {
-  var s = "";
-  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
-  for (var i = 0; i < a.length; i++) {
-    var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
-    s = s + "/" + _x509_hex2rdn(hRDN);
-  }
-  return s;
-}
-
-function _x509_hex2rdn(hRDN) {
-    var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
-    var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
-    var type = "";
-    try { type = _x509_DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
-    hValue = hValue.replace(/(..)/g, "%$1");
-    var value = decodeURIComponent(hValue);
-    return type + "=" + value;
-}
-
-// ===== read certificate =====================================
-
-
-/**
- * read PEM formatted X.509 certificate from string.<br/>
- * @name readCertPEM
- * @memberOf X509#
- * @function
- * @param {String} sCertPEM string for PEM formatted X.509 certificate
- */
-function _x509_readCertPEM(sCertPEM) {
-  var hCert = _x509_pemToHex(sCertPEM);
-  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
-  if(LOG>4){
-	  console.log('HEX VALUE IS ' + hCert);
-	  console.log('type of a' + typeof a);
-	  console.log('a VALUE IS ');
-	  console.log(a);
-	  console.log('a[0] VALUE IS ' + a[0]);
-	  console.log('a[1] VALUE IS ' + a[1]);
-  }
-  var rsa = new RSAKey();
-  rsa.setPublic(a[0], a[1]);
-  this.subjectPublicKeyRSA = rsa;
-  this.subjectPublicKeyRSA_hN = a[0];
-  this.subjectPublicKeyRSA_hE = a[1];
-  this.hex = hCert;
-}
-
-/**
- * read hex formatted X.509 certificate from string.
- * @name readCertHex
- * @memberOf X509#
- * @function
- * @param {String} hCert string for hex formatted X.509 certificate
- */
-function _x509_readCertHex(hCert) {
-  hCert = hCert.toLowerCase();
-  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
-  var rsa = new RSAKey();
-  rsa.setPublic(a[0], a[1]);
-  this.subjectPublicKeyRSA = rsa;
-  this.subjectPublicKeyRSA_hN = a[0];
-  this.subjectPublicKeyRSA_hE = a[1];
-  this.hex = hCert;
-}
-
-function _x509_readCertPEMWithoutRSAInit(sCertPEM) {
-  var hCert = _x509_pemToHex(sCertPEM);
-  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
-  this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
-  this.subjectPublicKeyRSA_hN = a[0];
-  this.subjectPublicKeyRSA_hE = a[1];
-  this.hex = hCert;
-}
 
 /**
  * X.509 certificate class.<br/>
@@ -6364,24 +5348,698 @@
  * @version 1.0.1 (08 May 2012)
  * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
  */
+
+var b64tohex = require('./base64.js').b64tohex;
+var RSAKey = require('./rsa.js').RSAKey;
+var ASN1HEX = require('./asn1hex-1.1.js').ASN1HEX;
+
 function X509() {
-  this.subjectPublicKeyRSA = null;
-  this.subjectPublicKeyRSA_hN = null;
-  this.subjectPublicKeyRSA_hE = null;
-  this.hex = null;
-}
+    this.subjectPublicKeyRSA = null;
+    this.subjectPublicKeyRSA_hN = null;
+    this.subjectPublicKeyRSA_hE = null;
+    this.hex = null;
 
-X509.prototype.readCertPEM = _x509_readCertPEM;
-X509.prototype.readCertHex = _x509_readCertHex;
-X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
-X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
-X509.prototype.getIssuerHex = _x509_getIssuerHex;
-X509.prototype.getSubjectHex = _x509_getSubjectHex;
-X509.prototype.getIssuerString = _x509_getIssuerString;
-X509.prototype.getSubjectString = _x509_getSubjectString;
-X509.prototype.getNotBefore = _x509_getNotBefore;
-X509.prototype.getNotAfter = _x509_getNotAfter;
+    // ===== get basic fields from hex =====================================
 
+    /**
+     * get hexadecimal string of serialNumber field of certificate.<br/>
+     * @name getSerialNumberHex
+     * @memberOf X509#
+     * @function
+     */
+    this.getSerialNumberHex = function() {
+        return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
+    };
+
+    /**
+     * get hexadecimal string of issuer field TLV of certificate.<br/>
+     * @name getIssuerHex
+     * @memberOf X509#
+     * @function
+     */
+    this.getIssuerHex = function() {
+        return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
+    };
+
+    /**
+     * get string of issuer field of certificate.<br/>
+     * @name getIssuerString
+     * @memberOf X509#
+     * @function
+     */
+    this.getIssuerString = function() {
+        return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
+    };
+
+    /**
+     * get hexadecimal string of subject field of certificate.<br/>
+     * @name getSubjectHex
+     * @memberOf X509#
+     * @function
+     */
+    this.getSubjectHex = function() {
+        return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
+    };
+
+    /**
+     * get string of subject field of certificate.<br/>
+     * @name getSubjectString
+     * @memberOf X509#
+     * @function
+     */
+    this.getSubjectString = function() {
+        return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
+    };
+
+    /**
+     * get notBefore field string of certificate.<br/>
+     * @name getNotBefore
+     * @memberOf X509#
+     * @function
+     */
+    this.getNotBefore = function() {
+        var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
+        s = s.replace(/(..)/g, "%$1");
+        s = decodeURIComponent(s);
+        return s;
+    };
+
+    /**
+     * get notAfter field string of certificate.<br/>
+     * @name getNotAfter
+     * @memberOf X509#
+     * @function
+     */
+    this.getNotAfter = function() {
+        var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
+        s = s.replace(/(..)/g, "%$1");
+        s = decodeURIComponent(s);
+        return s;
+    };
+
+    // ===== read certificate public key ==========================
+
+    // ===== read certificate =====================================
+    /**
+     * read PEM formatted X.509 certificate from string.<br/>
+     * @name readCertPEM
+     * @memberOf X509#
+     * @function
+     * @param {String} sCertPEM string for PEM formatted X.509 certificate
+     */
+    this.readCertPEM = function(sCertPEM) {
+        var hCert = X509.pemToHex(sCertPEM);
+        var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
+        var rsa = new RSAKey();
+        rsa.setPublic(a[0], a[1]);
+        this.subjectPublicKeyRSA = rsa;
+        this.subjectPublicKeyRSA_hN = a[0];
+        this.subjectPublicKeyRSA_hE = a[1];
+        this.hex = hCert;
+    };
+
+    this.readCertPEMWithoutRSAInit = function(sCertPEM) {
+        var hCert = X509.pemToHex(sCertPEM);
+        var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
+        this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
+        this.subjectPublicKeyRSA_hN = a[0];
+        this.subjectPublicKeyRSA_hE = a[1];
+        this.hex = hCert;
+    };
+};
+
+X509.pemToBase64 = function(sCertPEM) {
+    var s = sCertPEM;
+    s = s.replace("-----BEGIN CERTIFICATE-----", "");
+    s = s.replace("-----END CERTIFICATE-----", "");
+    s = s.replace(/[ \n]+/g, "");
+    return s;
+};
+
+X509.pemToHex = function(sCertPEM) {
+    var b64Cert = X509.pemToBase64(sCertPEM);
+    var hCert = b64tohex(b64Cert);
+    return hCert;
+};
+
+// NOTE: Without BITSTRING encapsulation.
+X509.getSubjectPublicKeyPosFromCertHex = function(hCert) {
+    var pInfo = X509.getSubjectPublicKeyInfoPosFromCertHex(hCert);
+    if (pInfo == -1) return -1;    
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo); 
+    if (a.length != 2) return -1;
+    var pBitString = a[1];
+    if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
+    var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
+    
+    if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
+    return pBitStringV + 2;
+};
+
+// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
+// NOTE: v1 and v3 supported
+X509.getSubjectPublicKeyInfoPosFromCertHex = function(hCert) {
+    var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert); 
+    if (a.length < 1) return -1;
+    if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
+        if (a.length < 6) return -1;
+        return a[6];
+    } else {
+        if (a.length < 5) return -1;
+        return a[5];
+    }
+};
+
+X509.getPublicKeyHexArrayFromCertHex = function(hCert) {
+    var p = X509.getSubjectPublicKeyPosFromCertHex(hCert);
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 
+    if (a.length != 2) return [];
+    var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
+    var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
+    if (hN != null && hE != null) {
+        return [hN, hE];
+    } else {
+        return [];
+    }
+};
+
+X509.getHexTbsCertificateFromCert = function(hCert) {
+    var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
+    return pTbsCert;
+};
+
+X509.getPublicKeyHexArrayFromCertPEM = function(sCertPEM) {
+    var hCert = X509.pemToHex(sCertPEM);
+    var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
+    return a;
+};
+
+X509.hex2dn = function(hDN) {
+    var s = "";
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
+    for (var i = 0; i < a.length; i++) {
+        var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
+        s = s + "/" + X509.hex2rdn(hRDN);
+    }
+    return s;
+};
+
+X509.hex2rdn = function(hRDN) {
+    var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
+    var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
+    var type = "";
+    try { type = X509.DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
+    hValue = hValue.replace(/(..)/g, "%$1");
+    var value = decodeURIComponent(hValue);
+    return type + "=" + value;
+};
+
+X509.DN_ATTRHEX = {
+    "0603550406": "C",
+    "060355040a": "O",
+    "060355040b": "OU",
+    "0603550403": "CN",
+    "0603550405": "SN",
+    "0603550408": "ST",
+    "0603550407": "L"
+};
+
+/**
+ * get RSAKey/ECDSA public key object from PEM certificate string
+ * @name getPublicKeyFromCertPEM
+ * @memberOf X509
+ * @function
+ * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
+ * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
+ * @since x509 1.1.1
+ * @description
+ * NOTE: DSA is also supported since x509 1.1.2.
+ */
+X509.getPublicKeyFromCertPEM = function(sCertPEM) {
+    var info = X509.getPublicKeyInfoPropOfCertPEM(sCertPEM);
+
+    if (info.algoid == "2a864886f70d010101") { // RSA
+        var aRSA = KEYUTIL.parsePublicRawRSAKeyHex(info.keyhex);
+        var key = new RSAKey();
+        key.setPublic(aRSA.n, aRSA.e);
+        return key;
+    } else if (info.algoid == "2a8648ce3d0201") { // ECC
+        var curveName = KJUR.crypto.OID.oidhex2name[info.algparam];
+        var key = new KJUR.crypto.ECDSA({'curve': curveName, 'info': info.keyhex});
+        key.setPublicKeyHex(info.keyhex);
+        return key;
+    } else if (info.algoid == "2a8648ce380401") { // DSA 1.2.840.10040.4.1
+        var p = ASN1HEX.getVbyList(info.algparam, 0, [0], "02");
+        var q = ASN1HEX.getVbyList(info.algparam, 0, [1], "02");
+        var g = ASN1HEX.getVbyList(info.algparam, 0, [2], "02");
+        var y = ASN1HEX.getHexOfV_AtObj(info.keyhex, 0);
+        y = y.substr(2);
+        var key = new KJUR.crypto.DSA();
+        key.setPublic(new BigInteger(p, 16),
+                      new BigInteger(q, 16),
+                      new BigInteger(g, 16),
+                      new BigInteger(y, 16));
+        return key;
+    } else {
+        throw "unsupported key";
+    }
+};
+
+/**
+ * get public key information from PEM certificate
+ * @name getPublicKeyInfoPropOfCertPEM
+ * @memberOf X509
+ * @function
+ * @param {String} sCertPEM string of PEM formatted certificate
+ * @return {Hash} hash of information for public key
+ * @since x509 1.1.1
+ * @description
+ * Resulted associative array has following properties:
+ * <ul>
+ * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li>
+ * <li>algparam - hexadecimal string of OID of ECC curve name or null</li>
+ * <li>keyhex - hexadecimal string of key in the certificate</li>
+ * </ul>
+ * @since x509 1.1.1
+ */
+X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
+    var result = {};
+    result.algparam = null;
+    var hCert = X509.pemToHex(sCertPEM);
+
+    // 1. Certificate ASN.1
+    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
+    if (a1.length != 3)
+        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
+
+    // 2. tbsCertificate
+    if (hCert.substr(a1[0], 2) != "30")
+        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
+
+    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
+
+    // 3. subjectPublicKeyInfo
+    if (a2.length < 7)
+        throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
+
+    var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[6]); 
+
+    if (a3.length != 2)
+        throw "malformed X.509 certificate PEM (code:004)"; // not AlgId and PubKey
+
+    // 4. AlgId
+    var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]); 
+
+    if (a4.length != 2)
+        throw "malformed X.509 certificate PEM (code:005)"; // not 2 item in AlgId
+
+    result.algoid = ASN1HEX.getHexOfV_AtObj(hCert, a4[0]);
+
+    if (hCert.substr(a4[1], 2) == "06") { // EC
+        result.algparam = ASN1HEX.getHexOfV_AtObj(hCert, a4[1]);
+    } else if (hCert.substr(a4[1], 2) == "30") { // DSA
+        result.algparam = ASN1HEX.getHexOfTLV_AtObj(hCert, a4[1]);
+    }
+
+    // 5. Public Key Hex
+    if (hCert.substr(a3[1], 2) != "03")
+        throw "malformed X.509 certificate PEM (code:006)"; // not bitstring
+
+    var unusedBitAndKeyHex = ASN1HEX.getHexOfV_AtObj(hCert, a3[1]);
+    result.keyhex = unusedBitAndKeyHex.substr(2);
+
+    return result;
+};
+
+/**
+ * get position of subjectPublicKeyInfo field from HEX certificate
+ * @name getPublicKeyInfoPosOfCertHEX
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of certificate
+ * @return {Integer} position in hexadecimal string
+ * @since x509 1.1.4
+ * @description
+ * get position for SubjectPublicKeyInfo field in the hexadecimal string of
+ * certificate.
+ */
+X509.getPublicKeyInfoPosOfCertHEX = function(hCert) {
+    // 1. Certificate ASN.1
+    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
+    if (a1.length != 3)
+        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
+
+    // 2. tbsCertificate
+    if (hCert.substr(a1[0], 2) != "30")
+        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
+
+    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
+
+    // 3. subjectPublicKeyInfo
+    if (a2.length < 7)
+        throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
+    
+    return a2[6];
+};
+
+/**
+ * get array of X.509 V3 extension value information in hex string of certificate
+ * @name getV3ExtInfoListOfCertHex
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @return {Array} array of result object by {@link X509.getV3ExtInfoListOfCertHex}
+ * @since x509 1.1.5
+ * @description
+ * This method will get all extension information of a X.509 certificate.
+ * Items of resulting array has following properties:
+ * <ul>
+ * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li>
+ * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li>
+ * <li>critical - critical flag value for this extension</li>
+ * <li>posV - index of ASN.1 TLV for the extension value.
+ * This is a position of a content of ENCAPSULATED OCTET STRING.</li>
+ * </ul>
+ * @example
+ * hCert = X509.pemToHex(certGithubPEM);
+ * a = X509.getV3ExtInfoListOfCertHex(hCert);
+ * // Then a will be an array of like following:
+ * [{posTLV: 1952, oid: "2.5.29.35", critical: false, posV: 1968},
+ *  {posTLV: 1974, oid: "2.5.29.19", critical: true, posV: 1986}, ...]
+ */
+X509.getV3ExtInfoListOfCertHex = function(hCert) {
+    // 1. Certificate ASN.1
+    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
+    if (a1.length != 3)
+        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
+
+    // 2. tbsCertificate
+    if (hCert.substr(a1[0], 2) != "30")
+        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
+
+    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
+
+    // 3. v3Extension EXPLICIT Tag [3]
+    // ver, seri, alg, iss, validity, subj, spki, (iui,) (sui,) ext
+    if (a2.length < 8)
+        throw "malformed X.509 certificate PEM (code:003)"; // tbsCert num field too short
+
+    if (hCert.substr(a2[7], 2) != "a3")
+        throw "malformed X.509 certificate PEM (code:004)"; // not [3] tag
+
+    var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[7]);
+    if (a3.length != 1)
+        throw "malformed X.509 certificate PEM (code:005)"; // [3]tag numChild!=1
+
+    // 4. v3Extension SEQUENCE
+    if (hCert.substr(a3[0], 2) != "30")
+        throw "malformed X.509 certificate PEM (code:006)"; // not SEQ
+
+    var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]);
+
+    // 5. v3Extension item position
+    var numExt = a4.length;
+    var aInfo = new Array(numExt);
+    for (var i = 0; i < numExt; i++) {
+	aInfo[i] = X509.getV3ExtItemInfo_AtObj(hCert, a4[i]);
+    }
+    return aInfo;
+};
+
+/**
+ * get X.509 V3 extension value information at the specified position
+ * @name getV3ExtItemInfo_AtObj
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @param {Integer} pos index of hexadecimal string for the extension
+ * @return {Object} properties for the extension
+ * @since x509 1.1.5
+ * @description
+ * This method will get some information of a X.509 V extension 
+ * which is referred by an index of hexadecimal string of X.509 
+ * certificate. 
+ * Resulting object has following properties:
+ * <ul>
+ * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li>
+ * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li>
+ * <li>critical - critical flag value for this extension</li>
+ * <li>posV - index of ASN.1 TLV for the extension value.
+ * This is a position of a content of ENCAPSULATED OCTET STRING.</li>
+ * </ul>
+ * This method is used by {@link X509.getV3ExtInfoListOfCertHex} internally.
+ */
+X509.getV3ExtItemInfo_AtObj = function(hCert, pos) {
+    var info = {};
+
+    // posTLV - extension TLV
+    info.posTLV = pos;
+
+    var a  = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos);
+    if (a.length != 2 && a.length != 3)
+        throw "malformed X.509v3 Ext (code:001)"; // oid,(critical,)val
+
+    // oid - extension OID
+    if (hCert.substr(a[0], 2) != "06")
+        throw "malformed X.509v3 Ext (code:002)"; // not OID "06"
+    var valueHex = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
+    info.oid = ASN1HEX.hextooidstr(valueHex); 
+
+    // critical - extension critical flag
+    info.critical = false; // critical false by default
+    if (a.length == 3) info.critical = true;
+
+    // posV - content TLV position of encapsulated
+    //        octet string of V3 extension value.
+    var posExtV = a[a.length - 1];
+    if (hCert.substr(posExtV, 2) != "04")
+        throw "malformed X.509v3 Ext (code:003)"; // not EncapOctet "04"
+    info.posV = ASN1HEX.getStartPosOfV_AtObj(hCert, posExtV);
+    
+    return info;
+};
+
+/**
+ * get X.509 V3 extension value ASN.1 TLV for specified oid or name
+ * @name getHexOfTLV_V3ExtValue
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
+ * @return {String} hexadecimal string of extension ASN.1 TLV
+ * @since x509 1.1.6
+ * @description
+ * This method will get X.509v3 extension value of ASN.1 TLV
+ * which is specifyed by extension name or oid. 
+ * @example
+ * hExtValue = X509.getHexOfTLV_V3ExtValue(hCert, "keyUsage");
+ * // hExtValue will be such like '030205a0'.
+ */
+X509.getHexOfTLV_V3ExtValue = function(hCert, oidOrName) {
+    var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName);
+    if (pos == -1) return '';
+    return ASN1HEX.getHexOfTLV_AtObj(hCert, pos);
+};
+
+/**
+ * get X.509 V3 extension value ASN.1 V for specified oid or name
+ * @name getHexOfV_V3ExtValue
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
+ * @return {String} hexadecimal string of extension ASN.1 TLV
+ * @since x509 1.1.6
+ * @description
+ * This method will get X.509v3 extension value of ASN.1 value
+ * which is specifyed by extension name or oid. 
+ * If there is no such extension in the certificate,
+ * it returns empty string (i.e. '').
+ * Available extension names and oids are defined
+ * in the {@link KJUR.asn1.x509.OID} class.
+ * @example
+ * hExtValue = X509.getHexOfV_V3ExtValue(hCert, "keyUsage");
+ * // hExtValue will be such like '05a0'.
+ */
+X509.getHexOfV_V3ExtValue = function(hCert, oidOrName) {
+    var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName);
+    if (pos == -1) return '';
+    return ASN1HEX.getHexOfV_AtObj(hCert, pos);
+};
+
+/**
+ * get index in the certificate hexa string for specified oid or name specified extension
+ * @name getPosOfTLV_V3ExtValue
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
+ * @return {Integer} index in the hexadecimal string of certficate for specified extension
+ * @since x509 1.1.6
+ * @description
+ * This method will get X.509v3 extension value of ASN.1 V(value)
+ * which is specifyed by extension name or oid. 
+ * If there is no such extension in the certificate,
+ * it returns empty string (i.e. '').
+ * Available extension names and oids are defined
+ * in the {@link KJUR.asn1.x509.OID} class.
+ * @example
+ * idx = X509.getPosOfV_V3ExtValue(hCert, "keyUsage");
+ * // The 'idx' will be index in the string for keyUsage value ASN.1 TLV.
+ */
+X509.getPosOfTLV_V3ExtValue = function(hCert, oidOrName) {
+    var oid = oidOrName;
+    if (! oidOrName.match(/^[0-9.]+$/)) oid = KJUR.asn1.x509.OID.name2oid(oidOrName);
+    if (oid == '') return -1;
+
+    var infoList = X509.getV3ExtInfoListOfCertHex(hCert);
+    for (var i = 0; i < infoList.length; i++) {
+	var info = infoList[i];
+	if (info.oid == oid) return info.posV;
+    }
+    return -1;
+};
+
+X509.KEYUSAGE_NAME = [
+    "digitalSignature",
+    "nonRepudiation",
+    "keyEncipherment",
+    "dataEncipherment",
+    "keyAgreement",
+    "keyCertSign",
+    "cRLSign",
+    "encipherOnly",
+    "decipherOnly"
+];
+
+/**
+ * get KeyUsage extension value as binary string in the certificate
+ * @name getExtKeyUsageBin
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @return {String} binary string of key usage bits (ex. '101')
+ * @since x509 1.1.6
+ * @description
+ * This method will get key usage extension value
+ * as binary string such like '101'.
+ * Key usage bits definition is in the RFC 5280.
+ * If there is no key usage extension in the certificate,
+ * it returns empty string (i.e. '').
+ * @example
+ * bKeyUsage = X509.getExtKeyUsageBin(hCert);
+ * // bKeyUsage will be such like '101'.
+ * // 1 - digitalSignature 
+ * // 0 - nonRepudiation
+ * // 1 - keyEncipherment
+ */
+X509.getExtKeyUsageBin = function(hCert) {
+    var hKeyUsage = X509.getHexOfV_V3ExtValue(hCert, "keyUsage");
+    if (hKeyUsage == '') return '';
+    if (hKeyUsage.length % 2 != 0 || hKeyUsage.length <= 2)
+	throw "malformed key usage value";
+    var unusedBits = parseInt(hKeyUsage.substr(0, 2));
+    var bKeyUsage = parseInt(hKeyUsage.substr(2), 16).toString(2);
+    return bKeyUsage.substr(0, bKeyUsage.length - unusedBits);
+};
+
+/**
+ * get KeyUsage extension value as names in the certificate
+ * @name getExtKeyUsageString
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @return {String} comma separated string of key usage
+ * @since x509 1.1.6
+ * @description
+ * This method will get key usage extension value
+ * as comma separated string of usage names.
+ * If there is no key usage extension in the certificate,
+ * it returns empty string (i.e. '').
+ * @example
+ * sKeyUsage = X509.getExtKeyUsageString(hCert);
+ * // sKeyUsage will be such like 'digitalSignature,keyEncipherment'.
+ */
+X509.getExtKeyUsageString = function(hCert) {
+    var bKeyUsage = X509.getExtKeyUsageBin(hCert);
+    var a = new Array();
+    for (var i = 0; i < bKeyUsage.length; i++) {
+	if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]);
+    }
+    return a.join(",");
+};
+
+/**
+ * get AuthorityInfoAccess extension value in the certificate as associative array
+ * @name getExtAIAInfo
+ * @memberOf X509
+ * @function
+ * @param {String} hCert hexadecimal string of X.509 certificate binary
+ * @return {Object} associative array of AIA extension properties
+ * @since x509 1.1.6
+ * @description
+ * This method will get authority info access value
+ * as associate array which has following properties:
+ * <ul>
+ * <li>ocsp - array of string for OCSP responder URL</li>
+ * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li>
+ * </ul>
+ * If there is no key usage extension in the certificate,
+ * it returns null;
+ * @example
+ * oAIA = X509.getExtAIAInfo(hCert);
+ * // result will be such like:
+ * // oAIA.ocsp = ["http://ocsp.foo.com"];
+ * // oAIA.caissuer = ["http://rep.foo.com/aaa.p8m"];
+ */
+X509.getExtAIAInfo = function(hCert) {
+    var result = {};
+    result.ocsp = [];
+    result.caissuer = [];
+    var pos1 = X509.getPosOfTLV_V3ExtValue(hCert, "authorityInfoAccess");
+    if (pos1 == -1) return null;
+    if (hCert.substr(pos1, 2) != "30") // extnValue SEQUENCE
+	throw "malformed AIA Extn Value";
+    
+    var posAccDescList = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos1);
+    for (var i = 0; i < posAccDescList.length; i++) {
+	var p = posAccDescList[i];
+	var posAccDescChild = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
+	if (posAccDescChild.length != 2)
+	    throw "malformed AccessDescription of AIA Extn";
+	var pOID = posAccDescChild[0];
+	var pName = posAccDescChild[1];
+	if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073001") {
+	    if (hCert.substr(pName, 2) == "86") {
+		result.ocsp.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName)));
+	    }
+	}
+	if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073002") {
+	    if (hCert.substr(pName, 2) == "86") {
+		result.caissuer.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName)));
+	    }
+	}
+    }
+    return result;
+};
+
+/*
+  X509.prototype.readCertPEM = _x509_readCertPEM;
+  X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
+  X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
+  X509.prototype.getIssuerHex = _x509_getIssuerHex;
+  X509.prototype.getSubjectHex = _x509_getSubjectHex;
+  X509.prototype.getIssuerString = _x509_getIssuerString;
+  X509.prototype.getSubjectString = _x509_getSubjectString;
+  X509.prototype.getNotBefore = _x509_getNotBefore;
+  X509.prototype.getNotAfter = _x509_getNotAfter;
+*/
+
+exports.X509 = X509;
+module.exports = exports;
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
 // Copyright (c) 2005  Tom Wu
 // All Rights Reserved.
 // See "LICENSE" for details.
@@ -6396,7 +6054,7 @@
 var j_lm = ((canary&0xffffff)==0xefcafe);
 
 // (public) Constructor
-function BigInteger(a,b,c) {
+var BigInteger = function BigInteger(a,b,c) {
   if(a != null)
     if("number" == typeof a) this.fromNumber(a,b,c);
     else if(b == null && "string" != typeof a) this.fromString(a,256);
@@ -6502,7 +6160,7 @@
   this.t = 1;
   this.s = (x<0)?-1:0;
   if(x > 0) this[0] = x;
-  else if(x < -1) this[0] = x+DV;
+  else if(x < -1) this[0] = x+this.DV;
   else this.t = 0;
 }
 
@@ -6596,7 +6254,7 @@
   if(r != 0) return r;
   var i = this.t;
   r = i-a.t;
-  if(r != 0) return r;
+  if(r != 0) return (this.s<0)?-r:r;
   while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
   return 0;
 }
@@ -6941,6 +6599,8 @@
 // "constants"
 BigInteger.ZERO = nbv(0);
 BigInteger.ONE = nbv(1);
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
 // Copyright (c) 2005-2009  Tom Wu
 // All Rights Reserved.
 // See "LICENSE" for details.
@@ -6948,6 +6608,7 @@
 // Extended JavaScript BN functions, required for RSA private ops.
 
 // Version 1.1: new BigInteger("0", 10) returns "proper" zero
+// Version 1.2: square() API, isProbablePrime fix
 
 // (public)
 function bnClone() { var r = nbi(); this.copyTo(r); return r; }
@@ -7233,6 +6894,9 @@
 // (public) this * a
 function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
 
+// (public) this^2
+function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
+
 // (public) this / a
 function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
 
@@ -7485,7 +7149,7 @@
   if(d.signum() < 0) return d.add(m); else return d;
 }
 
-var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
+var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
 var lplim = (1<<26)/lowprimes[lowprimes.length-1];
 
 // (public) test primality with certainty >= 1-.5^t
@@ -7517,7 +7181,8 @@
   if(t > lowprimes.length) t = lowprimes.length;
   var a = nbi();
   for(var i = 0; i < t; ++i) {
-    a.fromInt(lowprimes[i]);
+    //Pick bases at random, instead of starting at 2
+    a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
     var y = a.modPow(r,this);
     if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
       var j = 1;
@@ -7581,6 +7246,9 @@
 BigInteger.prototype.gcd = bnGCD;
 BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
 
+// JSBN-specific extension
+BigInteger.prototype.square = bnSquare;
+
 // BigInteger interfaces not implemented in jsbn:
 
 // BigInteger(int signum, byte[] magnitude)
@@ -7589,623 +7257,30318 @@
 // int hashCode()
 // long longValue()
 // static BigInteger valueOf(long val)
+
+exports.BigInteger = BigInteger;
+module.exports = exports;
 /**
- * @author: Meki Cherkaoui, Jeff Thompson, Wentao Shang
- * See COPYING for copyright and distribution information.
- * This class represents the top-level object for communicating with an NDN host.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
  */
 
-var LOG = 0;
+/** @ignore */
+var ASN1HEX = require('../contrib/securityLib/asn1hex-1.1.js').ASN1HEX /** @ignore */
+var KJUR = require('../contrib/securityLib/crypto-1.0.js').KJUR /** @ignore */
+var RSAKey = require('../contrib/securityLib/rsasign-1.2.js').RSAKey /** @ignore */
+var b64tohex = require('../contrib/securityLib/base64.js').b64tohex
 
-/**
- * settings is an associative array with the following defaults:
- * {
- *   getTransport: function() { return new WebSocketTransport(); },
- *   getHostAndPort: transport.defaultGetHostAndPort,
- *   host: null, // If null, use getHostAndPort when connecting.
- *   port: 9696,
- *   onopen: function() { if (LOG > 3) console.log("NDN connection established."); },
- *   onclose: function() { if (LOG > 3) console.log("NDN connection closed."); },
- *   verify: true // If false, don't verify and call upcall with Closure.UPCALL_CONTENT_UNVERIFIED.
- * }
- *
- * getHostAndPort is a function, on each call it returns a new { host: host, port: port } or
- *   null if there are no more hosts.
- *
- * This throws an exception if NDN.supported is false.
- */
-var NDN = function NDN(settings) {
-    if (!NDN.supported)
-        throw new Error("The necessary JavaScript support is not available on this platform.");
+// Library namespace
+/** @ignore */
+var ndn = ndn || {};
 
-    settings = (settings || {});
-    var getTransport = (settings.getTransport || function() { return new WebSocketTransport(); });
-    this.transport = getTransport();
-    this.getHostAndPort = (settings.getHostAndPort || this.transport.defaultGetHostAndPort);
-	this.host = (settings.host !== undefined ? settings.host : null);
-	this.port = (settings.port || 9696);
-    this.readyStatus = NDN.UNOPEN;
-    this.verify = (settings.verify !== undefined ? settings.verify : true);
-    // Event handler
-    this.onopen = (settings.onopen || function() { if (LOG > 3) console.log("NDN connection established."); });
-    this.onclose = (settings.onclose || function() { if (LOG > 3) console.log("NDN connection closed."); });
-	this.ndndid = null;
+/** @ignore */
+var exports = ndn;
+
+// Factory method to create hasher objects
+exports.createHash = function(alg)
+{
+  if (alg != 'sha256')
+    throw new Error('createHash: unsupported algorithm.');
+
+  var obj = {};
+
+  obj.md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "cryptojs"});
+
+  obj.update = function(buf) {
+    this.md.updateHex(buf.toString('hex'));
+  };
+
+  obj.digest = function(encoding) {
+    var hexDigest = this.md.digest();
+    if (encoding == 'hex')
+      return hexDigest;
+    else if (encoding == 'base64')
+      return new Buffer(hexDigest, 'hex').toString('base64');
+    else
+      return new Buffer(hexDigest, 'hex');
+  };
+
+  return obj;
 };
 
-NDN.UNOPEN = 0;  // created but not opened yet
-NDN.OPENED = 1;  // connection to ndnd opened
-NDN.CLOSED = 2;  // connection to ndnd closed
+// Factory method to create HMAC objects.
+exports.createHmac = function(algorithm, key)
+{
+  if (algorithm !== 'sha256')
+    throw new Error('createHmac: unsupported algorithm.');
+
+  var obj = {};
+
+  obj.md = new KJUR.crypto.Mac({alg: "HmacSHA256", pass: {hex: key.toString('hex')}});
+
+  obj.update = function(buf) {
+    this.md.updateHex(buf.toString('hex'));
+  };
+
+  obj.digest = function(encoding) {
+    var hexDigest = this.md.doFinal();
+    if (encoding == 'hex')
+      return hexDigest;
+    else if (encoding == 'base64')
+      return new Buffer(hexDigest, 'hex').toString('base64');
+    else
+      return new Buffer(hexDigest, 'hex');
+  };
+
+  return obj;
+};
+
+// Factory method to create RSA signer objects
+exports.createSign = function(alg)
+{
+  if (alg != 'RSA-SHA256')
+    throw new Error('createSign: unsupported algorithm.');
+
+  var obj = {};
+
+  obj.arr = [];
+
+  obj.update = function(buf) {
+    this.arr.push(buf);
+  };
+
+  obj.sign = function(keypem) {
+    var rsa = new RSAKey();
+    rsa.readPrivateKeyFromPEMString(keypem);
+    var signer = new KJUR.crypto.Signature({alg: "SHA256withRSA", prov: "cryptojs/jsrsa"});
+    signer.initSign(rsa);
+    for (var i = 0; i < this.arr.length; ++i)
+      signer.updateHex(this.arr[i].toString('hex'));
+
+    return new Buffer(signer.sign(), 'hex');
+  };
+
+  return obj;
+};
+
+// Factory method to create RSA verifier objects
+exports.createVerify = function(alg)
+{
+  if (alg != 'RSA-SHA256')
+    throw new Error('createSign: unsupported algorithm.');
+
+  var obj = {};
+
+  obj.arr = [];
+
+  obj.update = function(buf) {
+    this.arr.push(buf);
+  };
+
+  var getSubjectPublicKeyPosFromHex = function(hPub) {
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hPub, 0);
+    if (a.length != 2)
+      return -1;
+    var pBitString = a[1];
+    if (hPub.substring(pBitString, pBitString + 2) != '03')
+      return -1;
+    var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hPub, pBitString);
+    if (hPub.substring(pBitStringV, pBitStringV + 2) != '00')
+      return -1;
+    return pBitStringV + 2;
+  };
+
+  var publicKeyPemToDer = function(publicKeyPem) {
+    // Remove the '-----XXX-----' from the beginning and the end of the public
+    // key and also remove any \n in the public key string.
+    var lines = publicKeyPem.split('\n');
+    var pub = "";
+    for (var i = 1; i < lines.length - 1; i++)
+      pub += lines[i];
+    return new Buffer(pub, 'base64');
+  }
+
+  var readPublicDER = function(pub_der) {
+    var hex = pub_der.toString('hex');
+    var p = getSubjectPublicKeyPosFromHex(hex);
+    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hex, p);
+    if (a.length != 2)
+      return null;
+    var hN = ASN1HEX.getHexOfV_AtObj(hex, a[0]);
+    var hE = ASN1HEX.getHexOfV_AtObj(hex, a[1]);
+    var rsaKey = new RSAKey();
+    rsaKey.setPublic(hN, hE);
+    return rsaKey;
+  };
+
+  obj.verify = function(keypem, sig) {
+    var rsa = readPublicDER(publicKeyPemToDer(keypem));
+    var signer = new KJUR.crypto.Signature({alg: "SHA256withRSA", prov: "cryptojs/jsrsa"});
+    signer.initVerifyByPublicKey(rsa);
+    for (var i = 0; i < this.arr.length; i++)
+      signer.updateHex(this.arr[i].toString('hex'));
+    var hSig = sig.toString('hex');
+    return signer.verify(hSig);
+  };
+
+  return obj;
+};
+
+exports.randomBytes = function(size)
+{
+  // TODO: Use a cryptographic random number generator.
+  var result = new Buffer(size);
+  for (var i = 0; i < size; ++i)
+    result[i] = Math.floor(Math.random() * 256);
+  return result;
+};
+
+// contrib/feross/buffer.js needs base64.toByteArray. Define it here so that
+// we don't have to include the entire base64 module.
+exports.toByteArray = function(str) {
+  var hex = b64tohex(str);
+  var result = [];
+  hex.replace(/(..)/g, function(ss) {
+    result.push(parseInt(ss, 16));
+  });
+  return result;
+};
+
+module.exports = exports
+// After this we include contrib/feross/buffer.js to define the Buffer class.
+var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var base64js = {};
+
+;(function (exports) {
+	'use strict';
+
+  var Arr = (typeof Uint8Array !== 'undefined')
+    ? Uint8Array
+    : Array
+
+	var PLUS   = '+'.charCodeAt(0)
+	var SLASH  = '/'.charCodeAt(0)
+	var NUMBER = '0'.charCodeAt(0)
+	var LOWER  = 'a'.charCodeAt(0)
+	var UPPER  = 'A'.charCodeAt(0)
+
+	function decode (elt) {
+		var code = elt.charCodeAt(0)
+		if (code === PLUS)
+			return 62 // '+'
+		if (code === SLASH)
+			return 63 // '/'
+		if (code < NUMBER)
+			return -1 //no match
+		if (code < NUMBER + 10)
+			return code - NUMBER + 26 + 26
+		if (code < UPPER + 26)
+			return code - UPPER
+		if (code < LOWER + 26)
+			return code - LOWER + 26
+	}
+
+	function b64ToByteArray (b64) {
+		var i, j, l, tmp, placeHolders, arr
+
+		if (b64.length % 4 > 0) {
+			throw new Error('Invalid string. Length must be a multiple of 4')
+		}
+
+		// the number of equal signs (place holders)
+		// if there are two placeholders, than the two characters before it
+		// represent one byte
+		// if there is only one, then the three characters before it represent 2 bytes
+		// this is just a cheap hack to not do indexOf twice
+		var len = b64.length
+		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
+
+		// base64 is 4/3 + up to two characters of the original data
+		arr = new Arr(b64.length * 3 / 4 - placeHolders)
+
+		// if there are placeholders, only get up to the last complete 4 chars
+		l = placeHolders > 0 ? b64.length - 4 : b64.length
+
+		var L = 0
+
+		function push (v) {
+			arr[L++] = v
+		}
+
+		for (i = 0, j = 0; i < l; i += 4, j += 3) {
+			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
+			push((tmp & 0xFF0000) >> 16)
+			push((tmp & 0xFF00) >> 8)
+			push(tmp & 0xFF)
+		}
+
+		if (placeHolders === 2) {
+			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
+			push(tmp & 0xFF)
+		} else if (placeHolders === 1) {
+			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
+			push((tmp >> 8) & 0xFF)
+			push(tmp & 0xFF)
+		}
+
+		return arr
+	}
+
+	function uint8ToBase64 (uint8) {
+		var i,
+			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
+			output = "",
+			temp, length
+
+		function encode (num) {
+			return lookup.charAt(num)
+		}
+
+		function tripletToBase64 (num) {
+			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
+		}
+
+		// go through the array every three bytes, we'll deal with trailing stuff later
+		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
+			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
+			output += tripletToBase64(temp)
+		}
+
+		// pad the end with zeros, but make sure to not forget the extra bytes
+		switch (extraBytes) {
+			case 1:
+				temp = uint8[uint8.length - 1]
+				output += encode(temp >> 2)
+				output += encode((temp << 4) & 0x3F)
+				output += '=='
+				break
+			case 2:
+				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
+				output += encode(temp >> 10)
+				output += encode((temp >> 4) & 0x3F)
+				output += encode((temp << 2) & 0x3F)
+				output += '='
+				break
+		}
+
+		return output
+	}
+
+	exports.toByteArray = b64ToByteArray
+	exports.fromByteArray = uint8ToBase64
+})(base64js);
+var ieee = {};
+
+ieee.read = function(buffer, offset, isLE, mLen, nBytes) {
+  var e, m,
+      eLen = nBytes * 8 - mLen - 1,
+      eMax = (1 << eLen) - 1,
+      eBias = eMax >> 1,
+      nBits = -7,
+      i = isLE ? (nBytes - 1) : 0,
+      d = isLE ? -1 : 1,
+      s = buffer[offset + i];
+
+  i += d;
+
+  e = s & ((1 << (-nBits)) - 1);
+  s >>= (-nBits);
+  nBits += eLen;
+  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
+
+  m = e & ((1 << (-nBits)) - 1);
+  e >>= (-nBits);
+  nBits += mLen;
+  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
+
+  if (e === 0) {
+    e = 1 - eBias;
+  } else if (e === eMax) {
+    return m ? NaN : ((s ? -1 : 1) * Infinity);
+  } else {
+    m = m + Math.pow(2, mLen);
+    e = e - eBias;
+  }
+  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
+};
+
+ieee.write = function(buffer, value, offset, isLE, mLen, nBytes) {
+  var e, m, c,
+      eLen = nBytes * 8 - mLen - 1,
+      eMax = (1 << eLen) - 1,
+      eBias = eMax >> 1,
+      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
+      i = isLE ? 0 : (nBytes - 1),
+      d = isLE ? 1 : -1,
+      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
+
+  value = Math.abs(value);
+
+  if (isNaN(value) || value === Infinity) {
+    m = isNaN(value) ? 1 : 0;
+    e = eMax;
+  } else {
+    e = Math.floor(Math.log(value) / Math.LN2);
+    if (value * (c = Math.pow(2, -e)) < 1) {
+      e--;
+      c *= 2;
+    }
+    if (e + eBias >= 1) {
+      value += rt / c;
+    } else {
+      value += rt * Math.pow(2, 1 - eBias);
+    }
+    if (value * c >= 2) {
+      e++;
+      c /= 2;
+    }
+
+    if (e + eBias >= eMax) {
+      m = 0;
+      e = eMax;
+    } else if (e + eBias >= 1) {
+      m = (value * c - 1) * Math.pow(2, mLen);
+      e = e + eBias;
+    } else {
+      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
+      e = 0;
+    }
+  }
+
+  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
+
+  e = (e << mLen) | m;
+  eLen += mLen;
+  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
+
+  buffer[offset + i - d] |= s * 128;
+};
+
+exports.ieee = ieee;
+/**
+ * The buffer module from node.js, for the browser.
+ * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+ *
+ * Copyright (C) 2013 Feross Aboukhadijeh, and other contributors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * @license  MIT
+ */
+
+var base64 = base64js;
+var ieee754 = require('./ieee754.js').ieee
+
+exports.Buffer = Buffer
+exports.SlowBuffer = Buffer
+exports.INSPECT_MAX_BYTES = 50
+Buffer.poolSize = 8192
+
+/**
+ * If `Buffer._useTypedArrays`:
+ *   === true    Use Uint8Array implementation (fastest)
+ *   === false   Use Object implementation (compatible down to IE6)
+ */
+Buffer._useTypedArrays = (function () {
+  // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+,
+  // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding
+  // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support
+  // because we need to be able to add all the node Buffer API methods. This is an issue
+  // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438
+  try {
+    var buf = new ArrayBuffer(0)
+    var arr = new Uint8Array(buf)
+    arr.foo = function () { return 42 }
+    return 42 === arr.foo() &&
+        typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray`
+  } catch (e) {
+    return false
+  }
+})()
+
+/**
+ * Class: Buffer
+ * =============
+ *
+ * The Buffer constructor returns instances of `Uint8Array` that are augmented
+ * with function properties for all the node `Buffer` API functions. We use
+ * `Uint8Array` so that square bracket notation works as expected -- it returns
+ * a single octet.
+ *
+ * By augmenting the instances, we can avoid modifying the `Uint8Array`
+ * prototype.
+ */
+function Buffer (subject, encoding, noZero) {
+  if (!(this instanceof Buffer))
+    return new Buffer(subject, encoding, noZero)
+
+  var type = typeof subject
+
+  // Workaround: node's base64 implementation allows for non-padded strings
+  // while base64-js does not.
+  if (encoding === 'base64' && type === 'string') {
+    subject = Buffer.stringtrim(subject)
+    while (subject.length % 4 !== 0) {
+      subject = subject + '='
+    }
+  }
+
+  // Find the length
+  var length
+  if (type === 'number')
+    length = Buffer.coerce(subject)
+  else if (type === 'string')
+    length = Buffer.byteLength(subject, encoding)
+  else if (type === 'object')
+    length = Buffer.coerce(subject.length) // assume that object is array-like
+  else
+    throw new Error('First argument needs to be a number, array or string.')
+
+  var buf
+  if (Buffer._useTypedArrays) {
+    // Preferred: Return an augmented `Uint8Array` instance for best performance
+    buf = Buffer._augment(new Uint8Array(length))
+  } else {
+    // Fallback: Return THIS instance of Buffer (created by `new`)
+    buf = this
+    buf.length = length
+    buf._isBuffer = true
+  }
+
+  var i
+  if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') {
+    // Speed optimization -- use set if we're copying from a typed array
+    buf._set(subject)
+  } else if (Buffer.isArrayish(subject)) {
+    // Treat array-ish objects as a byte array
+    if (Buffer.isBuffer(subject)) {
+      for (i = 0; i < length; i++)
+        buf[i] = subject.readUInt8(i)
+    } else {
+      for (i = 0; i < length; i++)
+        buf[i] = ((subject[i] % 256) + 256) % 256
+    }
+  } else if (type === 'string') {
+    buf.write(subject, 0, encoding)
+  } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) {
+    for (i = 0; i < length; i++) {
+      buf[i] = 0
+    }
+  }
+
+  return buf
+}
+
+// STATIC METHODS
+// ==============
+
+Buffer.isEncoding = function (encoding) {
+  switch (String(encoding).toLowerCase()) {
+    case 'hex':
+    case 'utf8':
+    case 'utf-8':
+    case 'ascii':
+    case 'binary':
+    case 'base64':
+    case 'raw':
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      return true
+    default:
+      return false
+  }
+}
+
+Buffer.isBuffer = function (b) {
+  return !!(b !== null && b !== undefined && b._isBuffer)
+}
+
+Buffer.byteLength = function (str, encoding) {
+  var ret
+  str = str.toString()
+  switch (encoding || 'utf8') {
+    case 'hex':
+      ret = str.length / 2
+      break
+    case 'utf8':
+    case 'utf-8':
+      ret = Buffer.utf8ToBytes(str).length
+      break
+    case 'ascii':
+    case 'binary':
+    case 'raw':
+      ret = str.length
+      break
+    case 'base64':
+      ret = Buffer.base64ToBytes(str).length
+      break
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      ret = str.length * 2
+      break
+    default:
+      throw new Error('Unknown encoding')
+  }
+  return ret
+}
+
+Buffer.concat = function (list, totalLength) {
+  Buffer.assert(Buffer.isArray(list), 'Usage: Buffer.concat(list[, length])')
+
+  if (list.length === 0) {
+    return new Buffer(0)
+  } else if (list.length === 1) {
+    return list[0]
+  }
+
+  var i
+  if (totalLength === undefined) {
+    totalLength = 0
+    for (i = 0; i < list.length; i++) {
+      totalLength += list[i].length
+    }
+  }
+
+  var buf = new Buffer(totalLength)
+  var pos = 0
+  for (i = 0; i < list.length; i++) {
+    var item = list[i]
+    item.copy(buf, pos)
+    pos += item.length
+  }
+  return buf
+}
+
+Buffer.compare = function (a, b) {
+  Buffer.assert(Buffer.isBuffer(a) && Buffer.isBuffer(b), 'Arguments must be Buffers')
+  var x = a.length
+  var y = b.length
+  for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}
+  if (i !== len) {
+    x = a[i]
+    y = b[i]
+  }
+  if (x < y) {
+    return -1
+  }
+  if (y < x) {
+    return 1
+  }
+  return 0
+}
+
+// BUFFER INSTANCE METHODS
+// =======================
+
+Buffer.hexWrite = function(buf, string, offset, length) {
+  offset = Number(offset) || 0
+  var remaining = buf.length - offset
+  if (!length) {
+    length = remaining
+  } else {
+    length = Number(length)
+    if (length > remaining) {
+      length = remaining
+    }
+  }
+
+  // must be an even number of digits
+  var strLen = string.length
+  Buffer.assert(strLen % 2 === 0, 'Invalid hex string')
+
+  if (length > strLen / 2) {
+    length = strLen / 2
+  }
+  for (var i = 0; i < length; i++) {
+    var b = parseInt(string.substr(i * 2, 2), 16)
+    Buffer.assert(!isNaN(b), 'Invalid hex string')
+    buf[offset + i] = b
+  }
+  return i
+}
+
+Buffer.utf8Write = function(buf, string, offset, length) {
+  var charsWritten = Buffer.blitBuffer(Buffer.utf8ToBytes(string), buf, offset, length)
+  return charsWritten
+}
+
+Buffer.asciiWrite = function(buf, string, offset, length) {
+  var charsWritten = Buffer.blitBuffer(Buffer.asciiToBytes(string), buf, offset, length)
+  return charsWritten
+}
+
+Buffer.binaryWrite = function(buf, string, offset, length) {
+  return Buffer.asciiWrite(buf, string, offset, length)
+}
+
+Buffer.base64Write = function(buf, string, offset, length) {
+  var charsWritten = Buffer.blitBuffer(Buffer.base64ToBytes(string), buf, offset, length)
+  return charsWritten
+}
+
+Buffer.utf16leWrite = function(buf, string, offset, length) {
+  var charsWritten = Buffer.blitBuffer(Buffer.utf16leToBytes(string), buf, offset, length)
+  return charsWritten
+}
+
+Buffer.prototype.write = function (string, offset, length, encoding) {
+  // Support both (string, offset, length, encoding)
+  // and the legacy (string, encoding, offset, length)
+  if (isFinite(offset)) {
+    if (!isFinite(length)) {
+      encoding = length
+      length = undefined
+    }
+  } else {  // legacy
+    var swap = encoding
+    encoding = offset
+    offset = length
+    length = swap
+  }
+
+  offset = Number(offset) || 0
+  var remaining = this.length - offset
+  if (!length) {
+    length = remaining
+  } else {
+    length = Number(length)
+    if (length > remaining) {
+      length = remaining
+    }
+  }
+  encoding = String(encoding || 'utf8').toLowerCase()
+
+  var ret
+  switch (encoding) {
+    case 'hex':
+      ret = Buffer.hexWrite(this, string, offset, length)
+      break
+    case 'utf8':
+    case 'utf-8':
+      ret = Buffer.utf8Write(this, string, offset, length)
+      break
+    case 'ascii':
+      ret = Buffer.asciiWrite(this, string, offset, length)
+      break
+    case 'binary':
+      ret = Buffer.binaryWrite(this, string, offset, length)
+      break
+    case 'base64':
+      ret = Buffer.base64Write(this, string, offset, length)
+      break
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      ret = Buffer.utf16leWrite(this, string, offset, length)
+      break
+    default:
+      throw new Error('Unknown encoding')
+  }
+  return ret
+}
+
+Buffer.prototype.toString = function (encoding, start, end) {
+  var self = this
+
+  encoding = String(encoding || 'utf8').toLowerCase()
+  start = Number(start) || 0
+  end = (end === undefined) ? self.length : Number(end)
+
+  // Fastpath empty strings
+  if (end === start)
+    return ''
+
+  var ret
+  switch (encoding) {
+    case 'hex':
+      ret = Buffer.hexSlice(self, start, end)
+      break
+    case 'utf8':
+    case 'utf-8':
+      ret = Buffer.utf8Slice(self, start, end)
+      break
+    case 'ascii':
+      ret = Buffer.asciiSlice(self, start, end)
+      break
+    case 'binary':
+      ret = Buffer.binarySlice(self, start, end)
+      break
+    case 'base64':
+      ret = Buffer.base64Slice(self, start, end)
+      break
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      ret = utf16leSlice(self, start, end)
+      break
+    default:
+      throw new Error('Unknown encoding')
+  }
+  return ret
+}
+
+Buffer.prototype.toJSON = function () {
+  return {
+    type: 'Buffer',
+    data: Array.prototype.slice.call(this._arr || this, 0)
+  }
+}
+
+Buffer.prototype.equals = function (b) {
+  Buffer.assert(Buffer.isBuffer(b), 'Argument must be a Buffer')
+  return Buffer.compare(this, b) === 0
+}
+
+Buffer.prototype.compare = function (b) {
+  Buffer.assert(Buffer.isBuffer(b), 'Argument must be a Buffer')
+  return Buffer.compare(this, b)
+}
+
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+Buffer.prototype.copy = function (target, target_start, start, end) {
+  var source = this
+
+  if (!start) start = 0
+  if (!end && end !== 0) end = this.length
+  if (!target_start) target_start = 0
+
+  // Copy 0 bytes; we're done
+  if (end === start) return
+  if (target.length === 0 || source.length === 0) return
+
+  // Fatal error conditions
+  Buffer.assert(end >= start, 'sourceEnd < sourceStart')
+  Buffer.assert(target_start >= 0 && target_start < target.length,
+      'targetStart out of bounds')
+  Buffer.assert(start >= 0 && start < source.length, 'sourceStart out of bounds')
+  Buffer.assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds')
+
+  // Are we oob?
+  if (end > this.length)
+    end = this.length
+  if (target.length - target_start < end - start)
+    end = target.length - target_start + start
+
+  var len = end - start
+
+  if (len < 100 || !Buffer._useTypedArrays) {
+    for (var i = 0; i < len; i++) {
+      target[i + target_start] = this[i + start]
+    }
+  } else {
+    target._set(this.subarray(start, start + len), target_start)
+  }
+}
+
+Buffer.base64Slice = function(buf, start, end) {
+  if (start === 0 && end === buf.length) {
+    return base64.fromByteArray(buf)
+  } else {
+    return base64.fromByteArray(buf.slice(start, end))
+  }
+}
+
+Buffer.utf8Slice = function(buf, start, end) {
+  var res = ''
+  var tmp = ''
+  end = Math.min(buf.length, end)
+
+  for (var i = start; i < end; i++) {
+    if (buf[i] <= 0x7F) {
+      res += Buffer.decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
+      tmp = ''
+    } else {
+      tmp += '%' + buf[i].toString(16)
+    }
+  }
+
+  return res + Buffer.decodeUtf8Char(tmp)
+}
+
+Buffer.asciiSlice = function(buf, start, end) {
+  var ret = ''
+  end = Math.min(buf.length, end)
+
+  for (var i = start; i < end; i++) {
+    ret += String.fromCharCode(buf[i])
+  }
+  return ret
+}
+
+Buffer.binarySlice = function(buf, start, end) {
+  return Buffer.asciiSlice(buf, start, end)
+}
+
+Buffer.hexSlice = function(buf, start, end) {
+  var len = buf.length
+
+  if (!start || start < 0) start = 0
+  if (!end || end < 0 || end > len) end = len
+
+  var out = ''
+  for (var i = start; i < end; i++) {
+    out += Buffer.toHex(buf[i])
+  }
+  return out
+}
+
+function utf16leSlice (buf, start, end) {
+  var bytes = buf.slice(start, end)
+  var res = ''
+  for (var i = 0; i < bytes.length; i += 2) {
+    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
+  }
+  return res
+}
+
+Buffer.prototype.slice = function (start, end) {
+  var len = this.length
+  start = Buffer.clamp(start, len, 0)
+  end = Buffer.clamp(end, len, len)
+
+  if (Buffer._useTypedArrays) {
+    return Buffer._augment(this.subarray(start, end))
+  } else {
+    var sliceLen = end - start
+    var newBuf = new Buffer(sliceLen, undefined, true)
+    for (var i = 0; i < sliceLen; i++) {
+      newBuf[i] = this[i + start]
+    }
+    return newBuf
+  }
+}
+
+// `get` will be removed in Node 0.13+
+Buffer.prototype.get = function (offset) {
+  console.log('.get() is deprecated. Access using array indexes instead.')
+  return this.readUInt8(offset)
+}
+
+// `set` will be removed in Node 0.13+
+Buffer.prototype.set = function (v, offset) {
+  console.log('.set() is deprecated. Access using array indexes instead.')
+  return this.writeUInt8(v, offset)
+}
+
+Buffer.prototype.readUInt8 = function (offset, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset < this.length, 'Trying to read beyond buffer length')
+  }
+
+  if (offset >= this.length)
+    return
+
+  return this[offset]
+}
+
+Buffer.readUInt16 = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  var val
+  if (littleEndian) {
+    val = buf[offset]
+    if (offset + 1 < len)
+      val |= buf[offset + 1] << 8
+  } else {
+    val = buf[offset] << 8
+    if (offset + 1 < len)
+      val |= buf[offset + 1]
+  }
+  return val
+}
+
+Buffer.prototype.readUInt16LE = function (offset, noAssert) {
+  return Buffer.readUInt16(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readUInt16BE = function (offset, noAssert) {
+  return Buffer.readUInt16(this, offset, false, noAssert)
+}
+
+Buffer.readUInt32 = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  var val
+  if (littleEndian) {
+    if (offset + 2 < len)
+      val = buf[offset + 2] << 16
+    if (offset + 1 < len)
+      val |= buf[offset + 1] << 8
+    val |= buf[offset]
+    if (offset + 3 < len)
+      val = val + (buf[offset + 3] << 24 >>> 0)
+  } else {
+    if (offset + 1 < len)
+      val = buf[offset + 1] << 16
+    if (offset + 2 < len)
+      val |= buf[offset + 2] << 8
+    if (offset + 3 < len)
+      val |= buf[offset + 3]
+    val = val + (buf[offset] << 24 >>> 0)
+  }
+  return val
+}
+
+Buffer.prototype.readUInt32LE = function (offset, noAssert) {
+  return Buffer.readUInt32(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readUInt32BE = function (offset, noAssert) {
+  return Buffer.readUInt32(this, offset, false, noAssert)
+}
+
+Buffer.prototype.readInt8 = function (offset, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(offset !== undefined && offset !== null,
+        'missing offset')
+    Buffer.assert(offset < this.length, 'Trying to read beyond buffer length')
+  }
+
+  if (offset >= this.length)
+    return
+
+  var neg = this[offset] & 0x80
+  if (neg)
+    return (0xff - this[offset] + 1) * -1
+  else
+    return this[offset]
+}
+
+Buffer.readInt16 = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  var val = Buffer.readUInt16(buf, offset, littleEndian, true)
+  var neg = val & 0x8000
+  if (neg)
+    return (0xffff - val + 1) * -1
+  else
+    return val
+}
+
+Buffer.prototype.readInt16LE = function (offset, noAssert) {
+  return Buffer.readInt16(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readInt16BE = function (offset, noAssert) {
+  return Buffer.readInt16(this, offset, false, noAssert)
+}
+
+Buffer.readInt32 = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  var val = Buffer.readUInt32(buf, offset, littleEndian, true)
+  var neg = val & 0x80000000
+  if (neg)
+    return (0xffffffff - val + 1) * -1
+  else
+    return val
+}
+
+Buffer.prototype.readInt32LE = function (offset, noAssert) {
+  return Buffer.readInt32(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readInt32BE = function (offset, noAssert) {
+  return Buffer.readInt32(this, offset, false, noAssert)
+}
+
+Buffer.readFloat = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  return ieee754.read(buf, offset, littleEndian, 23, 4)
+}
+
+Buffer.prototype.readFloatLE = function (offset, noAssert) {
+  return Buffer.readFloat(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readFloatBE = function (offset, noAssert) {
+  return Buffer.readFloat(this, offset, false, noAssert)
+}
+
+Buffer.readDouble = function(buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset + 7 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  return ieee754.read(buf, offset, littleEndian, 52, 8)
+}
+
+Buffer.prototype.readDoubleLE = function (offset, noAssert) {
+  return Buffer.readDouble(this, offset, true, noAssert)
+}
+
+Buffer.prototype.readDoubleBE = function (offset, noAssert) {
+  return Buffer.readDouble(this, offset, false, noAssert)
+}
+
+Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset < this.length, 'trying to write beyond buffer length')
+    Buffer.verifuint(value, 0xff)
+  }
+
+  if (offset >= this.length) return
+
+  this[offset] = value
+  return offset + 1
+}
+
+Buffer.writeUInt16 = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 1 < buf.length, 'trying to write beyond buffer length')
+    Buffer.verifuint(value, 0xffff)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) {
+    buf[offset + i] =
+        (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
+            (littleEndian ? i : 1 - i) * 8
+  }
+  return offset + 2
+}
+
+Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
+  return Buffer.writeUInt16(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
+  return Buffer.writeUInt16(this, value, offset, false, noAssert)
+}
+
+Buffer.writeUInt32 = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'trying to write beyond buffer length')
+    Buffer.verifuint(value, 0xffffffff)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) {
+    buf[offset + i] =
+        (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
+  }
+  return offset + 4
+}
+
+Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
+  return Buffer.writeUInt32(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
+  return Buffer.writeUInt32(this, value, offset, false, noAssert)
+}
+
+Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset < this.length, 'Trying to write beyond buffer length')
+    Buffer.verifsint(value, 0x7f, -0x80)
+  }
+
+  if (offset >= this.length)
+    return
+
+  if (value >= 0)
+    this.writeUInt8(value, offset, noAssert)
+  else
+    this.writeUInt8(0xff + value + 1, offset, noAssert)
+  return offset + 1
+}
+
+Buffer.writeInt16 = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 1 < buf.length, 'Trying to write beyond buffer length')
+    Buffer.verifsint(value, 0x7fff, -0x8000)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  if (value >= 0)
+    Buffer.writeUInt16(buf, value, offset, littleEndian, noAssert)
+  else
+    Buffer.writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert)
+  return offset + 2
+}
+
+Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
+  return Buffer.writeInt16(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
+  return Buffer.writeInt16(this, value, offset, false, noAssert)
+}
+
+Buffer.writeInt32 = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
+    Buffer.verifsint(value, 0x7fffffff, -0x80000000)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  if (value >= 0)
+    Buffer.writeUInt32(buf, value, offset, littleEndian, noAssert)
+  else
+    Buffer.writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert)
+  return offset + 4
+}
+
+Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
+  return Buffer.writeInt32(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
+  return Buffer.writeInt32(this, value, offset, false, noAssert)
+}
+
+Buffer.writeFloat = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
+    Buffer.verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  ieee754.write(buf, value, offset, littleEndian, 23, 4)
+  return offset + 4
+}
+
+Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
+  return Buffer.writeFloat(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
+  return Buffer.writeFloat(this, value, offset, false, noAssert)
+}
+
+Buffer.writeDouble = function(buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    Buffer.assert(value !== undefined && value !== null, 'missing value')
+    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
+    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
+    Buffer.assert(offset + 7 < buf.length,
+        'Trying to write beyond buffer length')
+    Buffer.verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)
+  }
+
+  var len = buf.length
+  if (offset >= len)
+    return
+
+  ieee754.write(buf, value, offset, littleEndian, 52, 8)
+  return offset + 8
+}
+
+Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
+  return Buffer.writeDouble(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
+  return Buffer.writeDouble(this, value, offset, false, noAssert)
+}
+
+// fill(value, start=0, end=buffer.length)
+Buffer.prototype.fill = function (value, start, end) {
+  if (!value) value = 0
+  if (!start) start = 0
+  if (!end) end = this.length
+
+  Buffer.assert(end >= start, 'end < start')
+
+  // Fill 0 bytes; we're done
+  if (end === start) return
+  if (this.length === 0) return
+
+  Buffer.assert(start >= 0 && start < this.length, 'start out of bounds')
+  Buffer.assert(end >= 0 && end <= this.length, 'end out of bounds')
+
+  var i
+  if (typeof value === 'number') {
+    for (i = start; i < end; i++) {
+      this[i] = value
+    }
+  } else {
+    var bytes = Buffer.utf8ToBytes(value.toString())
+    var len = bytes.length
+    for (i = start; i < end; i++) {
+      this[i] = bytes[i % len]
+    }
+  }
+
+  return this
+}
+
+Buffer.prototype.inspect = function () {
+  var out = []
+  var len = this.length
+  for (var i = 0; i < len; i++) {
+    out[i] = Buffer.toHex(this[i])
+    if (i === exports.INSPECT_MAX_BYTES) {
+      out[i + 1] = '...'
+      break
+    }
+  }
+  return '<Buffer ' + out.join(' ') + '>'
+}
+
+/**
+ * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
+ * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
+ */
+Buffer.prototype.toArrayBuffer = function () {
+  if (typeof Uint8Array !== 'undefined') {
+    if (Buffer._useTypedArrays) {
+      return (new Buffer(this)).buffer
+    } else {
+      var buf = new Uint8Array(this.length)
+      for (var i = 0, len = buf.length; i < len; i += 1) {
+        buf[i] = this[i]
+      }
+      return buf.buffer
+    }
+  } else {
+    throw new Error('Buffer.toArrayBuffer not supported in this browser')
+  }
+}
+
+// HELPER FUNCTIONS
+// ================
+
+var BP = Buffer.prototype
+
+/**
+ * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
+ */
+Buffer._augment = function (arr) {
+  arr._isBuffer = true
+
+  // save reference to original Uint8Array get/set methods before overwriting
+  arr._get = arr.get
+  arr._set = arr.set
+
+  // deprecated, will be removed in node 0.13+
+  arr.get = BP.get
+  arr.set = BP.set
+
+  arr.write = BP.write
+  arr.toString = BP.toString
+  arr.toLocaleString = BP.toString
+  arr.toJSON = BP.toJSON
+  arr.equals = BP.equals
+  arr.compare = BP.compare
+  arr.copy = BP.copy
+  arr.slice = BP.slice
+  arr.readUInt8 = BP.readUInt8
+  arr.readUInt16LE = BP.readUInt16LE
+  arr.readUInt16BE = BP.readUInt16BE
+  arr.readUInt32LE = BP.readUInt32LE
+  arr.readUInt32BE = BP.readUInt32BE
+  arr.readInt8 = BP.readInt8
+  arr.readInt16LE = BP.readInt16LE
+  arr.readInt16BE = BP.readInt16BE
+  arr.readInt32LE = BP.readInt32LE
+  arr.readInt32BE = BP.readInt32BE
+  arr.readFloatLE = BP.readFloatLE
+  arr.readFloatBE = BP.readFloatBE
+  arr.readDoubleLE = BP.readDoubleLE
+  arr.readDoubleBE = BP.readDoubleBE
+  arr.writeUInt8 = BP.writeUInt8
+  arr.writeUInt16LE = BP.writeUInt16LE
+  arr.writeUInt16BE = BP.writeUInt16BE
+  arr.writeUInt32LE = BP.writeUInt32LE
+  arr.writeUInt32BE = BP.writeUInt32BE
+  arr.writeInt8 = BP.writeInt8
+  arr.writeInt16LE = BP.writeInt16LE
+  arr.writeInt16BE = BP.writeInt16BE
+  arr.writeInt32LE = BP.writeInt32LE
+  arr.writeInt32BE = BP.writeInt32BE
+  arr.writeFloatLE = BP.writeFloatLE
+  arr.writeFloatBE = BP.writeFloatBE
+  arr.writeDoubleLE = BP.writeDoubleLE
+  arr.writeDoubleBE = BP.writeDoubleBE
+  arr.fill = BP.fill
+  arr.inspect = BP.inspect
+  arr.toArrayBuffer = BP.toArrayBuffer
+
+  return arr
+}
+
+Buffer.stringtrim = function(str) {
+  if (str.trim) return str.trim()
+  return str.replace(/^\s+|\s+$/g, '')
+}
+
+// slice(start, end)
+Buffer.clamp = function(index, len, defaultValue) {
+  if (typeof index !== 'number') return defaultValue
+  index = ~~index;  // Coerce to integer.
+  if (index >= len) return len
+  if (index >= 0) return index
+  index += len
+  if (index >= 0) return index
+  return 0
+}
+
+Buffer.coerce = function(length) {
+  // Coerce length to a number (possibly NaN), round up
+  // in case it's fractional (e.g. 123.456) then do a
+  // double negate to coerce a NaN to 0. Easy, right?
+  length = ~~Math.ceil(+length)
+  return length < 0 ? 0 : length
+}
+
+Buffer.isArray = function(subject) {
+  return (Array.isArray || function (subject) {
+    return Object.prototype.toString.call(subject) === '[object Array]'
+  })(subject)
+}
+
+Buffer.isArrayish = function(subject) {
+  return Buffer.isArray(subject) || Buffer.isBuffer(subject) ||
+      subject && typeof subject === 'object' &&
+      typeof subject.length === 'number'
+}
+
+Buffer.toHex = function(n) {
+  if (n < 16) return '0' + n.toString(16)
+  return n.toString(16)
+}
+
+Buffer.utf8ToBytes = function(str) {
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    var b = str.charCodeAt(i)
+    if (b <= 0x7F) {
+      byteArray.push(b)
+    } else {
+      var start = i
+      if (b >= 0xD800 && b <= 0xDFFF) i++
+      var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')
+      for (var j = 0; j < h.length; j++) {
+        byteArray.push(parseInt(h[j], 16))
+      }
+    }
+  }
+  return byteArray
+}
+
+Buffer.asciiToBytes = function(str) {
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    // Node's code seems to be doing this and not & 0x7F..
+    byteArray.push(str.charCodeAt(i) & 0xFF)
+  }
+  return byteArray
+}
+
+Buffer.utf16leToBytes = function(str) {
+  var c, hi, lo
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    c = str.charCodeAt(i)
+    hi = c >> 8
+    lo = c % 256
+    byteArray.push(lo)
+    byteArray.push(hi)
+  }
+
+  return byteArray
+}
+
+Buffer.base64ToBytes = function(str) {
+  return base64.toByteArray(str)
+}
+
+Buffer.blitBuffer = function(src, dst, offset, length) {
+  for (var i = 0; i < length; i++) {
+    if ((i + offset >= dst.length) || (i >= src.length))
+      break
+    dst[i + offset] = src[i]
+  }
+  return i
+}
+
+Buffer.decodeUtf8Char = function(str) {
+  try {
+    return decodeURIComponent(str)
+  } catch (err) {
+    return String.fromCharCode(0xFFFD) // UTF 8 invalid char
+  }
+}
 
 /*
- * Return true if necessary JavaScript support is available, else log an error and return false.
+ * We have to make sure that the value is a valid integer. This means that it
+ * is non-negative. It has no fractional component and that it does not
+ * exceed the maximum allowed value.
  */
-NDN.getSupported = function() {
+Buffer.verifuint = function(value, max) {
+  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
+  Buffer.assert(value >= 0, 'specified a negative value for writing an unsigned value')
+  Buffer.assert(value <= max, 'value is larger than maximum value for type')
+  Buffer.assert(Math.floor(value) === value, 'value has a fractional component')
+}
+
+Buffer.verifsint = function(value, max, min) {
+  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
+  Buffer.assert(value <= max, 'value larger than maximum allowed value')
+  Buffer.assert(value >= min, 'value smaller than minimum allowed value')
+  Buffer.assert(Math.floor(value) === value, 'value has a fractional component')
+}
+
+Buffer.verifIEEE754 = function(value, max, min) {
+  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
+  Buffer.assert(value <= max, 'value larger than maximum allowed value')
+  Buffer.assert(value >= min, 'value smaller than minimum allowed value')
+}
+
+Buffer.assert = function(test, message) {
+  if (!test) throw new Error(message || 'Failed assertion')
+}
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * The Log class holds the global static variable LOG.
+ */
+var Log = function Log()
+{
+}
+
+exports.Log = Log;
+
+/**
+ * LOG is the level for logging debugging statements.  0 means no log messages.
+ * @type Number
+ */
+Log.LOG = 0;
+/**
+ * Encapsulate a Buffer and support dynamic reallocation.
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var printStackTrace = require('../../contrib/stacktrace/stacktrace.js').printStackTrace;
+
+/**
+ * NdnCommon has static NDN utility methods and constants.
+ * @constructor
+ */
+var NdnCommon = {};
+
+exports.NdnCommon = NdnCommon;
+
+/**
+ * The practical limit of the size of a network-layer packet. If a packet is
+ * larger than this, the library or application MAY drop it. This constant is
+ * defined in this low-level class so that internal code can use it, but
+ * applications should use the static API method
+ * Face.getMaxNdnPacketSize() which is equivalent.
+ */
+NdnCommon.MAX_NDN_PACKET_SIZE = 8800;
+
+/**
+ * Get the error message plus its stack trace.
+ * @param {Error} error The error object.
+ * @return {string} The error message, plus the stack trace with each line
+ * separated by '\n'.
+ */
+NdnCommon.getErrorWithStackTrace = function(error)
+{
+  return error + '\n' + printStackTrace({e: error}).join('\n');
+};
+
+/**
+ * Check for Indexed DB support and call onComplete with the result as described
+ * below. This has to use an onComplete callback since IndexedDB is async.
+ * @param {function} onComplete This calls onComplete(haveIndexedDb) where
+ * haveIndexedDb is true if the browser has Indexed DB support, otherwise false.
+ */
+NdnCommon.checkIndexedDb = function(onComplete)
+{
+  try {
+    var database = new Dexie("test-Dexie-support");
+    database.version(1).stores({});
+    database.open();
+
+    // Give Dexie a little time to open.
+    setTimeout(function() {
+      try {
+        onComplete(database.isOpen());
+      } catch (ex) {
+        onComplete(false);
+      }
+    }, 200);
+  } catch (ex) {
+    onComplete(false);
+  }
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var NdnCommon = require('./ndn-common.js').NdnCommon;
+
+/**
+ * An ExponentialReExpress uses an internal onTimeout to express the interest again
+ * with double the interestLifetime. See ExponentialReExpress.makeOnTimeout,
+ * which you should call instead of the private constructor.
+ * Create a new ExponentialReExpress where onTimeout expresses the interest
+ * again with double the interestLifetime. If the interesLifetime goes
+ * over settings.maxInterestLifetime, then call the given onTimeout. If this
+ * internally gets onData, just call the given onData.
+ * @constructor
+ */
+var ExponentialReExpress = function ExponentialReExpress
+  (face, onData, onTimeout, settings)
+{
+  settings = (settings || {});
+  this.face = face;
+  this.callerOnData = onData;
+  this.callerOnTimeout = onTimeout;
+
+  this.maxInterestLifetime = (settings.maxInterestLifetime || 16000);
+};
+
+exports.ExponentialReExpress = ExponentialReExpress;
+
+/**
+ * Return a callback to use in expressInterest for onTimeout which will express
+ * the interest again with double the interestLifetime. If the interesLifetime
+ * goes over maxInterestLifetime (see settings below), then call the provided
+ * onTimeout. If a Data packet is received, this calls the provided onData.
+ * Use it like this:
+ *   var onData = function() { ... };
+ *   var onTimeout = function() { ... };
+ *   face.expressInterest
+ *     (interest, onData,
+ *      ExponentialReExpress.makeOnTimeout(face, onData, onTimeout));
+ * @param {Face} face This calls face.expressInterest.
+ * @param {function} onData When a matching data packet is received, this calls
+ * onData(interest, data) where interest is the interest given to
+ * expressInterest and data is the received Data object. This is normally the
+ * same onData you initially passed to expressInterest.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onTimeout If the interesLifetime goes over
+ * maxInterestLifetime, this calls onTimeout(interest). However, if onTimeout is
+ * null, this does not use it.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {Object} settings (optional) If not null, an associative array with
+ * the following defaults:
+ * {
+ *   maxInterestLifetime: 16000 // milliseconds
+ * }
+ * @return {function} The onTimeout callback to pass to expressInterest.
+ */
+ExponentialReExpress.makeOnTimeout = function(face, onData, onTimeout, settings)
+{
+  var reExpress = new ExponentialReExpress(face, onData, onTimeout, settings);
+  return function(interest) { reExpress.onTimeout(interest); };
+};
+
+ExponentialReExpress.prototype.onTimeout = function(interest)
+{
+  var interestLifetime = interest.getInterestLifetimeMilliseconds();
+  if (interestLifetime == null) {
+    // Can't re-express.
+    if (this.callerOnTimeout) {
+      try {
+        this.callerOnTimeout(interest);
+      } catch (ex) {
+        console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+    return;
+  }
+
+  var nextInterestLifetime = interestLifetime * 2;
+  if (nextInterestLifetime > this.maxInterestLifetime) {
+    if (this.callerOnTimeout) {
+      try {
+        this.callerOnTimeout(interest);
+      } catch (ex) {
+        console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+    return;
+  }
+
+  var nextInterest = interest.clone();
+  nextInterest.setInterestLifetimeMilliseconds(nextInterestLifetime);
+  var thisObject = this;
+  this.face.expressInterest
+    (nextInterest, this.callerOnData,
+     function(localInterest) { thisObject.onTimeout(localInterest); });
+};
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A Blob holds an immutable byte array implemented as a Buffer.  This should be
+ * treated like a string which is a pointer to an immutable string. (It is OK to
+ * pass a pointer to the string because the new owner can’t change the bytes of
+ * the string.)  Blob does not inherit from Buffer. Instead you must call buf()
+ * to get the byte array which reminds you that you should not change the
+ * contents.  Also remember that buf() can return null.
+ * @param {Blob|Buffer|Array<number>} value (optional) If value is a Blob, take
+ * another pointer to the Buffer without copying. If value is a Buffer or byte
+ * array, copy to create a new Buffer.  If omitted, buf() will return null.
+ * @param {boolean} copy (optional) If true, copy the contents of
+ * value into a new Buffer.  If false, just use the existing value without
+ * copying. If omitted, then copy the contents (unless value is already a Blob).
+ * IMPORTANT: If copy is false, if you keep a pointer to the value then you must
+ * treat the value as immutable and promise not to change it.
+ * @constructor
+ */
+var Blob = function Blob(value, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  if (value == null)
+    this.buffer = null;
+  else if (typeof value === 'object' && value instanceof Blob)
+    // Use the existing buffer.  Don't need to check for copy.
+    this.buffer = value.buffer;
+  else {
+    if (typeof value === 'string')
+      // Convert from a string to utf-8 byte encoding.
+      this.buffer = new Buffer(value, 'utf8');
+    else {
+      if (copy)
+        // We are copying, so just make another Buffer.
+        this.buffer = new Buffer(value);
+      else {
+        if (Buffer.isBuffer(value))
+          // We can use as-is.
+          this.buffer = value;
+        else
+          // We need a Buffer, so copy.
+          this.buffer = new Buffer(value);
+      }
+    }
+  }
+
+  // Set the length to be "JavaScript-like".
+  this.length = this.buffer != null ? this.buffer.length : 0;
+};
+
+exports.Blob = Blob;
+
+/**
+ * Return the length of the immutable byte array.
+ * @return {number} The length of the array.  If buf() is null, return 0.
+ */
+Blob.prototype.size = function()
+{
+  if (this.buffer != null)
+    return this.buffer.length;
+  else
+    return 0;
+};
+
+/**
+ * Return the immutable byte array.  DO NOT change the contents of the Buffer.
+ * If you need to change it, make a copy.
+ * @return {Buffer} The Buffer holding the immutable byte array, or null.
+ */
+Blob.prototype.buf = function()
+{
+  return this.buffer;
+};
+
+/**
+ * Return true if the array is null, otherwise false.
+ * @return {boolean} True if the array is null.
+ */
+Blob.prototype.isNull = function()
+{
+  return this.buffer == null;
+};
+
+/**
+ * Return the hex representation of the bytes in the byte array.
+ * @return {string} The hex string.
+ */
+Blob.prototype.toHex = function()
+{
+  if (this.buffer == null)
+    return "";
+  else
+    return this.buffer.toString('hex');
+};
+
+/**
+ * Decode the byte array as UTF8 and return the Unicode string.
+ * @return A unicode string, or "" if the buffer is null.
+ */
+Blob.prototype.toString = function()
+{
+  if (this.buffer == null)
+    return "";
+  else
+    return this.buffer.toString('utf8');
+};
+
+/**
+ * Check if the value of this Blob equals the other blob.
+ * @param {Blob} other The other Blob to check.
+ * @return {boolean} if this isNull and other isNull or if the bytes of this
+ * blob equal the bytes of the other.
+ */
+Blob.prototype.equals = function(other)
+{
+  if (this.isNull())
+    return other.isNull();
+  else if (other.isNull())
+    return false;
+  else {
+    if (this.buffer.length != other.buffer.length)
+      return false;
+
+    for (var i = 0; i < this.buffer.length; ++i) {
+      if (this.buffer[i] != other.buffer[i])
+        return false;
+    }
+
+    return true;
+  }
+};
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./blob.js').Blob;
+
+/**
+ * A SignedBlob extends Blob to keep the offsets of a signed portion (e.g., the
+ * bytes of Data packet). This inherits from Blob, including Blob.size and Blob.buf.
+ * @param {Blob|Buffer|Array<number>} value (optional) If value is a Blob, take
+ * another pointer to the Buffer without copying. If value is a Buffer or byte
+ * array, copy to create a new Buffer.  If omitted, buf() will return null.
+ * @param {number} signedPortionBeginOffset (optional) The offset in the
+ * encoding of the beginning of the signed portion. If omitted, set to 0.
+ * @param {number} signedPortionEndOffset (optional) The offset in the encoding
+ * of the end of the signed portion. If omitted, set to 0.
+ * @constructor
+ */
+var SignedBlob = function SignedBlob(value, signedPortionBeginOffset, signedPortionEndOffset)
+{
+  // Call the base constructor.
+  Blob.call(this, value);
+
+  if (this.buffer == null) {
+    this.signedPortionBeginOffset = 0;
+    this.signedPortionEndOffset = 0;
+  }
+  else if (typeof value === 'object' && value instanceof SignedBlob) {
+    // Copy the SignedBlob, allowing override for offsets.
+    this.signedPortionBeginOffset = signedPortionBeginOffset == null ?
+      value.signedPortionBeginOffset : signedPortionBeginOffset;
+    this.signedPortionEndOffset = signedPortionEndOffset == null ?
+      value.signedPortionEndOffset : signedPortionEndOffset;
+  }
+  else {
+    this.signedPortionBeginOffset = signedPortionBeginOffset || 0;
+    this.signedPortionEndOffset = signedPortionEndOffset || 0;
+  }
+
+  if (this.buffer == null)
+    this.signedBuffer = null;
+  else
+    this.signedBuffer = this.buffer.slice
+      (this.signedPortionBeginOffset, this.signedPortionEndOffset);
+};
+
+SignedBlob.prototype = new Blob();
+SignedBlob.prototype.name = "SignedBlob";
+
+exports.SignedBlob = SignedBlob;
+
+/**
+ * Return the length of the signed portion of the immutable byte array.
+ * @return {number} The length of the signed portion.  If signedBuf() is null,
+ * return 0.
+ */
+SignedBlob.prototype.signedSize = function()
+{
+  if (this.signedBuffer != null)
+    return this.signedBuffer.length;
+  else
+    return 0;
+};
+
+/**
+ * Return a the signed portion of the immutable byte array.
+ * @return {Buffer} A slice into the Buffer which is the signed portion.
+ * If the pointer to the array is null, return null.
+ */
+SignedBlob.prototype.signedBuf = function() { return this.signedBuffer; };
+
+/**
+ * Return the offset in the array of the beginning of the signed portion.
+ * @return {number} The offset in the array.
+ */
+SignedBlob.prototype.getSignedPortionBeginOffset = function()
+{
+  return this.signedPortionBeginOffset;
+};
+
+/**
+ * Return the offset in the array of the end of the signed portion.
+ * @return {number} The offset in the array.
+ */
+SignedBlob.prototype.getSignedPortionEndOffset = function()
+{
+  return this.signedPortionEndOffset;
+};
+/**
+ * Encapsulate a Buffer and support dynamic reallocation.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a DynamicBuffer where this.array is a Buffer of size length.
+ * To access the array, use this.array or call slice.
+ * @constructor
+ * @param {number} length the initial length of the array.  If null, use a default.
+ */
+var DynamicBuffer = function DynamicBuffer(length)
+{
+  if (!length)
+    length = 16;
+
+  this.array = new Buffer(length);
+};
+
+exports.DynamicBuffer = DynamicBuffer;
+
+/**
+ * Ensure that this.array has the length, reallocate and copy if necessary.
+ * Update the length of this.array which may be greater than length.
+ * @param {number} length The minimum length for the array.
+ */
+DynamicBuffer.prototype.ensureLength = function(length)
+{
+  if (this.array.length >= length)
+    return;
+
+  // See if double is enough.
+  var newLength = this.array.length * 2;
+  if (length > newLength)
+    // The needed length is much greater, so use it.
+    newLength = length;
+
+  var newArray = new Buffer(newLength);
+  this.array.copy(newArray);
+  this.array = newArray;
+};
+
+/**
+ * Copy the value to this.array at offset, reallocating if necessary.
+ * @param {Buffer} value The buffer to copy.
+ * @param {number} offset The offset in the buffer to start copying into.
+ * @return {number} The new offset which is offset + value.length.
+ */
+DynamicBuffer.prototype.copy = function(value, offset)
+{
+  this.ensureLength(value.length + offset);
+
+  if (Buffer.isBuffer(value))
+    value.copy(this.array, offset);
+  else
+    // Need to make value a Buffer to copy.
+    new Buffer(value).copy(this.array, offset);
+
+  return offset + value.length;
+};
+
+/**
+ * Ensure that this.array has the length. If necessary, reallocate the array
+ *   and shift existing data to the back of the new array.
+ * Update the length of this.array which may be greater than length.
+ * @param {number} length The minimum length for the array.
+ */
+DynamicBuffer.prototype.ensureLengthFromBack = function(length)
+{
+  if (this.array.length >= length)
+    return;
+
+  // See if double is enough.
+  var newLength = this.array.length * 2;
+  if (length > newLength)
+    // The needed length is much greater, so use it.
+    newLength = length;
+
+  var newArray = new Buffer(newLength);
+  // Copy to the back of newArray.
+  this.array.copy(newArray, newArray.length - this.array.length);
+  this.array = newArray;
+};
+
+/**
+ * First call ensureLengthFromBack to make sure the bytearray has
+ * offsetFromBack bytes, then copy value into the array starting
+ * offsetFromBack bytes from the back of the array.
+ * @param {Buffer} value The buffer to copy.
+ * @param {number} offsetFromBack The offset from the back of the array to start
+ * copying.
+ */
+DynamicBuffer.prototype.copyFromBack = function(value, offsetFromBack)
+{
+  this.ensureLengthFromBack(offsetFromBack);
+
+  if (Buffer.isBuffer(value))
+    value.copy(this.array, this.array.length - offsetFromBack);
+  else
+    // Need to make value a Buffer to copy.
+    new Buffer(value).copy(this.array, this.array.length - offsetFromBack);
+};
+
+/**
+ * Return this.array.slice(begin, end);
+ * @param {number} begin The begin index for the slice.
+ * @param {number} end (optional) The end index for the slice.
+ * @return {Buffer} The buffer slice.
+ */
+DynamicBuffer.prototype.slice = function(begin, end)
+{
+  if (end == undefined)
+    return this.array.slice(begin);
+  else
+    return this.array.slice(begin, end);
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A ChangeCounter keeps a target object whose change count is tracked by a
+ * local change count.  You can set to a new target which updates the local
+ * change count, and you can call checkChanged to check if the target (or one of
+ * the target's targets) has been changed. The target object must have a method
+ * getChangeCount.
+ *
+ * Create a new ChangeCounter to track the given target. If target is not null,
+ * this sets the local change counter to target.getChangeCount().
+ * @param {object} target The target to track, as an object with the method
+ * getChangeCount().
+ * @constructor
+ */
+var ChangeCounter = function ChangeCounter(target)
+{
+  this.target = target;
+  this.changeCount = (target == null ? 0 : target.getChangeCount());
+};
+
+exports.ChangeCounter = ChangeCounter;
+
+/**
+ * Get the target object. If the target is changed, then checkChanged will
+ * detect it.
+ * @return {object} The target, as an object with the method
+ * getChangeCount().
+ */
+ChangeCounter.prototype.get = function()
+{
+  return this.target;
+};
+
+/**
+ * Set the target to the given target. If target is not null, this sets the
+ * local change counter to target.getChangeCount().
+ * @param {object} target The target to track, as an object with the method
+ * getChangeCount().
+ */
+ChangeCounter.prototype.set = function(target)
+{
+  this.target = target;
+  this.changeCount = (target == null ? 0 : target.getChangeCount());
+};
+
+/**
+ * If the target's change count is different than the local change count, then
+ * update the local change count and return true. Otherwise return false,
+ * meaning that the target has not changed. Also, if the target is null,
+ * simply return false. This is useful since the target (or one of the target's
+ * targets) may be changed and you need to find out.
+ * @return {boolean} True if the change count has been updated, false if not.
+ */
+ChangeCounter.prototype.checkChanged = function()
+{
+  if (this.target == null)
+    return false;
+
+  var targetChangeCount = this.target.getChangeCount();
+  if (this.changeCount != targetChangeCount) {
+    this.changeCount = targetChangeCount;
+    return true;
+  }
+  else
+    return false;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var NdnCommon = require('./ndn-common.js').NdnCommon;
+
+/**
+ * A SyncPromise is a promise which is immediately fulfilled or rejected, used
+ * to return a promise in synchronous code.
+ * This private constructor creates a SyncPromise fulfilled or rejected with the
+ * given value. You should normally not call this constructor but call
+ * SyncPromise.resolve or SyncPromise.reject. Note that we don't need a
+ * constructor like SyncPromise(function(resolve, reject)) because this would be
+ * for scheduling the function to be called later, which we don't do.
+ * @param {any} value If isRejected is false, this is the value of the fulfilled
+ * promise, else if isRejected is true, this is the error.
+ * @param {boolean} isRejected True to create a promise in the rejected state,
+ * where value is the error.
+ * @constructor
+ */
+var SyncPromise = function SyncPromise(value, isRejected)
+{
+  this.value = value;
+  this.isRejected = isRejected;
+};
+
+exports.SyncPromise = SyncPromise;
+
+/**
+ * If this promise is fulfilled, immediately call onFulfilled with the fulfilled
+ * value as described below. Otherwise, if this promise is rejected, immediately
+ * call onRejected with the error as described below.
+ * @param {function} (optional) onFulfilled If this promise is fulfilled, this
+ * calls onFulfilled(value) with the value of this promise and returns the
+ * result. The function should return a promise. To use all synchronous code,
+ * onFulfilled should return SyncPromise.resolve(newValue).
+ * @param {function} (optional) onRejected If this promise is rejected, this
+ * calls onRejected(err) with the error value of this promise and returns the
+ * result. The function should return a promise. To use all synchronous code,
+ * onFulfilled should return SyncPromise.resolve(newValue) (or throw an
+ * exception).
+ * @return {Promise|SyncPromise} If this promise is fulfilled, return the result
+ * of calling onFulfilled(value). Note that this does not create a promise which
+ * is scheduled to execute later. Rather it immediately calls onFulfilled which
+ * should return a promise. But if onFulfilled is undefined, simply return this
+ * promise to pass it forward. If this promise is rejected, return the result of
+ * calling onRejected(err) with the error value. But if onRejected is undefined,
+ * simply return this promise to pass it forward. However, if onFulfilled or
+ * onRejected throws an exception, then return a new SyncPromise in the rejected
+ * state with the exception.
+ */
+SyncPromise.prototype.then = function(onFulfilled, onRejected)
+{
+  if (this.isRejected) {
+    if (onRejected) {
+      try {
+        return onRejected(this.value);
+      }
+      catch(err) {
+        return new SyncPromise(err, true);
+      }
+    }
+    else
+      // Pass the error forward.
+      return this;
+  }
+  else {
+    if (onFulfilled) {
+      try {
+        return onFulfilled(this.value);
+      }
+      catch(err) {
+        return new SyncPromise(err, true);
+      }
+    }
+    else
+      // Pass the fulfilled value forward.
+      return this;
+  }
+};
+
+/**
+ * Call this.then(undefined, onRejected) and return the result. If this promise
+ * is rejected then onRejected will process it. If this promise is fulfilled,
+ * this simply passes it forward.
+ */
+SyncPromise.prototype.catch = function(onRejected)
+{
+  return this.then(undefined, onRejected);
+};
+
+/**
+ * Return a new SyncPromise which is already fulfilled to the given value.
+ * @param {any} value The value of the promise.
+ */
+SyncPromise.resolve = function(value)
+{
+  return new SyncPromise(value, false);
+};
+
+/**
+ * Return a new SyncPromise which is already rejected with the given error.
+ * @param {any} err The error for the rejected promise.
+ */
+SyncPromise.reject = function(err)
+{
+  return new SyncPromise(err, true);
+};
+
+/**
+ * This static method checks if the promise is a SyncPromise and immediately
+ * returns its value or throws the error if promise is rejected. If promise is
+ * not a SyncPromise, this throws an exception since it is not possible to
+ * immediately get the value. This can be used with "promise-based" code which
+ * you expect to always return a SyncPromise to operate in synchronous mode.
+ * @param {SyncPromise} promise The SyncPromise with the value to get.
+ * @return {any} The value of the promise.
+ * @throws Error If promise is not a SyncPromise.
+ * @throws any If promise is a SyncPromise in the rejected state, this throws
+ * the error.
+ */
+SyncPromise.getValue = function(promise)
+{
+  if (promise instanceof SyncPromise) {
+    if (promise.isRejected)
+      throw promise.value;
+    else
+      return promise.value;
+  }
+  else
+    throw new Error("Cannot return immediately because promise is not a SyncPromise");
+};
+
+/**
+ * This can be called with complete(onComplete, promise) or
+ * complete(onComplete, onError, promise) to handle both synchronous and
+ * asynchronous code based on whether the caller supplies the onComlete callback.
+ * If onComplete is defined, call promise.then with a function which calls
+ * onComplete(value) when fulfilled (possibly in asynchronous mode). If
+ * onComplete is undefined, then we are in synchronous mode so return
+ * SyncPromise.getValue(promise) which will throw an exception if the promise is
+ * not a SyncPromise (or is a SyncPromise in the rejected state).
+ * @param {function} onComplete If defined, this calls promise.then to fulfill
+ * the promise, then calls onComplete(value) with the value of the promise.
+ * If onComplete is undefined, the return value is described below.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an error when this calls promise.then, this calls
+ * onError(err) with the value of the error. If onComplete is undefined, then
+ * onError is ignored and this will call SyncPromise.getValue(promise) which may
+ * throw an exception.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {Promise|SyncPromise} promise If onComplete is defined, this calls
+ * promise.then. Otherwise, this calls SyncPromise.getValue(promise).
+ * @return {any} If onComplete is undefined, return SyncPromise.getValue(promise).
+ * Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * @throws Error If onComplete is undefined and promise is not a SyncPromise.
+ * @throws any If onComplete is undefined and promise is a SyncPromise in the
+ * rejected state.
+ */
+SyncPromise.complete = function(onComplete, onErrorOrPromise, promise)
+{
+  var onError;
+  if (promise)
+    onError = onErrorOrPromise;
+  else {
+    promise = onErrorOrPromise;
+    onError = null;
+  }
+
+  if (onComplete)
+    promise
+    .then(function(value) {
+      try {
+        onComplete(value);
+      } catch (ex) {
+        console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }, function(err) {
+      if (onError) {
+        try {
+          onError(err);
+        } catch (ex) {
+          console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+      else {
+        if (promise instanceof SyncPromise)
+          throw err;
+        else
+          // We are in an async promise callback, so a thrown exception won't
+          // reach the caller. Just log it.
+          console.log("Uncaught exception from a Promise: " +
+            NdnCommon.getErrorWithStackTrace(err));
+      }
+    });
+  else
+    return SyncPromise.getValue(promise);
+};
+/**
+ * This class contains utilities to help parse the data
+ *
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A DataUtils has static methods for converting data.
+ * @constructor
+ */
+var DataUtils = {};
+
+exports.DataUtils = DataUtils;
+
+/*
+ * NOTE THIS IS CURRENTLY NOT BEING USED
+ *
+ */
+
+DataUtils.keyStr = "ABCDEFGHIJKLMNOP" +
+                   "QRSTUVWXYZabcdef" +
+                   "ghijklmnopqrstuv" +
+                   "wxyz0123456789+/" +
+                   "=";
+
+/**
+ * Raw String to Base 64
+ */
+DataUtils.stringtoBase64 = function stringtoBase64(input)
+{
+   //input = escape(input);
+   var output = "";
+   var chr1, chr2, chr3 = "";
+   var enc1, enc2, enc3, enc4 = "";
+   var i = 0;
+
+   do {
+    chr1 = input.charCodeAt(i++);
+    chr2 = input.charCodeAt(i++);
+    chr3 = input.charCodeAt(i++);
+
+    enc1 = chr1 >> 2;
+    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+    enc4 = chr3 & 63;
+
+    if (isNaN(chr2))
+       enc3 = enc4 = 64;
+    else if (isNaN(chr3))
+       enc4 = 64;
+
+    output = output +
+       DataUtils.keyStr.charAt(enc1) +
+       DataUtils.keyStr.charAt(enc2) +
+       DataUtils.keyStr.charAt(enc3) +
+       DataUtils.keyStr.charAt(enc4);
+    chr1 = chr2 = chr3 = "";
+    enc1 = enc2 = enc3 = enc4 = "";
+   } while (i < input.length);
+
+   return output;
+};
+
+/**
+ * Base 64 to Raw String
+ */
+DataUtils.base64toString = function base64toString(input)
+{
+  var output = "";
+  var chr1, chr2, chr3 = "";
+  var enc1, enc2, enc3, enc4 = "";
+  var i = 0;
+
+  // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+  var base64test = /[^A-Za-z0-9\+\/\=]/g;
+  /* Test for invalid characters. */
+  if (base64test.exec(input)) {
+    alert("There were invalid base64 characters in the input text.\n" +
+          "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
+          "Expect errors in decoding.");
+  }
+
+  input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+  do {
+    enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
+    enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
+    enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
+    enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));
+
+    chr1 = (enc1 << 2) | (enc2 >> 4);
+    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+    chr3 = ((enc3 & 3) << 6) | enc4;
+
+    output = output + String.fromCharCode(chr1);
+
+    if (enc3 != 64)
+      output = output + String.fromCharCode(chr2);
+
+    if (enc4 != 64)
+      output = output + String.fromCharCode(chr3);
+
+    chr1 = chr2 = chr3 = "";
+    enc1 = enc2 = enc3 = enc4 = "";
+  } while (i < input.length);
+
+  return output;
+};
+
+/**
+ * Buffer to Hex String
+ */
+DataUtils.toHex = function(buffer)
+{
+  return buffer.toString('hex');
+};
+
+/**
+ * Raw string to hex string.
+ */
+DataUtils.stringToHex = function(args)
+{
+  var ret = "";
+  for (var i = 0; i < args.length; ++i) {
+    var value = args.charCodeAt(i);
+    ret += (value < 16 ? "0" : "") + value.toString(16);
+  }
+  return ret;
+};
+
+/**
+ * Buffer to raw string.
+ */
+DataUtils.toString = function(buffer)
+{
+  return buffer.toString('binary');
+};
+
+/**
+ * Hex String to Buffer.
+ */
+DataUtils.toNumbers = function(str)
+{
+  return new Buffer(str, 'hex');
+};
+
+/**
+ * Hex String to raw string.
+ */
+DataUtils.hexToRawString = function(str)
+{
+  if (typeof str =='string') {
+  var ret = "";
+  str.replace(/(..)/g, function(s) {
+    ret += String.fromCharCode(parseInt(s, 16));
+  });
+  return ret;
+  }
+};
+
+/**
+ * Raw String to Buffer.
+ */
+DataUtils.toNumbersFromString = function(str)
+{
+  return new Buffer(str, 'binary');
+};
+
+/**
+ * If value is a string, then interpret it as a raw string and convert to
+ * a Buffer. Otherwise assume it is a Buffer or array type and just return it.
+ * @param {string|any} value
+ * @return {Buffer}
+ */
+DataUtils.toNumbersIfString = function(value)
+{
+  if (typeof value === 'string')
+    return new Buffer(value, 'binary');
+  else
+    return value;
+};
+
+/**
+ * Encode str as utf8 and return as Buffer.
+ */
+DataUtils.stringToUtf8Array = function(str)
+{
+  return new Buffer(str, 'utf8');
+};
+
+/**
+ * arrays is an array of Buffer. Return a new Buffer which is the concatenation of all.
+ */
+DataUtils.concatArrays = function(arrays)
+{
+  return Buffer.concat(arrays);
+};
+
+// TODO: Take Buffer and use TextDecoder when available.
+DataUtils.decodeUtf8 = function(utftext)
+{
+  var string = "";
+  var i = 0;
+  var c = 0;
+    var c1 = 0;
+    var c2 = 0;
+
+  while (i < utftext.length) {
+    c = utftext.charCodeAt(i);
+
+    if (c < 128) {
+      string += String.fromCharCode(c);
+      i++;
+    }
+    else if (c > 191 && c < 224) {
+      c2 = utftext.charCodeAt(i + 1);
+      string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+      i += 2;
+    }
+    else {
+      c2 = utftext.charCodeAt(i+1);
+      var c3 = utftext.charCodeAt(i+2);
+      string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+      i += 3;
+    }
+  }
+
+  return string;
+};
+
+/**
+ * Return true if a1 and a2 are the same length with equal elements.
+ */
+DataUtils.arraysEqual = function(a1, a2)
+{
+  // A simple sanity check that it is an array.
+  if (!a1.slice)
+    throw new Error("DataUtils.arraysEqual: a1 is not an array");
+  if (!a2.slice)
+    throw new Error("DataUtils.arraysEqual: a2 is not an array");
+
+  if (a1.length != a2.length)
+    return false;
+
+  for (var i = 0; i < a1.length; ++i) {
+    if (a1[i] != a2[i])
+      return false;
+  }
+
+  return true;
+};
+
+/**
+ * Convert the big endian Buffer to an unsigned int.
+ * Don't check for overflow.
+ */
+DataUtils.bigEndianToUnsignedInt = function(bytes)
+{
+  var result = 0;
+  for (var i = 0; i < bytes.length; ++i) {
+    // Multiply by 0x100 instead of shift by 8 because << is restricted to 32 bits.
+    result *= 0x100;
+    result += bytes[i];
+  }
+  return result;
+};
+
+/**
+ * Convert the int value to a new big endian Buffer and return.
+ * If value is 0 or negative, return new Buffer(0).
+ */
+DataUtils.nonNegativeIntToBigEndian = function(value)
+{
+  value = Math.round(value);
+  if (value <= 0)
+    return new Buffer(0);
+
+  // Assume value is not over 64 bits.
+  var size = 8;
+  var result = new Buffer(size);
+  var i = 0;
+  while (value != 0) {
+    ++i;
+    result[size - i] = value & 0xff;
+    // Divide by 0x100 and floor instead of shift by 8 because >> is restricted to 32 bits.
+    value = Math.floor(value / 0x100);
+  }
+  return result.slice(size - i, size);
+};
+
+/**
+ * Modify array to randomly shuffle the elements.
+ */
+DataUtils.shuffle = function(array)
+{
+  for (var i = array.length - 1; i >= 1; --i) {
+    // j is from 0 to i.
+    var j = Math.floor(Math.random() * (i + 1));
+    var temp = array[i];
+    array[i] = array[j];
+    array[j] = temp;
+  }
+};
+
+/**
+ * Decode the base64-encoded private key PEM and return the binary DER.
+ * @param {string} The PEM-encoded private key.
+ * @return {Buffer} The binary DER.
+ *
+ */
+DataUtils.privateKeyPemToDer = function(privateKeyPem)
+{
+  // Remove the '-----XXX-----' from the beginning and the end of the key and
+  // also remove any \n in the key string.
+  var lines = privateKeyPem.split('\n');
+  var privateKey = "";
+  for (var i = 1; i < lines.length - 1; i++)
+    privateKey += lines[i];
+
+  return new Buffer(privateKey, 'base64');
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a new DecodingException wrapping the given error object.
+ * Call with: throw new DecodingException(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+function DecodingException(error)
+{
+  if (error) {
+    error.__proto__ = DecodingException.prototype;
+    return error;
+  }
+}
+DecodingException.prototype = new Error();
+DecodingException.prototype.name = "DecodingException";
+
+exports.DecodingException = DecodingException;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * The Tlv class has static type codes for the NDN-TLV wire format.
+ * @constructor
+ */
+var Tlv = function Tlv()
+{
+};
+
+exports.Tlv = Tlv;
+
+Tlv.Interest =         5;
+Tlv.Data =             6;
+Tlv.Name =             7;
+Tlv.ImplicitSha256DigestComponent = 1;
+Tlv.NameComponent =    8;
+Tlv.Selectors =        9;
+Tlv.Nonce =            10;
+// <Unassigned> =      11;
+Tlv.InterestLifetime = 12;
+Tlv.MinSuffixComponents = 13;
+Tlv.MaxSuffixComponents = 14;
+Tlv.PublisherPublicKeyLocator = 15;
+Tlv.Exclude =          16;
+Tlv.ChildSelector =    17;
+Tlv.MustBeFresh =      18;
+Tlv.Any =              19;
+Tlv.MetaInfo =         20;
+Tlv.Content =          21;
+Tlv.SignatureInfo =    22;
+Tlv.SignatureValue =   23;
+Tlv.ContentType =      24;
+Tlv.FreshnessPeriod =  25;
+Tlv.FinalBlockId =     26;
+Tlv.SignatureType =    27;
+Tlv.KeyLocator =       28;
+Tlv.KeyLocatorDigest = 29;
+Tlv.SelectedDelegation = 32;
+Tlv.FaceInstance =     128;
+Tlv.ForwardingEntry =  129;
+Tlv.StatusResponse =   130;
+Tlv.Action =           131;
+Tlv.FaceID =           132;
+Tlv.IPProto =          133;
+Tlv.Host =             134;
+Tlv.Port =             135;
+Tlv.MulticastInterface = 136;
+Tlv.MulticastTTL =     137;
+Tlv.ForwardingFlags =  138;
+Tlv.StatusCode =       139;
+Tlv.StatusText =       140;
+
+Tlv.SignatureType_DigestSha256 = 0;
+Tlv.SignatureType_SignatureSha256WithRsa = 1;
+Tlv.SignatureType_SignatureSha256WithEcdsa = 3;
+Tlv.SignatureType_SignatureHmacWithSha256 = 4;
+
+Tlv.ContentType_Default = 0;
+Tlv.ContentType_Link =    1;
+Tlv.ContentType_Key =     2;
+
+Tlv.NfdCommand_ControlResponse = 101;
+Tlv.NfdCommand_StatusCode =      102;
+Tlv.NfdCommand_StatusText =      103;
+
+Tlv.ControlParameters_ControlParameters =   104;
+Tlv.ControlParameters_FaceId =              105;
+Tlv.ControlParameters_Uri =                 114;
+Tlv.ControlParameters_LocalControlFeature = 110;
+Tlv.ControlParameters_Origin =              111;
+Tlv.ControlParameters_Cost =                106;
+Tlv.ControlParameters_Flags =               108;
+Tlv.ControlParameters_Strategy =            107;
+Tlv.ControlParameters_ExpirationPeriod =    109;
+
+Tlv.LpPacket_LpPacket =        100;
+Tlv.LpPacket_Fragment =         80;
+Tlv.LpPacket_Sequence =         81;
+Tlv.LpPacket_FragIndex =        82;
+Tlv.LpPacket_FragCount =        83;
+Tlv.LpPacket_Nack =            800;
+Tlv.LpPacket_NackReason =      801;
+Tlv.LpPacket_NextHopFaceId =   816;
+Tlv.LpPacket_IncomingFaceId =  817;
+Tlv.LpPacket_CachePolicy =     820;
+Tlv.LpPacket_CachePolicyType = 821;
+Tlv.LpPacket_IGNORE_MIN =      800;
+Tlv.LpPacket_IGNORE_MAX =      959;
+
+Tlv.Link_Preference = 30;
+Tlv.Link_Delegation = 31;
+
+Tlv.Encrypt_EncryptedContent = 130;
+Tlv.Encrypt_EncryptionAlgorithm = 131;
+Tlv.Encrypt_EncryptedPayload = 132;
+Tlv.Encrypt_InitialVector = 133;
+
+// For RepetitiveInterval.
+Tlv.Encrypt_StartDate = 134;
+Tlv.Encrypt_EndDate = 135;
+Tlv.Encrypt_IntervalStartHour = 136;
+Tlv.Encrypt_IntervalEndHour = 137;
+Tlv.Encrypt_NRepeats = 138;
+Tlv.Encrypt_RepeatUnit = 139;
+Tlv.Encrypt_RepetitiveInterval = 140;
+
+// For Schedule.
+Tlv.Encrypt_WhiteIntervalList = 141;
+Tlv.Encrypt_BlackIntervalList = 142;
+Tlv.Encrypt_Schedule = 143;
+
+/**
+ * Strip off the lower 32 bits of x and divide by 2^32, returning the "high
+ * bytes" above 32 bits.  This is necessary because JavaScript << and >> are
+ * restricted to 32 bits.
+ * (This could be a general function, but we define it here so that the
+ * Tlv encoder/decoder is self-contained.)
+ * @param {number} x
+ * @return {number}
+ */
+Tlv.getHighBytes = function(x)
+{
+  // Don't use floor because we expect the caller to use & and >> on the result
+  // which already strip off the fraction.
+  return (x - (x % 0x100000000)) / 0x100000000;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DynamicBuffer = require('../../util/dynamic-buffer.js').DynamicBuffer; /** @ignore */
+var Tlv = require('./tlv.js').Tlv;
+
+/**
+ * Create a new TlvEncoder with an initialCapacity for the encoding buffer.
+ * @constructor
+ * @param {number} initialCapacity (optional) The initial capacity of the
+ * encoding buffer. If omitted, use a default value.
+ */
+var TlvEncoder = function TlvEncoder(initialCapacity)
+{
+  initialCapacity = initialCapacity || 16;
+  this.output = new DynamicBuffer(initialCapacity);
+  // length is the number of bytes that have been written to the back of
+  //  this.output.array.
+  this.length = 0;
+};
+
+exports.TlvEncoder = TlvEncoder;
+
+/**
+ * Get the number of bytes that have been written to the output.  You can
+ * save this number, write sub TLVs, then subtract the new length from this
+ * to get the total length of the sub TLVs.
+ * @return {number} The number of bytes that have been written to the output.
+ */
+TlvEncoder.prototype.getLength = function()
+{
+  return this.length;
+};
+
+/**
+ * Encode varNumber as a VAR-NUMBER in NDN-TLV and write it to this.output just
+ * before this.length from the back.  Advance this.length.
+ * @param {number} varNumber The non-negative number to encode.
+ */
+TlvEncoder.prototype.writeVarNumber = function(varNumber)
+{
+  if (varNumber < 253) {
+    this.length += 1;
+    this.output.ensureLengthFromBack(this.length);
+    this.output.array[this.output.array.length - this.length] = varNumber & 0xff;
+  }
+  else if (varNumber <= 0xffff) {
+    this.length += 3;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset] = 253;
+    this.output.array[offset + 1] = (varNumber >> 8) & 0xff;
+    this.output.array[offset + 2] = varNumber & 0xff;
+  }
+  else if (varNumber <= 0xffffffff) {
+    this.length += 5;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset] = 254;
+    this.output.array[offset + 1] = (varNumber >> 24) & 0xff;
+    this.output.array[offset + 2] = (varNumber >> 16) & 0xff;
+    this.output.array[offset + 3] = (varNumber >> 8) & 0xff;
+    this.output.array[offset + 4] = varNumber & 0xff;
+  }
+  else {
+    this.length += 9;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset] = 255;
+    var highBytes = Tlv.getHighBytes(varNumber);
+    this.output.array[offset + 1] = (highBytes >> 24) & 0xff;
+    this.output.array[offset + 2] = (highBytes >> 16) & 0xff;
+    this.output.array[offset + 3] = (highBytes >> 8)  & 0xff;
+    this.output.array[offset + 4] = (highBytes)       & 0xff;
+    this.output.array[offset + 5] = (varNumber >> 24) & 0xff;
+    this.output.array[offset + 6] = (varNumber >> 16) & 0xff;
+    this.output.array[offset + 7] = (varNumber >> 8) & 0xff;
+    this.output.array[offset + 8] = varNumber & 0xff;
+  }
+};
+
+/**
+ * Encode the type and length as VAR-NUMBER and write to this.output just before
+ * this.length from the back.  Advance this.length.
+ * @param {number} type The type of the TLV.
+ * @param {number} length The non-negative length of the TLV.
+ */
+TlvEncoder.prototype.writeTypeAndLength = function(type, length)
+{
+  // Write backwards.
+  this.writeVarNumber(length);
+  this.writeVarNumber(type);
+};
+
+/**
+ * Write value as a non-negative integer and write it to this.output just before
+ * this.length from the back. Advance this.length.
+ * @param {number} value The non-negative integer to encode.
+ */
+TlvEncoder.prototype.writeNonNegativeInteger = function(value)
+{
+  if (value < 0)
+    throw new Error("TLV integer value may not be negative");
+
+  // JavaScript doesn't distinguish int from float, so round.
+  value = Math.round(value);
+
+  if (value <= 0xff) {
+    this.length += 1;
+    this.output.ensureLengthFromBack(this.length);
+    this.output.array[this.output.array.length - this.length] = value & 0xff;
+  }
+  else if (value <= 0xffff) {
+    this.length += 2;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset]     = (value >> 8) & 0xff;
+    this.output.array[offset + 1] = value & 0xff;
+  }
+  else if (value <= 0xffffffff) {
+    this.length += 4;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    this.output.array[offset]     = (value >> 24) & 0xff;
+    this.output.array[offset + 1] = (value >> 16) & 0xff;
+    this.output.array[offset + 2] = (value >> 8) & 0xff;
+    this.output.array[offset + 3] = value & 0xff;
+  }
+  else {
+    this.length += 8;
+    this.output.ensureLengthFromBack(this.length);
+    var offset = this.output.array.length - this.length;
+    var highBytes = Tlv.getHighBytes(value);
+    this.output.array[offset]     = (highBytes >> 24) & 0xff;
+    this.output.array[offset + 1] = (highBytes >> 16) & 0xff;
+    this.output.array[offset + 2] = (highBytes >> 8)  & 0xff;
+    this.output.array[offset + 3] = (highBytes)       & 0xff;
+    this.output.array[offset + 4] = (value >> 24) & 0xff;
+    this.output.array[offset + 5] = (value >> 16) & 0xff;
+    this.output.array[offset + 6] = (value >> 8) & 0xff;
+    this.output.array[offset + 7] = value & 0xff;
+  }
+};
+
+/**
+ * Write the type, then the length of the encoded value then encode value as a
+ * non-negative integer and write it to this.output just before this.length from
+ * the back. Advance this.length.
+ * @param {number} type The type of the TLV.
+ * @param {number} value The non-negative integer to encode.
+ */
+TlvEncoder.prototype.writeNonNegativeIntegerTlv = function(type, value)
+{
+  // Write backwards.
+  var saveNBytes = this.length;
+  this.writeNonNegativeInteger(value);
+  this.writeTypeAndLength(type, this.length - saveNBytes);
+};
+
+/**
+ * If value is negative or null then do nothing, otherwise call
+ * writeNonNegativeIntegerTlv.
+ * @param {number} type The type of the TLV.
+ * @param {number} value If negative or null do nothing, otherwise the integer
+ *   to encode.
+ */
+TlvEncoder.prototype.writeOptionalNonNegativeIntegerTlv = function(type, value)
+{
+  if (value != null && value >= 0)
+    this.writeNonNegativeIntegerTlv(type, value);
+};
+
+/**
+ * Write the buffer value to this.output just before this.length from the back.
+ * Advance this.length.
+ * @param {Buffer} buffer The byte array with the bytes to write.  If value is
+ * null, then do nothing.
+ */
+TlvEncoder.prototype.writeBuffer = function(buffer)
+{
+  if (buffer == null)
+    return;
+
+  this.length += buffer.length;
+  this.output.copyFromBack(buffer, this.length);
+};
+
+/**
+ * Write the type, then the length of the buffer then the buffer value to
+ * this.output just before this.length from the back. Advance this.length.
+ * @param {number} type The type of the TLV.
+ * @param {Buffer} value The byte array with the bytes of the blob.  If value is
+    null, then just write the type and length 0.
+ */
+TlvEncoder.prototype.writeBlobTlv = function(type, value)
+{
+  if (value == null) {
+    this.writeTypeAndLength(type, 0);
+    return;
+  }
+
+  // Write backwards, starting with the blob array.
+  this.writeBuffer(value);
+  this.writeTypeAndLength(type, value.length);
+};
+
+/**
+ * If the byte array is null or zero length then do nothing, otherwise call
+ * writeBlobTlv.
+ * @param {number} type The type of the TLV.
+ * @param {Buffer} value If null or zero length do nothing, otherwise the byte
+ * array with the bytes of the blob.
+ */
+TlvEncoder.prototype.writeOptionalBlobTlv = function(type, value)
+{
+  if (value != null && value.length > 0)
+    this.writeBlobTlv(type, value);
+};
+
+/**
+ * Get a slice of the encoded bytes.
+ * @return {Buffer} A slice backed by the encoding Buffer.
+ */
+TlvEncoder.prototype.getOutput = function()
+{
+  return this.output.array.slice(this.output.array.length - this.length);
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DecodingException = require('../decoding-exception.js').DecodingException;
+
+/**
+ * Create a new TlvDecoder for decoding the input in the NDN-TLV wire format.
+ * @constructor
+ * @param {Buffer} input The buffer with the bytes to decode.
+ */
+var TlvDecoder = function TlvDecoder(input)
+{
+  this.input = input;
+  this.offset = 0;
+};
+
+exports.TlvDecoder = TlvDecoder;
+
+/**
+ * Decode VAR-NUMBER in NDN-TLV and return it. Update offset.
+ * @return {number} The decoded VAR-NUMBER.
+ */
+TlvDecoder.prototype.readVarNumber = function()
+{
+  // Assume array values are in the range 0 to 255.
+  var firstOctet = this.input[this.offset];
+  this.offset += 1;
+  if (firstOctet < 253)
+    return firstOctet;
+  else
+    return this.readExtendedVarNumber(firstOctet);
+};
+
+/**
+ * A private function to do the work of readVarNumber, given the firstOctet
+ * which is >= 253.
+ * @param {number} firstOctet The first octet which is >= 253, used to decode
+ * the remaining bytes.
+ * @return {number} The decoded VAR-NUMBER.
+ */
+TlvDecoder.prototype.readExtendedVarNumber = function(firstOctet)
+{
+  var result;
+  // This is a private function so we know firstOctet >= 253.
+  if (firstOctet == 253) {
+    result = ((this.input[this.offset] << 8) +
+           this.input[this.offset + 1]);
+    this.offset += 2;
+  }
+  else if (firstOctet == 254) {
+    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
+    result = (Math.abs(this.input[this.offset] << 24) +
+          (this.input[this.offset + 1] << 16) +
+          (this.input[this.offset + 2] << 8) +
+           this.input[this.offset + 3]);
+    this.offset += 4;
+  }
+  else {
+    // Get the high byte first because JavaScript << is restricted to 32 bits.
+    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
+    var highByte = Math.abs(this.input[this.offset] << 24) +
+                           (this.input[this.offset + 1] << 16) +
+                           (this.input[this.offset + 2] << 8) +
+                            this.input[this.offset + 3];
+    result = (highByte * 0x100000000 +
+          (this.input[this.offset + 4] << 24) +
+          (this.input[this.offset + 5] << 16) +
+          (this.input[this.offset + 6] << 8) +
+           this.input[this.offset + 7]);
+    this.offset += 8;
+  }
+
+  return result;
+};
+
+/**
+ * Decode the type and length from this's input starting at offset, expecting
+ * the type to be expectedType and return the length. Update offset.  Also make
+ * sure the decoded length does not exceed the number of bytes remaining in the
+ * input.
+ * @param {number} expectedType The expected type.
+ * @return {number} The length of the TLV.
+ * @throws DecodingException if (did not get the expected TLV type or the TLV length
+ * exceeds the buffer length.
+ */
+TlvDecoder.prototype.readTypeAndLength = function(expectedType)
+{
+  var type = this.readVarNumber();
+  if (type != expectedType)
+    throw new DecodingException(new Error("Did not get the expected TLV type"));
+
+  var length = this.readVarNumber();
+  if (this.offset + length > this.input.length)
+    throw new DecodingException(new Error("TLV length exceeds the buffer length"));
+
+  return length;
+};
+
+/**
+ * Decode the type and length from the input starting at offset, expecting the
+ * type to be expectedType.  Update offset.  Also make sure the decoded length
+ * does not exceed the number of bytes remaining in the input. Return the offset
+ * of the end of this parent TLV, which is used in decoding optional nested
+ * TLVs. After reading all nested TLVs, call finishNestedTlvs.
+ * @param {number} expectedType The expected type.
+ * @return {number} The offset of the end of the parent TLV.
+ * @throws DecodingException if did not get the expected TLV type or the TLV
+ * length exceeds the buffer length.
+ */
+TlvDecoder.prototype.readNestedTlvsStart = function(expectedType)
+{
+  return this.readTypeAndLength(expectedType) + this.offset;
+};
+
+/**
+ * Call this after reading all nested TLVs to skip any remaining unrecognized
+ * TLVs and to check if the offset after the final nested TLV matches the
+ * endOffset returned by readNestedTlvsStart.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @throws DecodingException if the TLV length does not equal the total length
+ * of the nested TLVs.
+ */
+TlvDecoder.prototype.finishNestedTlvs = function(endOffset)
+{
+  // We expect offset to be endOffset, so check this first.
+  if (this.offset == endOffset)
+    return;
+
+  // Skip remaining TLVs.
+  while (this.offset < endOffset) {
+    // Skip the type VAR-NUMBER.
+    this.readVarNumber();
+    // Read the length and update offset.
+    var length = this.readVarNumber();
+    this.offset += length;
+
+    if (this.offset > this.input.length)
+      throw new DecodingException(new Error("TLV length exceeds the buffer length"));
+  }
+
+  if (this.offset != endOffset)
+    throw new DecodingException(new Error
+      ("TLV length does not equal the total length of the nested TLVs"));
+};
+
+/**
+ * Decode the type from this's input starting at offset, and if it is the
+ * expectedType, then return true, else false.  However, if this's offset is
+ * greater than or equal to endOffset, then return false and don't try to read
+ * the type. Do not update offset.
+ * @param {number} expectedType The expected type.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @return {boolean} true if the type of the next TLV is the expectedType,
+ *  otherwise false.
+ */
+TlvDecoder.prototype.peekType = function(expectedType, endOffset)
+{
+  if (this.offset >= endOffset)
+    // No more sub TLVs to look at.
+    return false;
+  else {
+    var saveOffset = this.offset;
+    var type = this.readVarNumber();
+    // Restore offset.
+    this.offset = saveOffset;
+
+    return type == expectedType;
+  }
+};
+
+/**
+ * Decode a non-negative integer in NDN-TLV and return it. Update offset by
+ * length.
+ * @param {number} length The number of bytes in the encoded integer.
+ * @return {number} The integer.
+ * @throws DecodingException if length is an invalid length for a TLV
+ * non-negative integer.
+ */
+TlvDecoder.prototype.readNonNegativeInteger = function(length)
+{
+  var result;
+  if (length == 1)
+    result = this.input[this.offset];
+  else if (length == 2)
+    result = ((this.input[this.offset] << 8) +
+           this.input[this.offset + 1]);
+  else if (length == 4)
+    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
+    result = (Math.abs(this.input[this.offset] << 24) +
+          (this.input[this.offset + 1] << 16) +
+          (this.input[this.offset + 2] << 8) +
+           this.input[this.offset + 3]);
+  else if (length == 8) {
+    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
+    var highByte = Math.abs(this.input[this.offset] << 24) +
+                       (this.input[this.offset + 1] << 16) +
+                       (this.input[this.offset + 2] << 8) +
+                        this.input[this.offset + 3];
+    result = (highByte * 0x100000000 +
+          Math.abs(this.input[this.offset + 4] << 24) +
+          (this.input[this.offset + 5] << 16) +
+          (this.input[this.offset + 6] << 8) +
+           this.input[this.offset + 7]);
+  }
+  else
+    throw new DecodingException(new Error("Invalid length for a TLV nonNegativeInteger"));
+
+  this.offset += length;
+  return result;
+};
+
+/**
+ * Decode the type and length from this's input starting at offset, expecting
+ * the type to be expectedType. Then decode a non-negative integer in NDN-TLV
+ * and return it.  Update offset.
+ * @param {number} expectedType The expected type.
+ * @return {number} The integer.
+ * @throws DecodingException if did not get the expected TLV type or can't
+ * decode the value.
+ */
+TlvDecoder.prototype.readNonNegativeIntegerTlv = function(expectedType)
+{
+  var length = this.readTypeAndLength(expectedType);
+  return this.readNonNegativeInteger(length);
+};
+
+/**
+ * Peek at the next TLV, and if it has the expectedType then call
+ * readNonNegativeIntegerTlv and return the integer.  Otherwise, return null.
+ * However, if this's offset is greater than or equal to endOffset, then return
+ * null and don't try to read the type.
+ * @param {number} expectedType The expected type.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @return {number} The integer or null if the next TLV doesn't have the
+ * expected type.
+ */
+TlvDecoder.prototype.readOptionalNonNegativeIntegerTlv = function
+  (expectedType, endOffset)
+{
+  if (this.peekType(expectedType, endOffset))
+    return this.readNonNegativeIntegerTlv(expectedType);
+  else
+    return null;
+};
+
+/**
+ * Decode the type and length from this's input starting at offset, expecting
+ * the type to be expectedType. Then return an array of the bytes in the value.
+ * Update offset.
+ * @param {number} expectedType The expected type.
+ * @return {Buffer} The bytes in the value as a slice on the buffer.  This is
+ * not a copy of the bytes in the input buffer.  If you need a copy, then you
+ * must make a copy of the return value.
+ * @throws DecodingException if did not get the expected TLV type.
+ */
+TlvDecoder.prototype.readBlobTlv = function(expectedType)
+{
+  var length = this.readTypeAndLength(expectedType);
+  var result = this.input.slice(this.offset, this.offset + length);
+
+  // readTypeAndLength already checked if length exceeds the input buffer.
+  this.offset += length;
+  return result;
+};
+
+/**
+ * Peek at the next TLV, and if it has the expectedType then call readBlobTlv
+ * and return the value.  Otherwise, return null. However, if this's offset is
+ * greater than or equal to endOffset, then return null and don't try to read
+ * the type.
+ * @param {number} expectedType The expected type.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @return {Buffer} The bytes in the value as a slice on the buffer or null if
+ * the next TLV doesn't have the expected type.  This is not a copy of the bytes
+ * in the input buffer.  If you need a copy, then you must make a copy of the
+ * return value.
+ */
+TlvDecoder.prototype.readOptionalBlobTlv = function(expectedType, endOffset)
+{
+  if (this.peekType(expectedType, endOffset))
+    return this.readBlobTlv(expectedType);
+  else
+    return null;
+};
+
+/**
+ * Peek at the next TLV, and if it has the expectedType then read a type and
+ * value, ignoring the value, and return true. Otherwise, return false.
+ * However, if this's offset is greater than or equal to endOffset, then return
+ * false and don't try to read the type.
+ * @param {number} expectedType The expected type.
+ * @param {number} endOffset The offset of the end of the parent TLV, returned
+ * by readNestedTlvsStart.
+ * @return {boolean} true, or else false if the next TLV doesn't have the
+ * expected type.
+ */
+TlvDecoder.prototype.readBooleanTlv = function(expectedType, endOffset)
+{
+  if (this.peekType(expectedType, endOffset)) {
+    var length = this.readTypeAndLength(expectedType);
+    // We expect the length to be 0, but update offset anyway.
+    this.offset += length;
+    return true;
+  }
+  else
+    return false;
+};
+
+/**
+ * Get the offset into the input, used for the next read.
+ * @return {number} The offset.
+ */
+TlvDecoder.prototype.getOffset = function()
+{
+  return this.offset;
+};
+
+/**
+ * Set the offset into the input, used for the next read.
+ * @param {number} offset The new offset.
+ */
+TlvDecoder.prototype.seek = function(offset)
+{
+  this.offset = offset;
+};
+
+/**
+ * Return an array of a slice of the input for the given offset range.
+ * @param {number} beginOffset The offset in the input of the beginning of the
+ * slice.
+ * @param {number} endOffset The offset in the input of the end of the slice.
+ * @return {Buffer} The bytes in the value as a slice on the buffer.  This is
+ * not a copy of the bytes in the input buffer.  If you need a copy, then you
+ * must make a copy of the return value.
+ */
+TlvDecoder.prototype.getSlice = function(beginOffset, endOffset)
+{
+  return this.input.slice(beginOffset, endOffset);
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var TlvDecoder = require('./tlv-decoder.js').TlvDecoder;
+
+/**
+ * A TlvStructureDecoder finds the end of an NDN-TLV element, even if the
+ * element is supplied in parts.
+ * Create and initialize a TlvStructureDecoder.
+ * @constructor
+ */
+var TlvStructureDecoder = function TlvStructureDecoder()
+{
+  this.gotElementEnd_ = false;
+  this.offset_ = 0;
+  this.state_ = TlvStructureDecoder.READ_TYPE;
+  this.headerLength_ = 0;
+  this.useHeaderBuffer_ = false;
+  // 8 bytes is enough to hold the extended bytes in the length encoding
+  // where it is an 8-byte number.
+  this.headerBuffer_ = new Buffer(8);
+  this.nBytesToRead_ = 0;
+};
+
+exports.TlvStructureDecoder = TlvStructureDecoder;
+
+TlvStructureDecoder.READ_TYPE =         0;
+TlvStructureDecoder.READ_TYPE_BYTES =   1;
+TlvStructureDecoder.READ_LENGTH =       2;
+TlvStructureDecoder.READ_LENGTH_BYTES = 3;
+TlvStructureDecoder.READ_VALUE_BYTES =  4;
+
+/**
+ * Continue scanning input starting from this.offset_ to find the element end.
+ * If the end of the element which started at offset 0 is found, this returns
+ * true and getOffset() is the length of the element.  Otherwise, this returns
+ * false which means you should read more into input and call again.
+ * @param {Buffer} input The input buffer. You have to pass in input each time
+ * because the buffer could be reallocated.
+ * @return {boolean} true if found the element end, false if not.
+ */
+TlvStructureDecoder.prototype.findElementEnd = function(input)
+{
+  if (this.gotElementEnd_)
+    // Someone is calling when we already got the end.
+    return true;
+
+  var decoder = new TlvDecoder(input);
+
+  while (true) {
+    if (this.offset_ >= input.length)
+      // All the cases assume we have some input. Return and wait for more.
+      return false;
+
+    if (this.state_ == TlvStructureDecoder.READ_TYPE) {
+      var firstOctet = input[this.offset_];
+      this.offset_ += 1;
+      if (firstOctet < 253)
+        // The value is simple, so we can skip straight to reading the length.
+        this.state_ = TlvStructureDecoder.READ_LENGTH;
+      else {
+        // Set up to skip the type bytes.
+        if (firstOctet == 253)
+          this.nBytesToRead_ = 2;
+        else if (firstOctet == 254)
+          this.nBytesToRead_ = 4;
+        else
+          // value == 255.
+          this.nBytesToRead_ = 8;
+
+        this.state_ = TlvStructureDecoder.READ_TYPE_BYTES;
+      }
+    }
+    else if (this.state_ == TlvStructureDecoder.READ_TYPE_BYTES) {
+      var nRemainingBytes = input.length - this.offset_;
+      if (nRemainingBytes < this.nBytesToRead_) {
+        // Need more.
+        this.offset_ += nRemainingBytes;
+        this.nBytesToRead_ -= nRemainingBytes;
+        return false;
+      }
+
+      // Got the type bytes. Move on to read the length.
+      this.offset_ += this.nBytesToRead_;
+      this.state_ = TlvStructureDecoder.READ_LENGTH;
+    }
+    else if (this.state_ == TlvStructureDecoder.READ_LENGTH) {
+      var firstOctet = input[this.offset_];
+      this.offset_ += 1;
+      if (firstOctet < 253) {
+        // The value is simple, so we can skip straight to reading
+        //  the value bytes.
+        this.nBytesToRead_ = firstOctet;
+        if (this.nBytesToRead_ == 0) {
+          // No value bytes to read. We're finished.
+          this.gotElementEnd_ = true;
+          return true;
+        }
+
+        this.state_ = TlvStructureDecoder.READ_VALUE_BYTES;
+      }
+      else {
+        // We need to read the bytes in the extended encoding of
+        //  the length.
+        if (firstOctet == 253)
+          this.nBytesToRead_ = 2;
+        else if (firstOctet == 254)
+          this.nBytesToRead_ = 4;
+        else
+          // value == 255.
+          this.nBytesToRead_ = 8;
+
+        // We need to use firstOctet in the next state.
+        this.firstOctet_ = firstOctet;
+        this.state_ = TlvStructureDecoder.READ_LENGTH_BYTES;
+      }
+    }
+    else if (this.state_ == TlvStructureDecoder.READ_LENGTH_BYTES) {
+      var nRemainingBytes = input.length - this.offset_;
+      if (!this.useHeaderBuffer_ && nRemainingBytes >= this.nBytesToRead_) {
+        // We don't have to use the headerBuffer. Set nBytesToRead.
+        decoder.seek(this.offset_);
+
+        this.nBytesToRead_ = decoder.readExtendedVarNumber(this.firstOctet_);
+        // Update this.offset_ to the decoder's offset after reading.
+        this.offset_ = decoder.getOffset();
+      }
+      else {
+        this.useHeaderBuffer_ = true;
+
+        var nNeededBytes = this.nBytesToRead_ - this.headerLength_;
+        if (nNeededBytes > nRemainingBytes) {
+          // We can't get all of the header bytes from this input.
+          // Save in headerBuffer.
+          if (this.headerLength_ + nRemainingBytes > this.headerBuffer_.length)
+            // We don't expect this to happen.
+            throw new Error
+              ("Cannot store more header bytes than the size of headerBuffer");
+          input.slice(this.offset_, this.offset_ + nRemainingBytes).copy
+            (this.headerBuffer_, this.headerLength_);
+          this.offset_ += nRemainingBytes;
+          this.headerLength_ += nRemainingBytes;
+
+          return false;
+        }
+
+        // Copy the remaining bytes into headerBuffer, read the
+        //   length and set nBytesToRead.
+        if (this.headerLength_ + nNeededBytes > this.headerBuffer_.length)
+          // We don't expect this to happen.
+          throw new Error
+            ("Cannot store more header bytes than the size of headerBuffer");
+        input.slice(this.offset_, this.offset_ + nNeededBytes).copy
+          (this.headerBuffer_, this.headerLength_);
+        this.offset_ += nNeededBytes;
+
+        // Use a local decoder just for the headerBuffer.
+        var bufferDecoder = new TlvDecoder(this.headerBuffer_);
+        // Replace nBytesToRead with the length of the value.
+        this.nBytesToRead_ = bufferDecoder.readExtendedVarNumber(this.firstOctet_);
+      }
+
+      if (this.nBytesToRead_ == 0) {
+        // No value bytes to read. We're finished.
+        this.gotElementEnd_ = true;
+        return true;
+      }
+
+      // Get ready to read the value bytes.
+      this.state_ = TlvStructureDecoder.READ_VALUE_BYTES;
+    }
+    else if (this.state_ == TlvStructureDecoder.READ_VALUE_BYTES) {
+      var nRemainingBytes = input.length - this.offset_;
+      if (nRemainingBytes < this.nBytesToRead_) {
+        // Need more.
+        this.offset_ += nRemainingBytes;
+        this.nBytesToRead_ -= nRemainingBytes;
+        return false;
+      }
+
+      // Got the bytes. We're finished.
+      this.offset_ += this.nBytesToRead_;
+      this.gotElementEnd_ = true;
+      return true;
+    }
+    else
+      // We don't expect this to happen.
+      throw new Error("findElementEnd: unrecognized state");
+  }
+};
+
+/**
+ * Get the current offset into the input buffer.
+ * @return {number} The offset.
+ */
+TlvStructureDecoder.prototype.getOffset = function()
+{
+  return this.offset_;
+};
+
+/**
+ * Set the offset into the input, used for the next read.
+ * @param {number} offset The new offset.
+ */
+TlvStructureDecoder.prototype.seek = function(offset)
+{
+  this.offset_ = offset;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var TlvEncoder = require('./tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
+var TlvDecoder = require('./tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+
+/**
+ * ProtobufTlv has static methods to encode and decode an Protobuf Message
+ * object as NDN-TLV. The Protobuf tag value is used as the TLV type code. A
+ * Protobuf message is encoded/decoded as a nested TLV encoding. Protobuf types
+ * uint32, uint64 and enum are encoded/decoded as TLV nonNegativeInteger. (It is
+ * an error if an enum value is negative.) Protobuf types bytes and string are
+ * encoded/decoded as TLV bytes. The Protobuf type bool is encoded/decoded as a
+ * TLV boolean (a zero length value for True, omitted for False). The Protobuf
+ * type double is encoded/decoded as an 8-byte little-endian IEEE 754 double.
+ * Other Protobuf types are an error.
+ *
+ * Protobuf has no "outer" message type, so you need to put your TLV message
+ * inside an outer "typeless" message.
+ * @constructor
+ */
+var ProtobufTlv = function ProtobufTlv()
+{
+};
+
+exports.ProtobufTlv = ProtobufTlv;
+
+// Load ProtoBuf.Reflect.Message.Field dynamically so that protobufjs is optional.
+ProtobufTlv._Field = null;
+ProtobufTlv.establishField = function()
+{
+  if (ProtobufTlv._Field === null) {
     try {
-        var dummy = new Uint8Array(1).subarray(0, 1);
+      // Using protobuf.min.js in the browser.
+      ProtobufTlv._Field = dcodeIO.ProtoBuf.Reflect.Message.Field;
+    }
+    catch (ex) {
+      // Using protobufjs in node.
+      ProtobufTlv._Field = require("protobufjs").Reflect.Message.Field;
+    }
+  }
+}
+
+/**
+ * Encode the Protobuf message object as NDN-TLV. This calls
+ * message.encodeAB() to ensure that all required fields are present and
+ * raises an exception if not. (This does not use the result of toArrayBuffer().)
+ * @param {ProtoBuf.Builder.Message} message The Protobuf message object.
+ * @param {ProtoBuf.Reflect.T} descriptor The reflection descriptor for the
+ * message. For example, if the message is of type "MyNamespace.MyMessage" then
+ * the descriptor is builder.lookup("MyNamespace.MyMessage").
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+ProtobufTlv.encode = function(message, descriptor)
+{
+  ProtobufTlv.establishField();
+
+  message.encodeAB();
+  var encoder = new TlvEncoder();
+  ProtobufTlv._encodeMessageValue(message, descriptor, encoder);
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode the input as NDN-TLV and update the fields of the Protobuf message
+ * object.
+ * @param {ProtoBuf.Builder.Message} message The Protobuf message object. This
+ * does not first clear the object.
+ * @param {ProtoBuf.Reflect.T} descriptor The reflection descriptor for the
+ * message. For example, if the message is of type "MyNamespace.MyMessage" then
+ * the descriptor is builder.lookup("MyNamespace.MyMessage").
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ */
+ProtobufTlv.decode = function(message, descriptor, input)
+{
+  ProtobufTlv.establishField();
+
+  // If input is a blob, get its buf().
+  var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
+                     input.buf() : input;
+
+  var decoder = new TlvDecoder(decodeBuffer);
+  ProtobufTlv._decodeMessageValue
+    (message, descriptor, decoder, decodeBuffer.length);
+};
+
+ProtobufTlv._encodeMessageValue = function(message, descriptor, encoder)
+{
+  var fields = descriptor.getChildren(ProtobufTlv._Field);
+  // Encode the fields backwards.
+  for (var iField = fields.length - 1; iField >= 0; --iField) {
+    var field = fields[iField];
+    var tlvType = field.id;
+
+    var values;
+    if (field.repeated)
+      values = message[field.name];
+    else {
+      if (message[field.name] != null)
+        // Make a singleton list.
+        values = [message[field.name]];
+      else
+        continue;
+    }
+
+    // Encode the values backwards.
+    for (var iValue = values.length - 1; iValue >= 0; --iValue) {
+      var value = values[iValue];
+
+      if (field.type.name == "message") {
+        var saveLength =  encoder.getLength();
+
+        // Encode backwards.
+        ProtobufTlv._encodeMessageValue(value, field.resolvedType, encoder);
+        encoder.writeTypeAndLength(tlvType, encoder.getLength() - saveLength);
+      }
+      else if (field.type.name == "uint32" ||
+               field.type.name == "uint64")
+        encoder.writeNonNegativeIntegerTlv(tlvType, value);
+      else if (field.type.name == "enum") {
+        if (value < 0)
+          throw new Error("ProtobufTlv::encode: ENUM value may not be negative");
+        encoder.writeNonNegativeIntegerTlv(tlvType, value);
+      }
+      else if (field.type.name == "bytes") {
+        var buffer = value.toBuffer();
+        if (buffer.length == undefined)
+          // We are not running in Node.js, so assume we are using the dcodeIO
+          // browser implementation based on ArrayBuffer.
+          buffer = new Uint8Array(value.toArrayBuffer());
+        encoder.writeBlobTlv(tlvType, buffer);
+      }
+      else if (field.type.name == "string")
+        // Use Blob to convert.
+        encoder.writeBlobTlv(tlvType, new Blob(value, false).buf());
+      else if (field.type.name == "bool") {
+        if (value)
+          encoder.writeTypeAndLength(tlvType, 0);
+      }
+      else if (field.type.name == "double") {
+        var encoding = new Buffer(8);
+        encoding.writeDoubleLE(value, 0);
+        encoder.writeBlobTlv(tlvType, encoding);
+      }
+      else
+        throw new Error("ProtobufTlv::encode: Unknown field type");
+    }
+  }
+};
+
+ProtobufTlv._decodeMessageValue = function(message, descriptor, decoder, endOffset)
+{
+  var fields = descriptor.getChildren(ProtobufTlv._Field);
+  for (var iField = 0; iField < fields.length; ++iField) {
+    var field = fields[iField];
+    var tlvType = field.id;
+
+    if (!field.required && !decoder.peekType(tlvType, endOffset))
+      continue;
+
+    if (field.repeated) {
+      while (decoder.peekType(tlvType, endOffset)) {
+        if (field.type.name == "message") {
+          var innerEndOffset = decoder.readNestedTlvsStart(tlvType);
+          var value = new (field.resolvedType.build())();
+          message.add(field.name, value);
+          ProtobufTlv._decodeMessageValue
+            (value, field.resolvedType, decoder, innerEndOffset);
+          decoder.finishNestedTlvs(innerEndOffset);
+        }
+        else
+          message.add
+            (field.name,
+             ProtobufTlv._decodeFieldValue(field, tlvType, decoder, endOffset));
+      }
+    }
+    else {
+      if (field.type.name == "message") {
+        var innerEndOffset = decoder.readNestedTlvsStart(tlvType);
+        var value = new (field.resolvedType.build())();
+        message.set(field.name, value);
+        ProtobufTlv._decodeMessageValue
+          (value, field.resolvedType, decoder, innerEndOffset);
+        decoder.finishNestedTlvs(innerEndOffset);
+      }
+      else
+        message.set
+          (field.name,
+           ProtobufTlv._decodeFieldValue(field, tlvType, decoder, endOffset));
+    }
+  }
+};
+
+/**
+ * This is a helper for _decodeMessageValue. Decode a single field and return
+ * the value. Assume the field.type.name is not "message".
+ */
+ProtobufTlv._decodeFieldValue = function(field, tlvType, decoder, endOffset)
+{
+  if (field.type.name == "uint32" ||
+      field.type.name == "uint64" ||
+      field.type.name == "enum")
+    return decoder.readNonNegativeIntegerTlv(tlvType);
+  else if (field.type.name == "bytes")
+    return decoder.readBlobTlv(tlvType);
+  else if (field.type.name == "string")
+    return decoder.readBlobTlv(tlvType).toString();
+  else if (field.type.name == "bool")
+    return decoder.readBooleanTlv(tlvType, endOffset);
+  else if (field.type.name == "double")
+    return decoder.readBlobTlv(tlvType).readDoubleLE(0);
+  else
+    throw new Error("ProtobufTlv.decode: Unknown field type");
+};
+
+/**
+ * Return a Name made from the component array in a Protobuf message object,
+ * assuming that it was defined with "repeated bytes". For example:
+ * message Name {
+ *   repeated bytes component = 8;
+ * }
+ * @param {Array} componentArray The array from the Protobuf message object
+ * representing the "repeated bytes" component array.
+ * @return A new Name.
+ */
+ProtobufTlv.toName = function(componentArray)
+{
+  var name = new Name();
+  for (var i = 0; i < componentArray.length; ++i)
+    name.append
+      (new Blob(new Buffer(componentArray[i].toBinary(), "binary")), false);
+
+  return name;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * @constructor
+ */
+var OID = function OID(oid)
+{
+  if (typeof oid === 'string') {
+    var splitString = oid.split(".");
+    this.oid = [];
+    for (var i = 0; i < splitString.length; ++i)
+      this.oid.push(parseInt(splitString[i]));
+  }
+  else
+    // Assume oid is an array of int.  Make a copy.
+    this.oid = oid.slice(0, oid.length);
+};
+
+exports.OID = OID;
+
+OID.prototype.getIntegerList = function()
+{
+  return this.oid;
+};
+
+OID.prototype.setIntegerList = function(oid)
+{
+  // Make a copy.
+  this.oid = oid.slice(0, oid.length);
+};
+
+OID.prototype.toString = function()
+{
+  var result = "";
+  for (var i = 0; i < this.oid.length; ++i) {
+    if (i !== 0)
+      result += ".";
+    result += this.oid[i];
+  }
+
+  return result;
+};
+
+OID.prototype.equals = function(other)
+{
+  if (!(other instanceof OID))
+    return false;
+  if (this.oid.length !== other.oid.length)
+    return false;
+
+  for (var i = 0; i < this.oid.length; ++i) {
+    if (this.oid[i] != other.oid[i])
+      return false;
+  }
+  return true;
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a WireFormat base class where the encode and decode methods throw an error. You should use a derived class like TlvWireFormat.
+ * @constructor
+ */
+var WireFormat = function WireFormat() {
+};
+
+exports.WireFormat = WireFormat;
+
+/**
+ * Encode name and return the encoding.  Your derived class should override.
+ * @param {Name} name The Name to encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeName = function(name)
+{
+  throw new Error("encodeName is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as a name and set the fields of the Name object.
+ * Your derived class should override.
+ * @param {Name} name The Name object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeName = function(name, input, copy)
+{
+  throw new Error("decodeName is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode interest and return the encoding.  Your derived class should override.
+ * @param {Interest} interest The Interest to encode.
+ * @return {object} An associative array with fields
+ * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
+ * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
+ * the encoding of the beginning of the signed portion, and
+ * signedPortionEndOffset is the offset in the encoding of the end of the signed
+ * portion. The signed portion starts from the first name component and ends
+ * just before the final name component (which is assumed to be a signature for
+ * a signed interest).
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeInterest = function(interest)
+{
+  throw new Error("encodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as an interest and set the fields of the interest object.
+ * Your derived class should override.
+ * @param {Interest} interest The Interest object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion. The signed portion starts from the first
+ * name component and ends just before the final name component (which is
+ * assumed to be a signature for a signed interest).
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeInterest = function(interest, input, copy)
+{
+  throw new Error("decodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode data and return the encoding and signed offsets. Your derived class
+ * should override.
+ * @param {Data} data The Data object to encode.
+ * @return {object} An associative array with fields
+ * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
+ * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
+ * the encoding of the beginning of the signed portion, and
+ * signedPortionEndOffset is the offset in the encoding of the end of the
+ * signed portion.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeData = function(data)
+{
+  throw new Error("encodeData is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as a data packet, set the fields in the data object, and return
+ * the signed offsets.  Your derived class should override.
+ * @param {Data} data The Data object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeData = function(data, input, copy)
+{
+  throw new Error("decodeData is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode controlParameters and return the encoding.  Your derived class should
+ * override.
+ * @param {ControlParameters} controlParameters The ControlParameters object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeControlParameters = function(controlParameters)
+{
+  throw new Error("encodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as a controlParameters and set the fields of the
+ * controlParameters object. Your derived class should override.
+ * @param {ControlParameters} controlParameters The ControlParameters object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeControlParameters = function
+  (controlParameters, input, copy)
+{
+  throw new Error("decodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode controlResponse and return the encoding.  Your derived class should
+ * override.
+ * @param {ControlResponse} controlResponse The ControlResponse object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeControlResponse = function(controlResponse)
+{
+  throw new Error("encodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as a controlResponse and set the fields of the
+ * controlResponse object. Your derived class should override.
+ * @param {ControlResponse} controlResponse The ControlResponse object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeControlResponse = function
+  (controlResponse, input, copy)
+{
+  throw new Error("decodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode signature as a SignatureInfo and return the encoding. Your derived
+ * class should override.
+ * @param {Signature} signature An object of a subclass of Signature to encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeSignatureInfo = function(signature)
+{
+  throw new Error("encodeSignatureInfo is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode signatureInfo as a signature info and signatureValue as the related
+ * SignatureValue, and return a new object which is a subclass of Signature.
+ * Your derived class should override.
+ * @param {Buffer} signatureInfo The buffer with the signature info bytes to
+ * decode.
+ * @param {Buffer} signatureValue The buffer with the signature value to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {Signature} A new object which is a subclass of Signature.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.decodeSignatureInfoAndValue = function
+  (signatureInfo, signatureValue, copy)
+{
+  throw new Error("decodeSignatureInfoAndValue is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Encode the signatureValue in the Signature object as a SignatureValue (the
+ * signature bits) and return the encoding. Your derived class should override.
+ * @param {Signature} signature An object of a subclass of Signature with the
+ * signature value to encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class should override.
+ */
+WireFormat.prototype.encodeSignatureValue = function(signature)
+{
+  throw new Error("encodeSignatureValue is unimplemented in the base WireFormat class.  You should use a derived class.");
+};
+
+/**
+ * Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object.
+ * Your derived class should override.
+ * @param {LpPacket} lpPacket The LpPacket object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.decodeLpPacket = function(lpPacket, input, copy)
+{
+  throw new Error
+    ("decodeLpPacket is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Encode the DelegationSet and return the encoding.  Your derived class
+ * should override.
+ * @param {DelegationSet} delegationSet The DelegationSet object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.encodeDelegationSet = function(delegationSet)
+{
+  throw new Error
+    ("encodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Decode input as an DelegationSet and set the fields of the
+ * delegationSet object. Your derived class should override.
+ * @param {DelegationSet} delegationSet The DelegationSet object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.decodeDelegationSet = function(delegationSet, input, copy)
+{
+  throw new Error
+    ("decodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Encode the EncryptedContent and return the encoding.  Your derived class
+ * should override.
+ * @param {EncryptedContent} encryptedContent The EncryptedContent object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.encodeEncryptedContent = function(encryptedContent)
+{
+  throw new Error
+    ("encodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Decode input as an EncryptedContent and set the fields of the
+ * encryptedContent object. Your derived class should override.
+ * @param {EncryptedContent} encryptedContent The EncryptedContent object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws Error This always throws an "unimplemented" error. The derived class
+ * should override.
+ */
+WireFormat.prototype.decodeEncryptedContent = function
+  (encryptedContent, input, copy)
+{
+  throw new Error
+    ("decodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");
+};
+
+/**
+ * Set the static default WireFormat used by default encoding and decoding
+ * methods.
+ * @param {WireFormat} wireFormat An object of a subclass of WireFormat.
+ */
+WireFormat.setDefaultWireFormat = function(wireFormat)
+{
+  WireFormat.defaultWireFormat = wireFormat;
+};
+
+/**
+ * Return the default WireFormat used by default encoding and decoding methods
+ * which was set with setDefaultWireFormat.
+ * @return {WireFormat} An object of a subclass of WireFormat.
+ */
+WireFormat.getDefaultWireFormat = function()
+{
+  return WireFormat.defaultWireFormat;
+};
+
+// Invoke TlvWireFormat to set the default format.
+// Since tlv-wire-format.js includes this file, put this at the bottom
+// to avoid problems with cycles of require.
+var TlvWireFormat = require('./tlv-wire-format.js').TlvWireFormat;
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DataUtils = require('./data-utils.js').DataUtils; /** @ignore */
+var Tlv = require('./tlv/tlv.js').Tlv; /** @ignore */
+var TlvStructureDecoder = require('./tlv/tlv-structure-decoder.js').TlvStructureDecoder; /** @ignore */
+var DecodingException = require('./decoding-exception.js').DecodingException; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * A ElementReader lets you call onReceivedData multiple times which uses a
+ * TlvStructureDecoder to detect the end of a TLV element and calls
+ * elementListener.onReceivedElement(element) with the element.  This handles
+ * the case where a single call to onReceivedData may contain multiple elements.
+ * @constructor
+ * @param {object} elementListener An object with an onReceivedElement method.
+ */
+var ElementReader = function ElementReader(elementListener)
+{
+  this.elementListener_ = elementListener;
+  this.dataParts_ = [];
+  this.tlvStructureDecoder_ = new TlvStructureDecoder();
+};
+
+exports.ElementReader = ElementReader;
+
+/**
+ * Continue to read data until the end of an element, then call
+ * this.elementListener_.onReceivedElement(element). The buffer passed to
+ * onReceivedElement is only valid during this call.  If you need the data
+ * later, you must copy.
+ * @param {Buffer} data The Buffer with the incoming element's bytes.
+ */
+ElementReader.prototype.onReceivedData = function(data)
+{
+  // Process multiple elements in the data.
+  while (true) {
+    var gotElementEnd;
+    var offset;
+
+    try {
+      if (this.dataParts_.length === 0) {
+        // This is the beginning of an element.
+        if (data.length <= 0)
+          // Wait for more data.
+          return;
+      }
+
+      // Scan the input to check if a whole TLV element has been read.
+      this.tlvStructureDecoder_.seek(0);
+      gotElementEnd = this.tlvStructureDecoder_.findElementEnd(data);
+      offset = this.tlvStructureDecoder_.getOffset();
     } catch (ex) {
-        console.log("NDN not available: Uint8Array not supported. " + ex);
+      // Reset to read a new element on the next call.
+      this.dataParts_ = [];
+      this.tlvStructureDecoder_ = new TlvStructureDecoder();
+
+      throw ex;
+    }
+
+    if (gotElementEnd) {
+      // Got the remainder of an element.  Report to the caller.
+      var element;
+      if (this.dataParts_.length === 0)
+        element = data.slice(0, offset);
+      else {
+        this.dataParts_.push(data.slice(0, offset));
+        element = DataUtils.concatArrays(this.dataParts_);
+        this.dataParts_ = [];
+      }
+
+      // Reset to read a new element. Do this before calling onReceivedElement
+      // in case it throws an exception.
+      data = data.slice(offset, data.length);
+      this.tlvStructureDecoder_ = new TlvStructureDecoder();
+
+      this.elementListener_.onReceivedElement(element);
+      if (data.length == 0)
+        // No more data in the packet.
+        return;
+
+      // else loop back to decode.
+    }
+    else {
+      // Save a copy. We will call concatArrays later.
+      var totalLength = data.length;
+      for (var i = 0; i < this.dataParts_.length; ++i)
+        totalLength += this.dataParts_[i].length;
+      if (totalLength > NdnCommon.MAX_NDN_PACKET_SIZE) {
+        // Reset to read a new element on the next call.
+        this.dataParts_ = [];
+        this.tlvStructureDecoder_ = new TlvStructureDecoder();
+
+        throw new DecodingException(new Error
+          ("The incoming packet exceeds the maximum limit Face.getMaxNdnPacketSize()"));
+      }
+
+      this.dataParts_.push(new Buffer(data));
+      if (LOG > 3) console.log('Incomplete packet received. Length ' + data.length + '. Wait for more input.');
+      return;
+    }
+  }
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a new DerDecodingException wrapping the given error object.
+ * Call with: throw new DerDecodingException(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+function DerDecodingException(error)
+{
+  if (error) {
+    error.__proto__ = DerDecodingException.prototype;
+    return error;
+  }
+}
+DerDecodingException.prototype = new Error();
+DerDecodingException.prototype.name = "DerDecodingException";
+
+exports.DerDecodingException = DerDecodingException;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a new DerEncodingException wrapping the given error object.
+ * Call with: throw new DerEncodingException(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+function DerEncodingException(error)
+{
+  if (error) {
+    error.__proto__ = DerEncodingException.prototype;
+    return error;
+  }
+}
+DerEncodingException.prototype = new Error();
+DerEncodingException.prototype.name = "DerEncodingException";
+
+exports.DerEncodingException = DerEncodingException;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From PyNDN der.py by Adeola Bannis <thecodemaiden@gmail.com>.
+ * @author: Originally from code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * The DerNodeType enum defines the known DER node types.
+ */
+var DerNodeType = function DerNodeType()
+{
+}
+
+exports.DerNodeType = DerNodeType;
+
+DerNodeType.Eoc = 0;
+DerNodeType.Boolean = 1;
+DerNodeType.Integer = 2;
+DerNodeType.BitString = 3;
+DerNodeType.OctetString = 4;
+DerNodeType.Null = 5;
+DerNodeType.ObjectIdentifier = 6;
+DerNodeType.ObjectDescriptor = 7;
+DerNodeType.External = 40;
+DerNodeType.Real = 9;
+DerNodeType.Enumerated = 10;
+DerNodeType.EmbeddedPdv = 43;
+DerNodeType.Utf8String = 12;
+DerNodeType.RelativeOid = 13;
+DerNodeType.Sequence = 48;
+DerNodeType.Set = 49;
+DerNodeType.NumericString = 18;
+DerNodeType.PrintableString = 19;
+DerNodeType.T61String = 20;
+DerNodeType.VideoTexString = 21;
+DerNodeType.Ia5String = 22;
+DerNodeType.UtcTime = 23;
+DerNodeType.GeneralizedTime = 24;
+DerNodeType.GraphicString = 25;
+DerNodeType.VisibleString = 26;
+DerNodeType.GeneralString = 27;
+DerNodeType.UniversalString = 28;
+DerNodeType.CharacterString = 29;
+DerNodeType.BmpString = 30;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From PyNDN der_node.py by Adeola Bannis <thecodemaiden@gmail.com>.
+ * @author: Originally from code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DynamicBuffer = require('../../util/dynamic-buffer.js').DynamicBuffer; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DerDecodingException = require('./der-decoding-exception.js').DerDecodingException; /** @ignore */
+var DerEncodingException = require('./der-encoding-exception.js').DerEncodingException; /** @ignore */
+var DerNodeType = require('./der-node-type.js').DerNodeType;
+
+/**
+ * DerNode implements the DER node types used in encoding/decoding DER-formatted
+ * data.
+ *
+ * Create a generic DER node with the given nodeType. This is a private
+ * constructor used by one of the public DerNode subclasses defined below.
+ * @param {number} nodeType One of the defined DER DerNodeType constants.
+ * @constructor
+ */
+var DerNode = function DerNode(nodeType)
+{
+  this.nodeType_ = nodeType;
+  this.parent_ = null;
+  this.header_ = new Buffer(0);
+  this.payload_ = new DynamicBuffer(0);
+  this.payloadPosition_ = 0;
+};
+
+exports.DerNode = DerNode;
+
+/**
+ * Return the number of bytes in DER
+ * @return {number}
+ */
+DerNode.prototype.getSize = function()
+{
+  return this.header_.length + this.payloadPosition_;
+};
+
+/**
+ * Encode the given size and update the header.
+ * @param {number} size
+ */
+DerNode.prototype.encodeHeader = function(size)
+{
+  var buffer = new DynamicBuffer(10);
+  var bufferPosition = 0;
+  buffer.array[bufferPosition++] = this.nodeType_;
+  if (size < 0)
+    // We don't expect this to happen since this is an internal method and
+    // always called with the non-negative size() of some buffer.
+    throw new Error("encodeHeader: DER object has negative length");
+  else if (size <= 127)
+    buffer.array[bufferPosition++] = size & 0xff;
+  else {
+    var tempBuf = new DynamicBuffer(10);
+    // We encode backwards from the back.
+
+    var val = size;
+    var n = 0;
+    while (val != 0) {
+      ++n;
+      tempBuf.ensureLengthFromBack(n);
+      tempBuf.array[tempBuf.array.length - n] = val & 0xff;
+      val >>= 8;
+    }
+    var nTempBufBytes = n + 1;
+    tempBuf.ensureLengthFromBack(nTempBufBytes);
+    tempBuf.array[tempBuf.array.length - nTempBufBytes] = ((1<<7) | n) & 0xff;
+
+    buffer.copy(tempBuf.slice(tempBuf.array.length - nTempBufBytes), bufferPosition);
+    bufferPosition += nTempBufBytes;
+  }
+
+  this.header_ = buffer.slice(0, bufferPosition);
+};
+
+/**
+ * Extract the header from an input buffer and return the size.
+ * @param {Buffer} inputBuf The input buffer to read from.
+ * @param {number} startIdx The offset into the buffer.
+ * @return {number} The parsed size in the header.
+ */
+DerNode.prototype.decodeHeader = function(inputBuf, startIdx)
+{
+  var idx = startIdx;
+
+  var nodeType = inputBuf[idx] & 0xff;
+  idx += 1;
+
+  this.nodeType_ = nodeType;
+
+  var sizeLen = inputBuf[idx] & 0xff;
+  idx += 1;
+
+  var header = new DynamicBuffer(10);
+  var headerPosition = 0;
+  header.array[headerPosition++] = nodeType;
+  header.array[headerPosition++] = sizeLen;
+
+  var size = sizeLen;
+  var isLongFormat = (sizeLen & (1 << 7)) != 0;
+  if (isLongFormat) {
+    var lenCount = sizeLen & ((1<<7) - 1);
+    size = 0;
+    while (lenCount > 0) {
+      var b = inputBuf[idx];
+      idx += 1;
+      header.ensureLength(headerPosition + 1);
+      header.array[headerPosition++] = b;
+      size = 256 * size + (b & 0xff);
+      lenCount -= 1;
+    }
+  }
+
+  this.header_ = header.slice(0, headerPosition);
+  return size;
+};
+
+/**
+ * Get the raw data encoding for this node.
+ * @return {Blob} The raw data encoding.
+ */
+DerNode.prototype.encode = function()
+{
+  var buffer = new Buffer(this.getSize());
+
+  this.header_.copy(buffer);
+  this.payload_.slice(0, this.payloadPosition_).copy(buffer, this.header_.length);
+
+  return new Blob(buffer, false);
+};
+
+/**
+ * Decode and store the data from an input buffer.
+ * @param {Buffer} inputBuf The input buffer to read from. This reads from
+ * startIdx (regardless of the buffer's position) and does not change the
+ * position.
+ * @param {number} startIdx The offset into the buffer.
+ */
+DerNode.prototype.decode = function(inputBuf, startIdx)
+{
+  var idx = startIdx;
+  var payloadSize = this.decodeHeader(inputBuf, idx);
+  var skipBytes = this.header_.length;
+  if (payloadSize > 0) {
+    idx += skipBytes;
+    this.payloadAppend(inputBuf.slice(idx, idx + payloadSize));
+  }
+};
+
+/**
+ * Copy buffer to this.payload_ at this.payloadPosition_ and update
+ * this.payloadPosition_.
+ * @param {Buffer} buffer The buffer to copy.
+ */
+DerNode.prototype.payloadAppend = function(buffer)
+{
+  this.payloadPosition_ = this.payload_.copy(buffer, this.payloadPosition_);
+}
+
+/**
+ * Parse the data from the input buffer recursively and return the root as an
+ * object of a subclass of DerNode.
+ * @param {Buffer} inputBuf The input buffer to read from.
+ * @param {number} startIdx (optional) The offset into the buffer. If omitted,
+ * use 0.
+ * @return {DerNode} An object of a subclass of DerNode.
+ */
+DerNode.parse = function(inputBuf, startIdx)
+{
+  if (startIdx == undefined)
+    startIdx = 0;
+
+  var nodeType = inputBuf[startIdx] & 0xff;
+  // Don't increment idx. We're just peeking.
+
+  var newNode;
+  if (nodeType === DerNodeType.Boolean)
+    newNode = new DerNode.DerBoolean();
+  else if (nodeType === DerNodeType.Integer)
+    newNode = new DerNode.DerInteger();
+  else if (nodeType === DerNodeType.BitString)
+    newNode = new DerNode.DerBitString();
+  else if (nodeType === DerNodeType.OctetString)
+    newNode = new DerNode.DerOctetString();
+  else if (nodeType === DerNodeType.Null)
+    newNode = new DerNode.DerNull();
+  else if (nodeType === DerNodeType.ObjectIdentifier)
+    newNode = new DerNode.DerOid();
+  else if (nodeType === DerNodeType.Sequence)
+    newNode = new DerNode.DerSequence();
+  else if (nodeType === DerNodeType.PrintableString)
+    newNode = new DerNode.DerPrintableString();
+  else if (nodeType === DerNodeType.GeneralizedTime)
+    newNode = new DerNode.DerGeneralizedTime();
+  else
+    throw new DerDecodingException(new Error("Unimplemented DER type " + nodeType));
+
+  newNode.decode(inputBuf, startIdx);
+  return newNode;
+};
+
+/**
+ * Convert the encoded data to a standard representation. Overridden by some
+ * subclasses (e.g. DerBoolean).
+ * @return {Blob} The encoded data as a Blob.
+ */
+DerNode.prototype.toVal = function()
+{
+  return this.encode();
+};
+
+/**
+ * Get a copy of the payload bytes.
+ * @return {Blob} A copy of the payload.
+ */
+DerNode.prototype.getPayload = function()
+{
+  return new Blob(this.payload_.slice(0, this.payloadPosition_), true);
+};
+
+/**
+ * If this object is a DerNode.DerSequence, get the children of this node.
+ * Otherwise, throw an exception. (DerSequence overrides to implement this
+ * method.)
+ * @return {Array<DerNode>} The children as an array of DerNode.
+ * @throws DerDecodingException if this object is not a DerSequence.
+ */
+DerNode.prototype.getChildren = function()
+{
+  throw new DerDecodingException(new Error
+    ("getChildren: This DerNode is not DerSequence"));
+};
+
+/**
+ * Check that index is in bounds for the children list, return children[index].
+ * @param {Array<DerNode>} children The list of DerNode, usually returned by
+ * another call to getChildren.
+ * @param {number} index The index of the children.
+ * @return {DerNode.DerSequence} children[index].
+ * @throws DerDecodingException if index is out of bounds or if children[index]
+ * is not a DerSequence.
+ */
+DerNode.getSequence = function(children, index)
+{
+  if (index < 0 || index >= children.length)
+    throw new DerDecodingException(new Error
+      ("getSequence: Child index is out of bounds"));
+
+  if (!(children[index] instanceof DerNode.DerSequence))
+    throw new DerDecodingException(new Error
+      ("getSequence: Child DerNode is not a DerSequence"));
+
+  return children[index];
+};
+
+/**
+ * A DerStructure extends DerNode to hold other DerNodes.
+ * Create a DerStructure with the given nodeType. This is a private
+ * constructor. To create an object, use DerSequence.
+ * @param {number} nodeType One of the defined DER DerNodeType constants.
+ */
+DerNode.DerStructure = function DerStructure(nodeType)
+{
+  // Call the base constructor.
+  DerNode.call(this, nodeType);
+
+  this.childChanged_ = false;
+  this.nodeList_ = []; // Of DerNode.
+  this.size_ = 0;
+};
+DerNode.DerStructure.prototype = new DerNode();
+DerNode.DerStructure.prototype.name = "DerStructure";
+
+/**
+ * Get the total length of the encoding, including children.
+ * @return {number} The total (header + payload) length.
+ */
+DerNode.DerStructure.prototype.getSize = function()
+{
+  if (this.childChanged_) {
+    this.updateSize();
+    this.childChanged_ = false;
+  }
+
+  this.encodeHeader(this.size_);
+  return this.size_ + this.header_.length;
+};
+
+/**
+ * Get the children of this node.
+ * @return {Array<DerNode>} The children as an array of DerNode.
+ */
+DerNode.DerStructure.prototype.getChildren = function()
+{
+  return this.nodeList_;
+};
+
+DerNode.DerStructure.prototype.updateSize = function()
+{
+  var newSize = 0;
+
+  for (var i = 0; i < this.nodeList_.length; ++i) {
+    var n = this.nodeList_[i];
+    newSize += n.getSize();
+  }
+
+  this.size_ = newSize;
+  this.childChanged_ = false;
+};
+
+/**
+ * Add a child to this node.
+ * @param {DerNode} node The child node to add.
+ * @param {boolean} (optional) notifyParent Set to true to cause any containing
+ * nodes to update their size.  If omitted, use false.
+ */
+DerNode.DerStructure.prototype.addChild = function(node, notifyParent)
+{
+  node.parent_ = this;
+  this.nodeList_.push(node);
+
+  if (notifyParent) {
+    if (this.parent_ != null)
+      this.parent_.setChildChanged();
+  }
+
+  this.childChanged_ = true;
+};
+
+/**
+ * Mark the child list as dirty, so that we update size when necessary.
+ */
+DerNode.DerStructure.prototype.setChildChanged = function()
+{
+  if (this.parent_ != null)
+    this.parent_.setChildChanged();
+  this.childChanged_ = true;
+};
+
+/**
+ * Override the base encode to return raw data encoding for this node and its
+ * children.
+ * @return {Blob} The raw data encoding.
+ */
+DerNode.DerStructure.prototype.encode = function()
+{
+  var buffer = new DynamicBuffer(10);
+  var bufferPosition = 0;
+  this.updateSize();
+  this.encodeHeader(this.size_);
+  bufferPosition = buffer.copy(this.header_, bufferPosition);
+
+  for (var i = 0; i < this.nodeList_.length; ++i) {
+    var n = this.nodeList_[i];
+    var encodedChild = n.encode();
+    bufferPosition = buffer.copy(encodedChild.buf(), bufferPosition);
+  }
+
+  return new Blob(buffer.slice(0, bufferPosition), false);
+};
+
+/**
+ * Override the base decode to decode and store the data from an input
+ * buffer. Recursively populates child nodes.
+ * @param {Buffer} inputBuf The input buffer to read from.
+ * @param {number} startIdx The offset into the buffer.
+ */
+DerNode.DerStructure.prototype.decode = function(inputBuf, startIdx)
+{
+  var idx = startIdx;
+  this.size_ = this.decodeHeader(inputBuf, idx);
+  idx += this.header_.length;
+
+  var accSize = 0;
+  while (accSize < this.size_) {
+    var node = DerNode.parse(inputBuf, idx);
+    var size = node.getSize();
+    idx += size;
+    accSize += size;
+    this.addChild(node, false);
+  }
+};
+
+////////
+// Now for all the node types...
+////////
+
+/**
+ * A DerByteString extends DerNode to handle byte strings.
+ * Create a DerByteString with the given inputData and nodeType. This is a
+ * private constructor used by one of the public subclasses such as
+ * DerOctetString or DerPrintableString.
+ * @param {Buffer} inputData An input buffer containing the string to encode.
+ * @param {number} nodeType One of the defined DER DerNodeType constants.
+ */
+DerNode.DerByteString = function DerByteString(inputData, nodeType)
+{
+  // Call the base constructor.
+  DerNode.call(this, nodeType);
+
+  if (inputData != null) {
+    this.payloadAppend(inputData);
+    this.encodeHeader(inputData.length);
+  }
+};
+DerNode.DerByteString.prototype = new DerNode();
+DerNode.DerByteString.prototype.name = "DerByteString";
+
+/**
+ * Override to return just the byte string.
+ * @return {Blob} The byte string as a copy of the payload buffer.
+ */
+DerNode.DerByteString.prototype.toVal = function()
+{
+  return this.getPayload();
+};
+
+/**
+ * DerBoolean extends DerNode to encode a boolean value.
+ * Create a new DerBoolean for the value.
+ * @param {boolean} value The value to encode.
+ */
+DerNode.DerBoolean = function DerBoolean(value)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.Boolean);
+
+  if (value != undefined) {
+    var val = value ? 0xff : 0x00;
+    this.payload_.ensureLength(this.payloadPosition_ + 1);
+    this.payload_.array[this.payloadPosition_++] = val;
+    this.encodeHeader(1);
+  }
+};
+DerNode.DerBoolean.prototype = new DerNode();
+DerNode.DerBoolean.prototype.name = "DerBoolean";
+
+DerNode.DerBoolean.prototype.toVal = function()
+{
+  var val = this.payload_.array[0];
+  return val != 0x00;
+};
+
+/**
+ * DerInteger extends DerNode to encode an integer value.
+ * Create a new DerInteger for the value.
+ * @param {number|Buffer} integer The value to encode. If integer is a Buffer
+ * byte array of a positive integer, you must ensure that the first byte is less
+ * than 0x80.
+ */
+DerNode.DerInteger = function DerInteger(integer)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.Integer);
+
+  if (integer != undefined) {
+    if (Buffer.isBuffer(integer)) {
+      if (integer.length > 0 && integer[0] >= 0x80)
+        throw new DerEncodingException(new Error
+          ("DerInteger: Negative integers are not currently supported"));
+
+      if (integer.length == 0)
+        this.payloadAppend(new Buffer([0]));
+      else
+        this.payloadAppend(integer);
+    }
+    else {
+      // JavaScript doesn't distinguish int from float, so round.
+      integer = Math.round(integer);
+
+      if (integer < 0)
+        throw new DerEncodingException(new Error
+          ("DerInteger: Negative integers are not currently supported"));
+
+      // Convert the integer to bytes the easy/slow way.
+      var temp = new DynamicBuffer(10);
+      // We encode backwards from the back.
+      var length = 0;
+      while (true) {
+        ++length;
+        temp.ensureLengthFromBack(length);
+        temp.array[temp.array.length - length] = integer & 0xff;
+        integer >>= 8;
+
+        if (integer <= 0)
+          // We check for 0 at the end so we encode one byte if it is 0.
+          break;
+      }
+
+      if (temp.array[temp.array.length - length] >= 0x80) {
+        // Make it a non-negative integer.
+        ++length;
+        temp.ensureLengthFromBack(length);
+        temp.array[temp.array.length - length] = 0;
+      }
+
+      this.payloadAppend(temp.slice(temp.array.length - length));
+    }
+
+    this.encodeHeader(this.payloadPosition_);
+  }
+};
+DerNode.DerInteger.prototype = new DerNode();
+DerNode.DerInteger.prototype.name = "DerInteger";
+
+DerNode.DerInteger.prototype.toVal = function()
+{
+  if (this.payloadPosition_ > 0 && this.payload_.array[0] >= 0x80)
+    throw new DerDecodingException(new Error
+      ("DerInteger: Negative integers are not currently supported"));
+
+  var result = 0;
+  for (var i = 0; i < this.payloadPosition_; ++i) {
+    result <<= 8;
+    result += this.payload_.array[i];
+  }
+
+  return result;
+};
+
+/**
+ * A DerBitString extends DerNode to handle a bit string.
+ * Create a DerBitString with the given padding and inputBuf.
+ * @param {Buffer} inputBuf An input buffer containing the bit octets to encode.
+ * @param {number} paddingLen The number of bits of padding at the end of the bit
+ * string.  Should be less than 8.
+ */
+DerNode.DerBitString = function DerBitString(inputBuf, paddingLen)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.BitString);
+
+  if (inputBuf != undefined) {
+    this.payload_.ensureLength(this.payloadPosition_ + 1);
+    this.payload_.array[this.payloadPosition_++] = paddingLen & 0xff;
+    this.payloadAppend(inputBuf);
+    this.encodeHeader(this.payloadPosition_);
+  }
+};
+DerNode.DerBitString.prototype = new DerNode();
+DerNode.DerBitString.prototype.name = "DerBitString";
+
+/**
+ * DerOctetString extends DerByteString to encode a string of bytes.
+ * Create a new DerOctetString for the inputData.
+ * @param {Buffer} inputData An input buffer containing the string to encode.
+ */
+DerNode.DerOctetString = function DerOctetString(inputData)
+{
+  // Call the base constructor.
+  DerNode.DerByteString.call(this, inputData, DerNodeType.OctetString);
+};
+DerNode.DerOctetString.prototype = new DerNode.DerByteString();
+DerNode.DerOctetString.prototype.name = "DerOctetString";
+
+/**
+ * A DerNull extends DerNode to encode a null value.
+ * Create a DerNull.
+ */
+DerNode.DerNull = function DerNull()
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.Null);
+  this.encodeHeader(0);
+};
+DerNode.DerNull.prototype = new DerNode();
+DerNode.DerNull.prototype.name = "DerNull";
+
+/**
+ * A DerOid extends DerNode to represent an object identifier.
+ * Create a DerOid with the given object identifier. The object identifier
+ * string must begin with 0,1, or 2 and must contain at least 2 digits.
+ * @param {string|OID} oid The OID string or OID object to encode.
+ */
+DerNode.DerOid = function DerOid(oid)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.ObjectIdentifier);
+
+  if (oid != undefined) {
+    if (typeof oid === 'string') {
+      var splitString = oid.split(".");
+      var parts = [];
+      for (var i = 0; i < splitString.length; ++i)
+        parts.push(parseInt(splitString[i]));
+
+      this.prepareEncoding(parts);
+    }
+    else
+      // Assume oid is of type OID.
+      this.prepareEncoding(oid.getIntegerList());
+  }
+};
+DerNode.DerOid.prototype = new DerNode();
+DerNode.DerOid.prototype.name = "DerOid";
+
+/**
+ * Encode a sequence of integers into an OID object and set the payload.
+ * @param {Array<number>} value The array of integers.
+ */
+DerNode.DerOid.prototype.prepareEncoding = function(value)
+{
+  var firstNumber;
+  if (value.length == 0)
+    throw new DerEncodingException(new Error("No integer in OID"));
+  else {
+    if (value[0] >= 0 && value[0] <= 2)
+      firstNumber = value[0] * 40;
+    else
+      throw new DerEncodingException(new Error("First integer in OID is out of range"));
+  }
+
+  if (value.length >= 2) {
+    if (value[1] >= 0 && value[1] <= 39)
+      firstNumber += value[1];
+    else
+      throw new DerEncodingException(new Error("Second integer in OID is out of range"));
+  }
+
+  var encodedBuffer = new DynamicBuffer(10);
+  var encodedBufferPosition = 0;
+  encodedBufferPosition = encodedBuffer.copy
+    (DerNode.DerOid.encode128(firstNumber), encodedBufferPosition);
+
+  if (value.length > 2) {
+    for (var i = 2; i < value.length; ++i)
+      encodedBufferPosition = encodedBuffer.copy
+        (DerNode.DerOid.encode128(value[i]), encodedBufferPosition);
+  }
+
+  this.encodeHeader(encodedBufferPosition);
+  this.payloadAppend(encodedBuffer.slice(0, encodedBufferPosition));
+};
+
+/**
+ * Compute the encoding for one part of an OID, where values greater than 128
+ * must be encoded as multiple bytes.
+ * @param {number} value A component of an OID.
+ * @return {Buffer} The encoded buffer.
+ */
+DerNode.DerOid.encode128 = function(value)
+{
+  var mask = (1 << 7) - 1;
+  var outBytes = new DynamicBuffer(10);
+  var outBytesLength = 0;
+  // We encode backwards from the back.
+
+  if (value < 128) {
+    ++outBytesLength;
+    outBytes.array[outBytes.array.length - outBytesLength] = value & mask;
+  }
+  else {
+    ++outBytesLength;
+    outBytes.array[outBytes.array.length - outBytesLength] = value & mask;
+    value >>= 7;
+
+    while (value != 0) {
+      ++outBytesLength;
+      outBytes.ensureLengthFromBack(outBytesLength);
+      outBytes.array[outBytes.array.length - outBytesLength] =
+        (value & mask) | (1 << 7);
+      value >>= 7;
+    }
+  }
+
+  return outBytes.slice(outBytes.array.length - outBytesLength);
+};
+
+/**
+ * Convert an encoded component of the encoded OID to the original integer.
+ * @param {number} offset The offset into this node's payload.
+ * @param {Array<number>} skip Set skip[0] to the number of payload bytes to skip.
+ * @return {number} The original integer.
+ */
+DerNode.DerOid.prototype.decode128 = function(offset, skip)
+{
+  var flagMask = 0x80;
+  var result = 0;
+  var oldOffset = offset;
+
+  while ((this.payload_.array[offset] & flagMask) != 0) {
+    result = 128 * result + (this.payload_.array[offset] & 0xff) - 128;
+    offset += 1;
+  }
+
+  result = result * 128 + (this.payload_.array[offset] & 0xff);
+
+  skip[0] = offset - oldOffset + 1;
+  return result;
+};
+
+/**
+ * Override to return the string representation of the OID.
+ * @return {string} The string representation of the OID.
+ */
+DerNode.DerOid.prototype.toVal = function()
+{
+  var offset = 0;
+  var components = []; // of number.
+
+  while (offset < this.payloadPosition_) {
+    var skip = [0];
+    var nextVal = this.decode128(offset, skip);
+    offset += skip[0];
+    components.push(nextVal);
+  }
+
+  // For some odd reason, the first digits are represented in one byte.
+  var firstByte = components[0];
+  var firstDigit = Math.floor(firstByte / 40);
+  var secondDigit = firstByte % 40;
+
+  var result = firstDigit + "." + secondDigit;
+  for (var i = 1; i < components.length; ++i)
+    result += "." + components[i];
+
+  return result;
+};
+
+/**
+ * A DerSequence extends DerStructure to contains an ordered sequence of other
+ * nodes.
+ * Create a DerSequence.
+ */
+DerNode.DerSequence = function DerSequence()
+{
+  // Call the base constructor.
+  DerNode.DerStructure.call(this, DerNodeType.Sequence);
+};
+DerNode.DerSequence.prototype = new DerNode.DerStructure();
+DerNode.DerSequence.prototype.name = "DerSequence";
+
+/**
+ * A DerPrintableString extends DerByteString to handle a a printable string. No
+ * escaping or other modification is done to the string.
+ * Create a DerPrintableString with the given inputData.
+ * @param {Buffer} inputData An input buffer containing the string to encode.
+ */
+DerNode.DerPrintableString = function DerPrintableString(inputData)
+{
+  // Call the base constructor.
+  DerNode.DerByteString.call(this, inputData, DerNodeType.PrintableString);
+};
+DerNode.DerPrintableString.prototype = new DerNode.DerByteString();
+DerNode.DerPrintableString.prototype.name = "DerPrintableString";
+
+/**
+ * A DerGeneralizedTime extends DerNode to represent a date and time, with
+ * millisecond accuracy.
+ * Create a DerGeneralizedTime with the given milliseconds since 1970.
+ * @param {number} msSince1970 The timestamp as milliseconds since Jan 1, 1970.
+ */
+DerNode.DerGeneralizedTime = function DerGeneralizedTime(msSince1970)
+{
+  // Call the base constructor.
+  DerNode.call(this, DerNodeType.GeneralizedTime);
+
+  if (msSince1970 != undefined) {
+    var derTime = DerNode.DerGeneralizedTime.toDerTimeString(msSince1970);
+    // Use Blob to convert to a Buffer.
+    this.payloadAppend(new Blob(derTime).buf());
+    this.encodeHeader(this.payloadPosition_);
+  }
+};
+DerNode.DerGeneralizedTime.prototype = new DerNode();
+DerNode.DerGeneralizedTime.prototype.name = "DerGeneralizedTime";
+
+/**
+ * Convert a UNIX timestamp to the internal string representation.
+ * @param {type} msSince1970 Timestamp as milliseconds since Jan 1, 1970.
+ * @return {string} The string representation.
+ */
+DerNode.DerGeneralizedTime.toDerTimeString = function(msSince1970)
+{
+  var utcTime = new Date(Math.round(msSince1970));
+  return utcTime.getUTCFullYear() +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCMonth() + 1) +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCDate()) +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCHours()) +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCMinutes()) +
+         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCSeconds()) +
+         "Z";
+};
+
+/**
+ * A private method to zero pad an integer to 2 digits.
+ * @param {number} x The number to pad.  Assume it is a non-negative integer.
+ * @return {string} The padded string.
+ */
+DerNode.DerGeneralizedTime.to2DigitString = function(x)
+{
+  var result = x.toString();
+  return result.length === 1 ? "0" + result : result;
+};
+
+/**
+ * Override to return the milliseconds since 1970.
+ * @return {number} The timestamp value as milliseconds since 1970.
+ */
+DerNode.DerGeneralizedTime.prototype.toVal = function()
+{
+  var timeStr = this.payload_.slice(0, this.payloadPosition_).toString();
+  return Date.UTC
+    (parseInt(timeStr.substr(0, 4)),
+     parseInt(timeStr.substr(4, 2) - 1),
+     parseInt(timeStr.substr(6, 2)),
+     parseInt(timeStr.substr(8, 2)),
+     parseInt(timeStr.substr(10, 2)),
+     parseInt(timeStr.substr(12, 2)));
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From PyNDN boost_info_parser by Adeola Bannis.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var fs = require('fs');
+
+/**
+ * BoostInfoTree is provided for compatibility with the Boost INFO property list
+ * format used in ndn-cxx.
+ *
+ * Each node in the tree may have a name and a value as well as associated
+ * sub-trees. The sub-tree names are not unique, and so sub-trees are stored as
+ * dictionaries where the key is a sub-tree name and the values are the
+ * sub-trees sharing the same name.
+ *
+ * Nodes can be accessed with a path syntax, as long as nodes in the path do not
+ * contain the path separator '/' in their names.
+ * @constructor
+ */
+var BoostInfoTree = function BoostInfoTree(value, parent)
+{
+  // subtrees is an array of {key: treeName, value: subtreeList} where
+  // treeName is a string and subtreeList is an array of BoostInfoTree.
+  // We can't use a dictionary because we want the keys to be in order.
+  this.subtrees = [];
+  this.value = value;
+  this.parent = parent;
+
+  this.lastChild = null;
+};
+
+/**
+ * Insert a BoostInfoTree as a sub-tree with the given name.
+ * @param {string} treeName The name of the new sub-tree.
+ * @param {BoostInfoTree} newTree The sub-tree to add.
+ */
+BoostInfoTree.prototype.addSubtree = function(treeName, newTree)
+{
+  var subtreeList = this.find(treeName);
+  if (subtreeList !== null)
+    subtreeList.push(newTree);
+  else
+    this.subtrees.push({key: treeName, value: [newTree]});
+
+  newTree.parent = this;
+  this.lastChild = newTree;
+};
+
+/**
+ * Create a new BoostInfo and insert it as a sub-tree with the given name.
+ * @param {string} treeName The name of the new sub-tree.
+ * @param {string} value The value associated with the new sub-tree.
+ * @return {BoostInfoTree} The created sub-tree.
+ */
+BoostInfoTree.prototype.createSubtree = function(treeName, value)
+{
+  var newTree = new BoostInfoTree(value, this);
+  this.addSubtree(treeName, newTree);
+  return newTree;
+};
+
+/**
+ * Look up using the key and return a list of the subtrees.
+ * @param {string} key The key which may be a path separated with '/'.
+ * @return {Array<BoostInfoTree>} A new array with pointers to the subtrees.
+ */
+BoostInfoTree.prototype.get = function(key)
+{
+  // Strip beginning '/'.
+  key = key.replace(/^\/+/, "");
+  if (key.length === 0)
+    return [this];
+  var path = key.split('/');
+
+  var subtrees = this.find(path[0]);
+  if (subtrees === null)
+    return [];
+  if (path.length == 1)
+    return subtrees.slice(0);
+
+  var newPath = path.slice(1).join('/');
+  var foundVals = [];
+  for (var i = 0; i < subtrees.length; ++i) {
+    var t = subtrees[i];
+    var partial = t.get(newPath);
+    foundVals = foundVals.concat(partial);
+  }
+  return foundVals;
+};
+
+/**
+ * Look up using the key and return string value of the first subtree.
+ * @param {string} key The key which may be a path separated with '/'.
+ * @return {string} The string value or null if not found.
+ */
+BoostInfoTree.prototype.getFirstValue = function(key)
+{
+  var list = this.get(key);
+  if (list.length >= 1)
+    return list[0].value;
+  else
+    return null;
+};
+
+BoostInfoTree.prototype.getValue = function() { return this.value; };
+
+BoostInfoTree.prototype.getParent = function() { return this.parent; };
+
+BoostInfoTree.prototype.getLastChild = function() { return this.lastChild; };
+
+BoostInfoTree.prototype.prettyPrint = function(indentLevel)
+{
+  indentLevel = indentLevel || 1;
+
+  var prefix = Array(indentLevel + 1).join(' ');
+  var s = "";
+
+  if (this.parent != null) {
+    if (this.value && this.value.length > 0)
+      s += "\"" + this.value + "\"";
+    s += "\n";
+  }
+
+  if (this.subtrees.length > 0) {
+    if (this.parent)
+      s += prefix + "{\n";
+    var nextLevel = Array(indentLevel + 2 + 1).join(' ');
+    for (var i = 0; i < this.subtrees.length; ++i) {
+      for (var iSubTree = 0; iSubTree < this.subtrees[i].value.length; ++iSubTree)
+        s += nextLevel + this.subtrees[i].key + " " +
+             this.subtrees[i].value[iSubTree].prettyPrint(indentLevel + 2);
+    }
+
+    if (this.parent)
+      s +=  prefix + "}\n";
+  }
+
+  return s;
+};
+
+BoostInfoTree.prototype.toString = function()
+{
+  return this.prettyPrint();
+};
+
+/**
+ * Use treeName to find the array of BoostInfoTree in this.subtrees.
+ * @param {string} treeName The key in this.subtrees to search for. This does a
+ * flat search in subtrees_.  It does not split by '/' into a path.
+ * @return {Array<BoostInfoTree>} A array of BoostInfoTree, or null if not found.
+ */
+BoostInfoTree.prototype.find = function(treeName)
+{
+  for (var i = 0; i < this.subtrees.length; ++i) {
+    if (this.subtrees[i].key == treeName)
+      return this.subtrees[i].value;
+  }
+
+  return null;
+};
+
+/**
+ * A BoostInfoParser reads files in Boost's INFO format and constructs a
+ * BoostInfoTree.
+ * @constructor
+ */
+var BoostInfoParser = function BoostInfoParser()
+{
+  this.root = new BoostInfoTree();
+};
+
+exports.BoostInfoParser = BoostInfoParser;
+exports.BoostInfoTree = BoostInfoTree; // debug
+
+/**
+ * Add the contents of the file or input string to the root BoostInfoTree. There
+ * are two forms:
+ * read(fileName) reads fileName from the file system.
+ * read(input, inputName) reads from the input, in which case inputName is used
+ * only for log messages, etc.
+ * @param {string} fileName The path to the INFO file.
+ * @param {string} input The contents of the INFO file, with lines separated by
+ * "\n" or "\r\n".
+ * @param {string} inputName Use with input for log messages, etc.
+ */
+BoostInfoParser.prototype.read = function(fileNameOrInput, inputName)
+{
+  var input;
+  if (typeof inputName == 'string')
+    input = fileNameOrInput;
+  else {
+    // No inputName, so assume the first arg is the file name.
+    var fileName = fileNameOrInput;
+    inputName = fileName;
+    input = fs.readFileSync(fileName).toString();
+  }
+
+  var ctx = this.root;
+  var thisParser = this;
+  input.split(/\r?\n/).forEach(function(line) {
+    ctx = thisParser.parseLine(line.trim(), ctx);
+  });
+};
+
+/**
+ * Write the root tree of this BoostInfoParser as file in Boost's INFO format.
+ * @param {string} fileName The output path.
+ */
+BoostInfoParser.prototype.write = function(fileName)
+{
+  fs.writeFileSync(fileName, "" + this.root);
+};
+
+/**
+ * Get the root tree of this parser.
+ * @return {BoostInfoTree} The root BoostInfoTree.
+ */
+BoostInfoParser.prototype.getRoot = function() { return this.root; };
+
+/**
+ * Similar to Python's shlex.split, split s into an array of strings which are
+ * separated by whitespace, treating a string within quotes as a single entity
+ * regardless of whitespace between the quotes. Also allow a backslash to escape
+ * the next character.
+ * @param {string} s The input string to split.
+ * @return {Array<string>} An array of strings.
+ */
+BoostInfoParser.shlex_split = function(s)
+{
+  var result = [];
+  if (s == "")
+    return result;
+  var whiteSpace = " \t\n\r";
+  var iStart = 0;
+
+  while (true) {
+    // Move iStart past whitespace.
+    while (whiteSpace.indexOf(s[iStart]) >= 0) {
+      iStart += 1;
+      if (iStart >= s.length)
+        // Done.
+        return result;
+    }
+
+    // Move iEnd to the end of the token.
+    var iEnd = iStart;
+    var inQuotation = false;
+    var token = "";
+    while (true) {
+      if (s[iEnd] == '\\') {
+        // Append characters up to the backslash, skip the backslash and
+        //   move iEnd past the escaped character.
+        token += s.substring(iStart, iEnd);
+        iStart = iEnd + 1;
+        iEnd = iStart;
+        if (iEnd >= s.length)
+          // An unusual case: A backslash at the end of the string.
+          break;
+      }
+      else {
+        if (inQuotation) {
+          if (s[iEnd] == '\"') {
+            // Append characters up to the end quote and skip.
+            token += s.substring(iStart, iEnd);
+            iStart = iEnd + 1;
+            inQuotation = false;
+          }
+        }
+        else {
+          if (s[iEnd] == '\"') {
+            // Append characters up to the start quote and skip.
+            token += s.substring(iStart, iEnd);
+            iStart = iEnd + 1;
+            inQuotation = true;
+          }
+          else
+            if (whiteSpace.indexOf(s[iEnd]) >= 0)
+              break;
+        }
+      }
+
+      iEnd += 1;
+      if (iEnd >= s.length)
+        break;
+    }
+
+    token += s.substring(iStart, iEnd);
+    result.push(token);
+    if (iEnd >= s.length)
+      // Done.
+      return result;
+
+    iStart = iEnd;
+  }
+};
+
+BoostInfoParser.prototype.parseLine = function(line, context)
+{
+  // Skip blank lines and comments.
+  var commentStart = line.indexOf(';');
+  if (commentStart >= 0)
+    line = line.substring(0, commentStart).trim();
+  if (line.length == 0)
+    return context;
+
+  // Usually we are expecting key and optional value.
+  var strings = BoostInfoParser.shlex_split(line);
+  var isSectionStart = false;
+  var isSectionEnd = false;
+  for (var i = 0; i < strings.length; ++i) {
+    isSectionStart = (isSectionStart || strings[i] == "{");
+    isSectionEnd = (isSectionEnd || strings[i] == "}");
+  }
+
+  if (!isSectionStart && !isSectionEnd) {
+    var key = strings[0];
+    var val;
+    if (strings.length > 1)
+      val = strings[1];
+    context.createSubtree(key, val);
+
+    return context;
+  }
+
+  // OK, who is the joker who put a { on the same line as the key name?!
+  var sectionStart = line.indexOf('{');
+  if (sectionStart > 0) {
+    var firstPart = line.substring(0, sectionStart);
+    var secondPart = line.substring(sectionStart);
+
+    var ctx = this.parseLine(firstPart, context);
+    return this.parseLine(secondPart, ctx);
+  }
+
+  // If we encounter a {, we are beginning a new context.
+  // TODO: Error if there was already a subcontext here.
+  if (line[0] == '{') {
+    context = context.getLastChild();
+    return context;
+  }
+
+  // If we encounter a }, we are ending a list context.
+  if (line[0] == '}') {
+    context = context.getParent();
+    return context;
+  }
+
+  throw runtime_error("BoostInfoParser: input line is malformed");
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var InterestFilter = require('../interest-filter.js').InterestFilter; /** @ignore */
+var ForwardingFlags = require('../forwarding-flags.js').ForwardingFlags; /** @ignore */
+var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * A MemoryContentCache holds a set of Data packets and answers an Interest to
+ * return the correct Data packet. The cache is periodically cleaned up to
+ * remove each stale Data packet based on its FreshnessPeriod (if it has one).
+ * @note This class is an experimental feature.  See the API docs for more detail at
+ * http://named-data.net/doc/ndn-ccl-api/memory-content-cache.html .
+ *
+ * Create a new MemoryContentCache to use the given Face.
+ *
+ * @param {Face} face The Face to use to call registerPrefix and
+ * setInterestFilter, and which will call this object's OnInterest callback.
+ * @param {number} cleanupIntervalMilliseconds (optional) The interval
+ * in milliseconds between each check to clean up stale content in the cache. If
+ * omitted, use a default of 1000 milliseconds. If this is a large number, then
+ * effectively the stale content will not be removed from the cache.
+ * @constructor
+ */
+var MemoryContentCache = function MemoryContentCache
+  (face, cleanupIntervalMilliseconds)
+{
+  cleanupIntervalMilliseconds = (cleanupIntervalMilliseconds || 1000.0);
+
+  this.face = face;
+  this.cleanupIntervalMilliseconds = cleanupIntervalMilliseconds;
+  this.nextCleanupTime = new Date().getTime() + cleanupIntervalMilliseconds;
+
+  this.onDataNotFoundForPrefix = {}; /**< The map key is the prefix.toUri().
+                                          The value is an OnInterest function. */
+  this.interestFilterIdList = []; /**< elements are number */
+  this.registeredPrefixIdList = []; /**< elements are number */
+  this.noStaleTimeCache = []; /**< elements are MemoryContentCache.Content */
+  this.staleTimeCache = [];   /**< elements are MemoryContentCache.StaleTimeContent */
+  //StaleTimeContent::Compare contentCompare_;
+  this.emptyComponent = new Name.Component();
+  this.pendingInterestTable = [];
+
+  var thisMemoryContentCache = this;
+  this.storePendingInterestCallback = function
+    (localPrefix, localInterest, localFace, localInterestFilterId, localFilter) {
+       thisMemoryContentCache.storePendingInterest(localInterest, localFace);
+    };
+};
+
+exports.MemoryContentCache = MemoryContentCache;
+
+/**
+ * Call registerPrefix on the Face given to the constructor so that this
+ * MemoryContentCache will answer interests whose name has the prefix.
+ * Alternatively, if the Face's registerPrefix has already been called,
+ * then you can call this object's setInterestFilter.
+ * @param {Name} prefix The Name for the prefix to register. This copies the Name.
+ * @param {function} onRegisterFailed If this fails to register the prefix for
+ * any reason, this calls onRegisterFailed(prefix) where prefix is the prefix
+ * given to registerPrefix.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onRegisterSuccess (optional) When this receives a success
+ * message, this calls onRegisterSuccess[0](prefix, registeredPrefixId). If
+ * onRegisterSuccess is [null] or omitted, this does not use it. (As a special
+ * case, this optional parameter is supplied as an array of one function,
+ * instead of just a function, in order to detect when it is used instead of the
+ * following optional onDataNotFound function.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onDataNotFound (optional) If a data packet for an interest
+ * is not found in the cache, this forwards the interest by calling
+ * onDataNotFound(prefix, interest, face, interestFilterId, filter). Your
+ * callback can find the Data packet for the interest and call
+ * face.putData(data). If your callback cannot find the Data packet, it can
+ * optionally call storePendingInterest(interest, face) to store the pending
+ * interest in this object to be satisfied by a later call to add(data). If you
+ * want to automatically store all pending interests, you can simply use
+ * getStorePendingInterest() for onDataNotFound. If onDataNotFound is omitted or
+ * null, this does not use it.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {ForwardingFlags} flags (optional) See Face.registerPrefix.
+ * @param {WireFormat} wireFormat (optional) See Face.registerPrefix.
+ */
+MemoryContentCache.prototype.registerPrefix = function
+  (prefix, onRegisterFailed, onRegisterSuccess, onDataNotFound, flags, wireFormat)
+{
+  var arg3 = onRegisterSuccess;
+  var arg4 = onDataNotFound;
+  var arg5 = flags;
+  var arg6 = wireFormat;
+  // arg3,                arg4,            arg5,            arg6 may be:
+  // [OnRegisterSuccess], OnDataNotFound,  ForwardingFlags, WireFormat
+  // [OnRegisterSuccess], OnDataNotFound,  ForwardingFlags, null
+  // [OnRegisterSuccess], OnDataNotFound,  WireFormat,      null
+  // [OnRegisterSuccess], OnDataNotFound,  null,            null
+  // [OnRegisterSuccess], ForwardingFlags, WireFormat,      null
+  // [OnRegisterSuccess], ForwardingFlags, null,            null
+  // [OnRegisterSuccess], WireFormat,      null,            null
+  // [OnRegisterSuccess], null,            null,            null
+  // OnDataNotFound,      ForwardingFlags, WireFormat,      null
+  // OnDataNotFound,      ForwardingFlags, null,            null
+  // OnDataNotFound,      WireFormat,      null,            null
+  // OnDataNotFound,      null,            null,            null
+  // ForwardingFlags,     WireFormat,      null,            null
+  // ForwardingFlags,     null,            null,            null
+  // WireFormat,          null,            null,            null
+  // null,                null,            null,            null
+  if (typeof arg3 === "object" && arg3.length === 1 &&
+      typeof arg3[0] === "function")
+    onRegisterSuccess = arg3[0];
+  else
+    onRegisterSuccess = null;
+
+  if (typeof arg3 === "function")
+    onDataNotFound = arg3;
+  else if (typeof arg4 === "function")
+    onDataNotFound = arg4;
+  else
+    onDataNotFound = null;
+
+  if (arg3 instanceof ForwardingFlags)
+    flags = arg3;
+  else if (arg4 instanceof ForwardingFlags)
+    flags = arg4;
+  else if (arg5 instanceof ForwardingFlags)
+    flags = arg5;
+  else
+    flags = new ForwardingFlags();
+
+  if (arg3 instanceof WireFormat)
+    wireFormat = arg3;
+  else if (arg4 instanceof WireFormat)
+    wireFormat = arg4;
+  else if (arg5 instanceof WireFormat)
+    wireFormat = arg5;
+  else if (arg6 instanceof WireFormat)
+    wireFormat = arg6;
+  else
+    wireFormat = WireFormat.getDefaultWireFormat();
+
+  if (onDataNotFound)
+    this.onDataNotFoundForPrefix[prefix.toUri()] = onDataNotFound;
+  var registeredPrefixId = this.face.registerPrefix
+    (prefix, this.onInterest.bind(this), onRegisterFailed, onRegisterSuccess,
+     flags, wireFormat);
+  this.registeredPrefixIdList.push(registeredPrefixId);
+};
+
+/**
+ * Call setInterestFilter on the Face given to the constructor so that this
+ * MemoryContentCache will answer interests whose name matches the filter.
+ * There are two forms of setInterestFilter.
+ * The first form uses the exact given InterestFilter:
+ * setInterestFilter(filter, [onDataNotFound]).
+ * The second form creates an InterestFilter from the given prefix Name:
+ * setInterestFilter(prefix, [onDataNotFound]).
+ * @param {InterestFilter} filter The InterestFilter with a prefix and optional
+ * regex filter used to match the name of an incoming Interest. This makes a
+ * copy of filter.
+ * @param {Name} prefix The Name prefix used to match the name of an incoming
+ * Interest.
+ * @param {function} onDataNotFound (optional) If a data packet for an interest
+ * is not found in the cache, this forwards the interest by calling
+ * onDataNotFound(prefix, interest, face, interestFilterId, filter). Your
+ * callback can find the Data packet for the interest and call
+ * face.putData(data). If your callback cannot find the Data packet, it can
+ * optionally call storePendingInterest(interest, face) to store the pending
+ * interest in this object to be satisfied by a later call to add(data). If you
+ * want to automatically store all pending interests, you can simply use
+ * getStorePendingInterest() for onDataNotFound. If onDataNotFound is omitted or
+ * null, this does not use it.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+MemoryContentCache.prototype.setInterestFilter = function
+  (filterOrPrefix, onDataNotFound)
+{
+  if (onDataNotFound) {
+    var prefix;
+    if (typeof filterOrPrefix === 'object' && filterOrPrefix instanceof InterestFilter)
+      prefix = filterOrPrefix.getPrefix();
+    else
+      prefix = filterOrPrefix;
+    this.onDataNotFoundForPrefix[prefix.toUri()] = onDataNotFound;
+  }
+  var interestFilterId = this.face.setInterestFilter
+    (filterOrPrefix, this.onInterest.bind(this));
+  this.interestFilterIdList.push(interestFilterId);
+};
+
+/**
+ * Call Face.unsetInterestFilter and Face.removeRegisteredPrefix for all the
+ * prefixes given to the setInterestFilter and registerPrefix method on this
+ * MemoryContentCache object so that it will not receive interests any more. You
+ * can call this if you want to "shut down" this MemoryContentCache while your
+ * application is still running.
+ */
+MemoryContentCache.prototype.unregisterAll = function()
+{
+  for (var i = 0; i < this.interestFilterIdList.length; ++i)
+    this.face.unsetInterestFilter(this.interestFilterIdList[i]);
+  this.interestFilterIdList = [];
+
+  for (var i = 0; i < this.registeredPrefixIdList.length; ++i)
+    this.face.removeRegisteredPrefix(this.registeredPrefixIdList[i]);
+  this.registeredPrefixIdList = [];
+
+  // Also clear each onDataNotFoundForPrefix given to registerPrefix.
+  this.onDataNotFoundForPrefix = {};
+};
+
+/**
+ * Add the Data packet to the cache so that it is available to use to answer
+ * interests. If data.getMetaInfo().getFreshnessPeriod() is not null, set the
+ * staleness time to now plus data.getMetaInfo().getFreshnessPeriod(), which is
+ * checked during cleanup to remove stale content. This also checks if
+ * cleanupIntervalMilliseconds milliseconds have passed and removes stale
+ * content from the cache. After removing stale content, remove timed-out
+ * pending interests from storePendingInterest(), then if the added Data packet
+ * satisfies any interest, send it through the face and remove the interest
+ * from the pending interest table.
+ * @param {Data} data The Data packet object to put in the cache. This copies
+ * the fields from the object.
+ */
+MemoryContentCache.prototype.add = function(data)
+{
+  this.doCleanup();
+
+  if (data.getMetaInfo().getFreshnessPeriod() != null &&
+      data.getMetaInfo().getFreshnessPeriod() >= 0.0) {
+    // The content will go stale, so use staleTimeCache.
+    var content = new MemoryContentCache.StaleTimeContent(data);
+    // Insert into staleTimeCache, sorted on content.staleTimeMilliseconds.
+    // Search from the back since we expect it to go there.
+    var i = this.staleTimeCache.length - 1;
+    while (i >= 0) {
+      if (this.staleTimeCache[i].staleTimeMilliseconds <= content.staleTimeMilliseconds)
+        break;
+      --i;
+    }
+    // Element i is the greatest less than or equal to
+    // content.staleTimeMilliseconds, so insert after it.
+    this.staleTimeCache.splice(i + 1, 0, content);
+  }
+  else
+    // The data does not go stale, so use noStaleTimeCache.
+    this.noStaleTimeCache.push(new MemoryContentCache.Content(data));
+
+  // Remove timed-out interests and check if the data packet matches any pending
+  // interest.
+  // Go backwards through the list so we can erase entries.
+  var nowMilliseconds = new Date().getTime();
+  for (var i = this.pendingInterestTable.length - 1; i >= 0; --i) {
+    if (this.pendingInterestTable[i].isTimedOut(nowMilliseconds)) {
+      this.pendingInterestTable.splice(i, 1);
+      continue;
+    }
+    if (this.pendingInterestTable[i].getInterest().matchesName(data.getName())) {
+      try {
+        // Send to the same face from the original call to onInterest.
+        // wireEncode returns the cached encoding if available.
+        this.pendingInterestTable[i].getFace().send(data.wireEncode().buf());
+      }
+      catch (ex) {
+        if (LOG > 0)
+          console.log("" + ex);
+        return;
+      }
+
+      // The pending interest is satisfied, so remove it.
+      this.pendingInterestTable.splice(i, 1);
+    }
+  }
+};
+
+/**
+ * Store an interest from an OnInterest callback in the internal pending
+ * interest table (normally because there is no Data packet available yet to
+ * satisfy the interest). add(data) will check if the added Data packet
+ * satisfies any pending interest and send it through the face.
+ * @param {Interest} interest The Interest for which we don't have a Data packet
+ * yet. You should not modify the interest after calling this.
+ * @param {Face} face The Face with the connection which received
+ * the interest. This comes from the OnInterest callback.
+ */
+MemoryContentCache.prototype.storePendingInterest = function(interest, face)
+{
+  this.pendingInterestTable.push
+    (new MemoryContentCache.PendingInterest(interest, face));
+};
+
+/**
+ * Return a callback to use for onDataNotFound in registerPrefix which simply
+ * calls storePendingInterest() to store the interest that doesn't match a
+ * Data packet. add(data) will check if the added Data packet satisfies any
+ * pending interest and send it.
+ * @return {function} A callback to use for onDataNotFound in registerPrefix().
+ */
+MemoryContentCache.prototype.getStorePendingInterest = function()
+{
+  return this.storePendingInterestCallback;
+};
+
+/**
+ * This is the OnInterest callback which is called when the library receives
+ * an interest whose name has the prefix given to registerPrefix. First check
+ * if cleanupIntervalMilliseconds milliseconds have passed and remove stale
+ * content from the cache. Then search the cache for the Data packet, matching
+ * any interest selectors including ChildSelector, and send the Data packet
+ * to the face. If no matching Data packet is in the cache, call
+ * the callback in onDataNotFoundForPrefix (if defined).
+ */
+MemoryContentCache.prototype.onInterest = function
+  (prefix, interest, face, interestFilterId, filter)
+{
+  this.doCleanup();
+
+  var selectedComponent = 0;
+  var selectedEncoding = null;
+  // We need to iterate over both arrays.
+  var totalSize = this.staleTimeCache.length + this.noStaleTimeCache.length;
+  for (var i = 0; i < totalSize; ++i) {
+    var content;
+    if (i < this.staleTimeCache.length)
+      content = this.staleTimeCache[i];
+    else
+      // We have iterated over the first array. Get from the second.
+      content = this.noStaleTimeCache[i - this.staleTimeCache.length];
+
+    if (interest.matchesName(content.getName())) {
+      if (interest.getChildSelector() < 0) {
+        // No child selector, so send the first match that we have found.
+        face.send(content.getDataEncoding());
+        return;
+      }
+      else {
+        // Update selectedEncoding based on the child selector.
+        var component;
+        if (content.getName().size() > interest.getName().size())
+          component = content.getName().get(interest.getName().size());
+        else
+          component = this.emptyComponent;
+
+        var gotBetterMatch = false;
+        if (selectedEncoding === null)
+          // Save the first match.
+          gotBetterMatch = true;
+        else {
+          if (interest.getChildSelector() == 0) {
+            // Leftmost child.
+            if (component.compare(selectedComponent) < 0)
+              gotBetterMatch = true;
+          }
+          else {
+            // Rightmost child.
+            if (component.compare(selectedComponent) > 0)
+              gotBetterMatch = true;
+          }
+        }
+
+        if (gotBetterMatch) {
+          selectedComponent = component;
+          selectedEncoding = content.getDataEncoding();
+        }
+      }
+    }
+  }
+
+  if (selectedEncoding !== null)
+    // We found the leftmost or rightmost child.
+    face.send(selectedEncoding);
+  else {
+    // Call the onDataNotFound callback (if defined).
+    var onDataNotFound = this.onDataNotFoundForPrefix[prefix.toUri()];
+    if (onDataNotFound)
+      onDataNotFound(prefix, interest, face, interestFilterId, filter);
+  }
+};
+
+/**
+ * Check if now is greater than nextCleanupTime and, if so, remove stale
+ * content from staleTimeCache and reset nextCleanupTime based on
+ * cleanupIntervalMilliseconds. Since add(Data) does a sorted insert into
+ * staleTimeCache, the check for stale data is quick and does not require
+ * searching the entire staleTimeCache.
+ */
+MemoryContentCache.prototype.doCleanup = function()
+{
+  var now = new Date().getTime();
+  if (now >= this.nextCleanupTime) {
+    // staleTimeCache is sorted on staleTimeMilliseconds, so we only need to
+    // erase the stale entries at the front, then quit.
+    while (this.staleTimeCache.length > 0 && this.staleTimeCache[0].isStale(now))
+      this.staleTimeCache.shift();
+
+    this.nextCleanupTime = now + this.cleanupIntervalMilliseconds;
+  }
+};
+
+/**
+ * Content is a private class to hold the name and encoding for each entry
+ * in the cache. This base class is for a Data packet without a FreshnessPeriod.
+ *
+ * Create a new Content entry to hold data's name and wire encoding.
+ * @param {Data} data The Data packet whose name and wire encoding are copied.
+ */
+MemoryContentCache.Content = function MemoryContentCacheContent(data)
+{
+  // Allow an undefined data so that StaleTimeContent can set the prototype.
+  if (data) {
+    // Copy the name.
+    this.name = new Name(data.getName());
+    // wireEncode returns the cached encoding if available.
+    this.dataEncoding = data.wireEncode().buf();
+  }
+};
+
+MemoryContentCache.Content.prototype.getName = function() { return this.name; };
+
+MemoryContentCache.Content.prototype.getDataEncoding = function() { return this.dataEncoding; };
+
+/**
+ * StaleTimeContent extends Content to include the staleTimeMilliseconds for
+ * when this entry should be cleaned up from the cache.
+ *
+ * Create a new StaleTimeContent to hold data's name and wire encoding as well
+ * as the staleTimeMilliseconds which is now plus
+ * data.getMetaInfo().getFreshnessPeriod().
+ * @param {Data} data The Data packet whose name and wire encoding are copied.
+ */
+MemoryContentCache.StaleTimeContent = function MemoryContentCacheStaleTimeContent
+  (data)
+{
+  // Call the base constructor.
+  MemoryContentCache.Content.call(this, data);
+
+  // Set up staleTimeMilliseconds which is The time when the content becomse
+  // stale in milliseconds according to new Date().getTime().
+  this.staleTimeMilliseconds = new Date().getTime() +
+    data.getMetaInfo().getFreshnessPeriod();
+};
+
+MemoryContentCache.StaleTimeContent.prototype = new MemoryContentCache.Content();
+MemoryContentCache.StaleTimeContent.prototype.name = "StaleTimeContent";
+
+/**
+ * Check if this content is stale.
+ * @param {number} nowMilliseconds The current time in milliseconds from
+ * new Date().getTime().
+ * @return {boolean} True if this content is stale, otherwise false.
+ */
+MemoryContentCache.StaleTimeContent.prototype.isStale = function(nowMilliseconds)
+{
+  return this.staleTimeMilliseconds <= nowMilliseconds;
+};
+
+/**
+ * A PendingInterest holds an interest which onInterest received but could
+ * not satisfy. When we add a new data packet to the cache, we will also check
+ * if it satisfies a pending interest.
+ */
+MemoryContentCache.PendingInterest = function MemoryContentCachePendingInterest
+  (interest, face)
+{
+  this.interest = interest;
+  this.face = face;
+
+  if (this.interest.getInterestLifetimeMilliseconds() >= 0.0)
+    this.timeoutMilliseconds = (new Date()).getTime() +
+      this.interest.getInterestLifetimeMilliseconds();
+  else
+    this.timeoutMilliseconds = -1.0;
+};
+
+/**
+ * Return the interest given to the constructor.
+ */
+MemoryContentCache.PendingInterest.prototype.getInterest = function()
+{
+  return this.interest;
+};
+
+/**
+ * Return the face given to the constructor.
+ */
+MemoryContentCache.PendingInterest.prototype.getFace = function()
+{
+  return this.face;
+};
+
+/**
+ * Check if this interest is timed out.
+ * @param {number} nowMilliseconds The current time in milliseconds from
+ * new Date().getTime().
+ * @return {boolean} True if this interest timed out, otherwise false.
+ */
+MemoryContentCache.PendingInterest.prototype.isTimedOut = function(nowMilliseconds)
+{
+  return this.timeoutTimeMilliseconds >= 0.0 &&
+         nowMilliseconds >= this.timeoutTimeMilliseconds;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From PyNDN ndn_regex.py by Adeola Bannis.
+ * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../name.js').Name;
+
+/**
+ * An NdnRegexMatcher has static methods to convert an NDN regex
+ * (http://redmine.named-data.net/projects/ndn-cxx/wiki/Regex) to a JavaScript
+ * RegExp that can match against URIs.
+ * @constructor
+ */
+var NdnRegexMatcher = function NdnRegexMatcher()
+{
+};
+
+exports.NdnRegexMatcher = NdnRegexMatcher;
+
+/**
+ * Determine if the provided NDN regex matches the given Name.
+ * @param {string} pattern The NDN regex.
+ * @param {Name} name The Name to match against the regex.
+ * @return {Object} The match object from String.match, or null if the pattern
+ * does not match.
+ */
+NdnRegexMatcher.match = function(pattern, name)
+{
+  var nameUri = name.toUri();
+
+  pattern = NdnRegexMatcher.sanitizeSets(pattern);
+
+  pattern = pattern.replace(/<>/g, "(?:<.+?>)");
+  pattern = pattern.replace(/>/g, "");
+  pattern = pattern.replace(/<(?!!)/g, "/");
+
+  return nameUri.match(new RegExp(pattern));
+};
+
+NdnRegexMatcher.sanitizeSets = function(pattern)
+{
+  var newPattern = pattern;
+
+  // Positive sets can be changed to (comp1|comp2).
+  // Negative sets must be changed to negative lookahead assertions.
+
+  var regex1 = /\[(\^?)(.*?)\]/g;
+  var match;
+  while ((match = regex1.exec(pattern)) !== null) {
+    // Insert | between components.
+    // Match 2 is the last match, so we use the hack of working backwards from
+    //   lastIndex.  If possible, this should be changed to a more direct solution.
+    var start = regex1.lastIndex - "]".length - match[2].length;
+    var end = start + match[2].length;
+    if (start - end === 0)
+      continue;
+    var oldStr = match[2];
+    var newStr = oldStr.replace(/></g, ">|<");
+    newPattern = newPattern.substr(0, start) + newStr + newPattern.substr(end);
+  }
+
+  // Replace [] with (),  or (?! ) for negative lookahead.
+  // If we use negative lookahead, we also have to consume one component.
+  var isNegative = newPattern.indexOf("[^") >= 0;
+  if (isNegative) {
+    newPattern = newPattern.replace(/\[\^/g, "(?:(?!");
+    newPattern = newPattern.replace(/\]/g, ")(?:/.*)*)");
+  }
+  else {
+    newPattern = newPattern.replace(/\[/g, "(");
+    newPattern = newPattern.replace(/\]/g, ")");
+  }
+
+  return newPattern;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-cxx util/segment-fetcher https://github.com/named-data/ndn-cxx
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Blob = require('./blob.js').Blob; /** @ignore */
+var KeyChain = require('../security/key-chain.js').KeyChain; /** @ignore */
+var NdnCommon = require('./ndn-common.js').NdnCommon;
+
+/**
+ * SegmentFetcher is a utility class to fetch the latest version of segmented data.
+ *
+ * SegmentFetcher assumes that the data is named /<prefix>/<version>/<segment>,
+ * where:
+ * - <prefix> is the specified name prefix,
+ * - <version> is an unknown version that needs to be discovered, and
+ * - <segment> is a segment number. (The number of segments is unknown and is
+ *   controlled by the `FinalBlockId` field in at least the last Data packet.
+ *
+ * The following logic is implemented in SegmentFetcher:
+ *
+ * 1. Express the first Interest to discover the version:
+ *
+ *    >> Interest: /<prefix>?ChildSelector=1&MustBeFresh=true
+ *
+ * 2. Infer the latest version of the Data: <version> = Data.getName().get(-2)
+ *
+ * 3. If the segment number in the retrieved packet == 0, go to step 5.
+ *
+ * 4. Send an Interest for segment 0:
+ *
+ *    >> Interest: /<prefix>/<version>/<segment=0>
+ *
+ * 5. Keep sending Interests for the next segment while the retrieved Data does
+ *    not have a FinalBlockId or the FinalBlockId != Data.getName().get(-1).
+ *
+ *    >> Interest: /<prefix>/<version>/<segment=(N+1))>
+ *
+ * 6. Call the onComplete callback with a Blob that concatenates the content
+ *    from all the segmented objects.
+ *
+ * If an error occurs during the fetching process, the onError callback is called
+ * with a proper error code.  The following errors are possible:
+ *
+ * - `INTEREST_TIMEOUT`: if any of the Interests times out
+ * - `DATA_HAS_NO_SEGMENT`: if any of the retrieved Data packets don't have a segment
+ *   as the last component of the name (not counting the implicit digest)
+ * - `SEGMENT_VERIFICATION_FAILED`: if any retrieved segment fails
+ *   the user-provided VerifySegment callback or KeyChain verifyData.
+ * - `IO_ERROR`: for I/O errors when sending an Interest.
+ *
+ * In order to validate individual segments, a KeyChain needs to be supplied.
+ * If verifyData fails, the fetching process is aborted with
+ * SEGMENT_VERIFICATION_FAILED. If data validation is not required, pass null.
+ *
+ * Example:
+ *     var onComplete = function(content) { ... }
+ *
+ *     var onError = function(errorCode, message) { ... }
+ *
+ *     var interest = new Interest(new Name("/data/prefix"));
+ *     interest.setInterestLifetimeMilliseconds(1000);
+ *
+ *     SegmentFetcher.fetch(face, interest, null, onComplete, onError);
+ *
+ * This is a private constructor to create a new SegmentFetcher to use the Face.
+ * An application should use SegmentFetcher.fetch. If validatorKeyChain is not
+ * null, use it and ignore verifySegment. After creating the SegmentFetcher,
+ * call fetchFirstSegment.
+ * @param {Face} face This calls face.expressInterest to fetch more segments.
+ * @param validatorKeyChain {KeyChain} If this is not null, use its verifyData
+ * instead of the verifySegment callback.
+ * @param {function} verifySegment When a Data packet is received this calls
+ * verifySegment(data) where data is a Data object. If it returns False then
+ * abort fetching and call onError with
+ * SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onComplete When all segments are received, call
+ * onComplete(content) where content is a Blob which has the concatenation of
+ * the content of all the segments.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError Call onError.onError(errorCode, message) for
+ * timeout or an error processing segments. errorCode is a value from
+ * SegmentFetcher.ErrorCode and message is a related string.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @constructor
+ */
+var SegmentFetcher = function SegmentFetcher
+  (face, validatorKeyChain, verifySegment, onComplete, onError)
+{
+  this.face = face;
+  this.validatorKeyChain = validatorKeyChain;
+  this.verifySegment = verifySegment;
+  this.onComplete = onComplete;
+  this.onError = onError;
+
+  this.contentParts = []; // of Buffer
+};
+
+exports.SegmentFetcher = SegmentFetcher;
+
+/**
+ * An ErrorCode value is passed in the onError callback.
+ */
+SegmentFetcher.ErrorCode = {
+  INTEREST_TIMEOUT: 1,
+  DATA_HAS_NO_SEGMENT: 2,
+  SEGMENT_VERIFICATION_FAILED: 3
+};
+
+/**
+ * DontVerifySegment may be used in fetch to skip validation of Data packets.
+ */
+SegmentFetcher.DontVerifySegment = function(data)
+{
+  return true;
+};
+
+/**
+ * Initiate segment fetching. For more details, see the documentation for the
+ * class. There are two forms of fetch:
+ * fetch(face, baseInterest, validatorKeyChain, onComplete, onError)
+ * and
+ * fetch(face, baseInterest, verifySegment, onComplete, onError)
+ * @param {Face} face This calls face.expressInterest to fetch more segments.
+ * @param {Interest} baseInterest An Interest for the initial segment of the
+ * requested data, where baseInterest.getName() has the name prefix. This
+ * interest may include a custom InterestLifetime and selectors that will
+ * propagate to all subsequent Interests. The only exception is that the initial
+ * Interest will be forced to include selectors "ChildSelector=1" and
+ * "MustBeFresh=true" which will be turned off in subsequent Interests.
+ * @param validatorKeyChain {KeyChain} When a Data packet is received this calls
+ * validatorKeyChain.verifyData(data). If validation fails then abortfetching
+ * and call onError with SEGMENT_VERIFICATION_FAILED. This does not make a copy
+ * of the KeyChain; the object must remain valid while fetching.
+ * If validatorKeyChain is null, this does not validate the data packet.
+ * @param {function} verifySegment When a Data packet is received this calls
+ * verifySegment(data) where data is a Data object. If it returns False then
+ * abort fetching and call onError with
+ * SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED. If data validation is
+ * not required, use SegmentFetcher.DontVerifySegment.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onComplete When all segments are received, call
+ * onComplete(content) where content is a Blob which has the concatenation of
+ * the content of all the segments.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError Call onError.onError(errorCode, message) for
+ * timeout or an error processing segments. errorCode is a value from
+ * SegmentFetcher.ErrorCode and message is a related string.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+SegmentFetcher.fetch = function
+  (face, baseInterest, validatorKeyChainOrVerifySegment, onComplete, onError)
+{
+  if (validatorKeyChainOrVerifySegment == null ||
+      validatorKeyChainOrVerifySegment instanceof KeyChain)
+    new SegmentFetcher
+      (face, validatorKeyChainOrVerifySegment, SegmentFetcher.DontVerifySegment,
+       onComplete, onError)
+      .fetchFirstSegment(baseInterest);
+  else
+    new SegmentFetcher
+      (face, null, validatorKeyChainOrVerifySegment, onComplete, onError)
+      .fetchFirstSegment(baseInterest);
+};
+
+SegmentFetcher.prototype.fetchFirstSegment = function(baseInterest)
+{
+  var interest = new Interest(baseInterest);
+  interest.setChildSelector(1);
+  interest.setMustBeFresh(true);
+  var thisSegmentFetcher = this;
+  this.face.expressInterest
+    (interest,
+     function(originalInterest, data)
+       { thisSegmentFetcher.onData(originalInterest, data); },
+     function(interest) { thisSegmentFetcher.onTimeout(interest); });
+};
+
+SegmentFetcher.prototype.fetchNextSegment = function
+  (originalInterest, dataName, segment)
+{
+  // Start with the original Interest to preserve any special selectors.
+  var interest = new Interest(originalInterest);
+  // Changing a field clears the nonce so that the library will generate a new
+  // one.
+  interest.setChildSelector(0);
+  interest.setMustBeFresh(false);
+  interest.setName(dataName.getPrefix(-1).appendSegment(segment));
+  var thisSegmentFetcher = this;
+  this.face.expressInterest
+    (interest, function(originalInterest, data)
+       { thisSegmentFetcher.onData(originalInterest, data); },
+     function(interest) { thisSegmentFetcher.onTimeout(interest); });
+};
+
+SegmentFetcher.prototype.onData = function(originalInterest, data)
+{
+  if (this.validatorKeyChain != null) {
+    try {
+      var thisSegmentFetcher = this;
+      this.validatorKeyChain.verifyData
+        (data,
+         function(localData) {
+           thisSegmentFetcher.onVerified(localData, originalInterest);
+         },
+         this.onValidationFailed.bind(this));
+    } catch (ex) {
+      console.log("Error in KeyChain.verifyData: " + ex);
+    }
+  }
+  else {
+    if (!this.verifySegment(data)) {
+      try {
+        this.onError
+          (SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,
+           "Segment verification failed");
+      } catch (ex) {
+        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return;
+    }
+
+    this.onVerified(data, originalInterest);
+  }
+};
+
+SegmentFetcher.prototype.onVerified = function(data, originalInterest)
+{
+  if (!SegmentFetcher.endsWithSegmentNumber(data.getName())) {
+    // We don't expect a name without a segment number.  Treat it as a bad packet.
+    try {
+      this.onError
+        (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
+         "Got an unexpected packet without a segment number: " +
+          data.getName().toUri());
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+  else {
+    var currentSegment = 0;
+    try {
+      currentSegment = data.getName().get(-1).toSegment();
+    }
+    catch (ex) {
+      try {
+        this.onError
+          (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
+           "Error decoding the name segment number " +
+           data.getName().get(-1).toEscapedString() + ": " + ex);
+      } catch (ex) {
+        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return;
+    }
+
+    var expectedSegmentNumber = this.contentParts.length;
+    if (currentSegment != expectedSegmentNumber)
+      // Try again to get the expected segment.  This also includes the case
+      // where the first segment is not segment 0.
+      this.fetchNextSegment
+        (originalInterest, data.getName(), expectedSegmentNumber);
+    else {
+      // Save the content and check if we are finished.
+      this.contentParts.push(data.getContent().buf());
+
+      if (data.getMetaInfo().getFinalBlockId().getValue().size() > 0) {
+        var finalSegmentNumber = 0;
+        try {
+          finalSegmentNumber = (data.getMetaInfo().getFinalBlockId().toSegment());
+        }
+        catch (ex) {
+          try {
+            this.onError
+              (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
+               "Error decoding the FinalBlockId segment number " +
+               data.getMetaInfo().getFinalBlockId().toEscapedString() +
+               ": " + ex);
+          } catch (ex) {
+            console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+          }
+          return;
+        }
+
+        if (currentSegment == finalSegmentNumber) {
+          // We are finished.
+
+          // Concatenate to get content.
+          var content = Buffer.concat(this.contentParts);
+          try {
+            this.onComplete(new Blob(content, false));
+          } catch (ex) {
+            console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
+          }
+          return;
+        }
+      }
+
+      // Fetch the next segment.
+      this.fetchNextSegment
+        (originalInterest, data.getName(), expectedSegmentNumber + 1);
+    }
+  }
+}
+
+SegmentFetcher.prototype.onValidationFailed = function(data, reason)
+{
+  try {
+    this.onError
+      (SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,
+       "Segment verification failed for " + data.getName().toUri() +
+       " . Reason: " + reason);
+  } catch (ex) {
+    console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+};
+
+SegmentFetcher.prototype.onTimeout = function(interest)
+{
+  try {
+    this.onError
+      (SegmentFetcher.ErrorCode.INTEREST_TIMEOUT,
+       "Time out for interest " + interest.getName().toUri());
+  } catch (ex) {
+    console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+};
+
+/**
+ * Check if the last component in the name is a segment number.
+ * @param {Name} name The name to check.
+ * @return {boolean} True if the name ends with a segment number, otherwise false.
+ */
+SegmentFetcher.endsWithSegmentNumber = function(name)
+{
+  return name.size() >= 1 && name.get(-1).isSegment();
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Transport is a base class for specific transport classes such as TcpTransport.
+ * @constructor
+ */
+var Transport = function Transport()
+{
+};
+
+exports.Transport = Transport;
+
+/**
+ * Transport.ConnectionInfo is a base class for connection information used by
+ * subclasses of Transport.
+ */
+Transport.ConnectionInfo = function TransportConnectionInfo()
+{
+};
+
+/**
+ * Determine whether this transport connecting according to connectionInfo is to
+ * a node on the current machine. This affects the processing of
+ * Face.registerPrefix(): if the NFD is local, registration occurs with the
+ * '/localhost/nfd...' prefix; if non-local, the library will attempt to use
+ * remote prefix registration using '/localhop/nfd...'
+ * @param {Transport.ConnectionInfo} connectionInfo A ConnectionInfo with the
+ * host to check.
+ * @param {function} onResult On success, this calls onResult(isLocal) where
+ * isLocal is true if the host is local, false if not. We use callbacks because
+ * this may need to do an asynchronous DNS lookup.
+ * @param {function} onError On failure for DNS lookup or other error, this
+ * calls onError(message) where message is an error string.
+ */
+Transport.prototype.isLocal = function(connectionInfo, onResult, onError)
+{
+  onError("Transport.isLocal is not implemented");
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A MicroForwarderTransport extends Transport to connect to the browser's
+ * micro forwarder service. This assumes that the MicroForwarder extensions has
+ * been installed.
+ * @constructor
+ */
+var MicroForwarderTransport = function MicroForwarderTransport()
+{
+  // Call the base constructor.
+  Transport.call(this);
+
+  this.elementReader = null;
+  this.connectionInfo = null; // Read by Face.
+  this.onReceivedObject = null;
+
+  var thisTransport = this;
+  window.addEventListener("message", function(event) {
+    // We only accept messages from ourselves
+    if (event.source != window)
+      return;
+
+    if (event.data.type && (event.data.type == "FromMicroForwarderStub")) {
+      var obj = event.data.object;
+      if (obj.type && obj.type == "Buffer") {
+        if (thisTransport.elementReader != null)
+          thisTransport.elementReader.onReceivedData(new Buffer(obj.data));
+      }
+      else {
+        if (thisTransport.onReceivedObject)
+          thisTransport.onReceivedObject(obj);
+      }
+    }
+  }, false);
+};
+
+MicroForwarderTransport.prototype = new Transport();
+MicroForwarderTransport.prototype.name = "MicroForwarderTransport";
+
+/**
+ * Create a new MicroForwarderTransport.ConnectionInfo which extends
+ * Transport.ConnectionInfo to hold info for the micro forwarer connection.
+ */
+MicroForwarderTransport.ConnectionInfo = function MicroForwarderTransportConnectionInfo()
+{
+  // Call the base constructor.
+  Transport.ConnectionInfo .call(this);
+};
+
+MicroForwarderTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
+MicroForwarderTransport.ConnectionInfo.prototype.name = "MicroForwarderTransport.ConnectionInfo";
+
+/**
+ * Check if the fields of this MicroForwarderTransport.ConnectionInfo equal the other
+ * MicroForwarderTransport.ConnectionInfo.
+ * @param {MicroForwarderTransport.ConnectionInfo} The other object to check.
+ * @return {boolean} True if the objects have equal fields, false if not.
+ */
+MicroForwarderTransport.ConnectionInfo.prototype.equals = function(other)
+{
+  if (other == null)
+    return false;
+  return true;
+};
+
+MicroForwarderTransport.ConnectionInfo.prototype.toString = function()
+{
+  return "{}";
+};
+
+/**
+ * Set the onReceivedObject callback, replacing any previous callback.
+ * @param {function} onReceivedObject (optional) If supplied and the received
+ * object type field is not "Buffer" then just call this.onReceivedObject(obj).
+ * If this is null, then don't call it.
+ */
+MicroForwarderTransport.prototype.setOnReceivedObject = function(onReceivedObject)
+{
+  this.onReceivedObject = onReceivedObject;
+}
+
+/**
+ * Determine whether this transport connecting according to connectionInfo is to
+ * a node on the current machine. Unix transports are always local.
+ * @param {MicroForwarderTransport.ConnectionInfo} connectionInfo This is ignored.
+ * @param {function} onResult This calls onResult(true) because micro forwarder
+ * transports are always local.
+ * @param {function} onError This is ignored.
+ */
+MicroForwarderTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
+{
+  onResult(true);
+};
+
+/**
+ * Connect to the micro forwarder according to the info in connectionInfo.
+ * Listen on the connection to read an entire packet element and call
+ * elementListener.onReceivedElement(element). However, if the received object
+ * type field is not "Buffer" then just call this.onReceivedObject(obj).
+ * @param {MicroForwarderTransport.ConnectionInfo} connectionInfo
+ * @param {object} elementListener The elementListener with function
+ * onReceivedElement which must remain valid during the life of this object.
+ * @param {function} onopenCallback Once connected, call onopenCallback().
+ * @param {function} onclosedCallback (optional) If the connection is closed by
+ * the remote host, call onclosedCallback(). If omitted or null, don't call it.
+ */
+MicroForwarderTransport.prototype.connect = function
+  (connectionInfo, elementListener, onopenCallback, onclosedCallback)
+{
+  // The window listener is already set up.
+  this.elementReader = new ElementReader(elementListener);
+  this.connectionInfo = connectionInfo;
+  onopenCallback();
+};
+
+/**
+ * Send the JavaScript over the connection created by connect.
+ * @param {object} obj The object to send. It should have a field "type". If
+ * "type" is "Buffer" then it is processed like an NDN packet.
+ */
+MicroForwarderTransport.prototype.sendObject = function(obj)
+{
+  window.postMessage({
+    type: "FromMicroForwarderTransport",
+    object: obj
+  }, "*");
+};
+
+/**
+ * Send the buffer over the connection created by connect.
+ * @param {Buffer} buffer The bytes to send.
+ */
+MicroForwarderTransport.prototype.send = function(buffer)
+{
+  if (this.connectionInfo == null) {
+    console.log("MicroForwarderTransport connection is not established.");
+    return;
+  }
+
+  this.sendObject(buffer.toJSON());
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A RuntimePortTransport extends Transport to connect to a WebExtensions
+ * runtime.port.
+ * @param {function} onReceivedObject (optional) If supplied and the received
+ * object type field is not "Buffer" then just call this.onReceivedObject(obj).
+ * If this is null, then don't call it.
+ * @constructor
+ */
+var RuntimePortTransport = function RuntimePortTransport(onReceivedObject)
+{
+  // Call the base constructor.
+  Transport.call(this);
+
+  this.elementReader = null;
+  this.connectionInfo = null; // Read by Face.
+  this.onReceivedObject = onReceivedObject;
+  this.port = null;
+};
+
+RuntimePortTransport.prototype = new Transport();
+RuntimePortTransport.prototype.name = "RuntimePortTransport";
+
+/**
+ * Create a new RuntimePortTransport.ConnectionInfo which extends
+ * Transport.ConnectionInfo to hold the runtime.port used to connect.
+ * @param {runtime.port} port The runtime.port object.
+ */
+RuntimePortTransport.ConnectionInfo = function RuntimePortTransportConnectionInfo
+  (port)
+{
+  // Call the base constructor.
+  Transport.ConnectionInfo .call(this);
+
+  this.port = port;
+};
+
+RuntimePortTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
+RuntimePortTransport.ConnectionInfo.prototype.name = "RuntimePortTransport.ConnectionInfo";
+
+/**
+ * Check if the fields of this RuntimePortTransport.ConnectionInfo equal the other
+ * RuntimePortTransport.ConnectionInfo.
+ * @param {RuntimePortTransport.ConnectionInfo} The other object to check.
+ * @return {boolean} True if the objects have equal fields, false if not.
+ */
+RuntimePortTransport.ConnectionInfo.prototype.equals = function(other)
+{
+  if (other == null || other.port == undefined)
+    return false;
+  return this.port == other.port;
+};
+
+RuntimePortTransport.ConnectionInfo.prototype.toString = function()
+{
+  return "{}";
+};
+
+/**
+ * Set the onReceivedObject callback, replacing any previous callback.
+ * @param {function} onReceivedObject (optional) If supplied and the received
+ * object type field is not "Buffer" then just call this.onReceivedObject(obj).
+ * If this is null, then don't call it.
+ */
+RuntimePortTransport.prototype.setOnReceivedObject = function(onReceivedObject)
+{
+  this.onReceivedObject = onReceivedObject;
+}
+
+/**
+ * Determine whether this transport connecting according to connectionInfo is to
+ * a node on the current machine. RuntimePortTransport is always local.
+ * @param {RuntimePortTransport.ConnectionInfo} connectionInfo This is ignored.
+ * @param {function} onResult This calls onResult(true) because a runtime.port
+ * is always local.
+ * @param {function} onError This is ignored.
+ */
+RuntimePortTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
+{
+  onResult(true);
+};
+
+/**
+ * Connect to the runtime.port in connectionInfo. For a received object obj, if
+ * obj.type is "Buffer", read an entire packet element from obj.data and call
+ * elementListener.onReceivedElement(element). Otherwise just call
+ * onReceivedObject(obj) using the callback given to the constructor.
+ * @param {RuntimePortTransport.ConnectionInfo} connectionInfo The
+ * ConnectionInfo with the runtime.port.
+ * @param {object} elementListener The elementListener with function
+ * onReceivedElement which must remain valid during the life of this object.
+ * @param {function} onOpenCallback Once connected, call onOpenCallback().
+ * @param {function} onClosedCallback (optional) If the connection is closed by
+ * the remote host, call onClosedCallback(). If omitted or null, don't call it.
+ */
+RuntimePortTransport.prototype.connect = function
+  (connectionInfo, elementListener, onOpenCallback, onClosedCallback)
+{
+  // The window listener is already set up.
+  this.elementReader = new ElementReader(elementListener);
+  this.connectionInfo = connectionInfo;
+  this.port = this.connectionInfo.port;
+
+  // Add a listener to wait for a message object from the tab
+  var thisTransport = this;
+  this.port.onMessage.addListener(function(obj) {
+    if (obj.type == "Buffer")
+      thisTransport.elementReader.onReceivedData
+        (Buffer.isBuffer(obj.data) ? obj.data : new Buffer(obj.data));
+    else {
+      if (thisTransport.onReceivedObject != null)
+        thisTransport.onReceivedObject(obj);
+    }
+  });
+
+  this.port.onDisconnect.addListener(function() {
+    thisTransport.port = null;
+    if (onClosedCallback != null)
+      onClosedCallback();
+  });
+
+  onOpenCallback();
+};
+
+/**
+ * Send the JavaScript object over the connection created by connect.
+ * @param {object} obj The object to send. If it is a JSON Buffer then it is
+ * processed like an NDN packet.
+ */
+RuntimePortTransport.prototype.sendObject = function(obj)
+{
+  if (this.port == null) {
+    console.log("RuntimePortTransport connection is not established.");
+    return;
+  }
+
+  this.port.postMessage(obj);
+};
+
+/**
+ * Send the buffer over the connection created by connect.
+ * @param {Buffer} buffer The bytes to send.
+ */
+RuntimePortTransport.prototype.send = function(buffer)
+{
+  this.sendObject(buffer.toJSON());
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var ElementReader = require('../encoding/element-reader.js').ElementReader; /** @ignore */
+var LOG = require('../log.js').Log.LOG; /** @ignore */
+var Transport = require('./transport.js').Transport; /** @ignore */
+var Face;
+
+/**
+ * @constructor
+ */
+var WebSocketTransport = function WebSocketTransport()
+{
+  // Call the base constructor.
+  Transport.call(this);
+
+  if (!WebSocket)
+    throw new Error("WebSocket support is not available on this platform.");
+
+  this.ws = null;
+  this.connectionInfo = null; // Read by Face.
+  this.elementReader = null;
+  this.defaultGetConnectionInfo = Face.makeShuffledHostGetConnectionInfo
+    (["A.ws.ndn.ucla.edu", "B.ws.ndn.ucla.edu", "C.ws.ndn.ucla.edu", "D.ws.ndn.ucla.edu",
+      "E.ws.ndn.ucla.edu", "F.ws.ndn.ucla.edu", "G.ws.ndn.ucla.edu", "H.ws.ndn.ucla.edu",
+      "I.ws.ndn.ucla.edu", "J.ws.ndn.ucla.edu", "K.ws.ndn.ucla.edu", "L.ws.ndn.ucla.edu",
+      "M.ws.ndn.ucla.edu", "N.ws.ndn.ucla.edu"],
+     9696,
+     function(host, port) { return new WebSocketTransport.ConnectionInfo(host, port); });
+};
+
+WebSocketTransport.prototype = new Transport();
+WebSocketTransport.prototype.name = "WebSocketTransport";
+
+WebSocketTransport.importFace = function(face){
+  Face = face;
+};
+
+exports.WebSocketTransport = WebSocketTransport;
+
+/**
+ * Create a new WebSocketTransport.ConnectionInfo which extends
+ * Transport.ConnectionInfo to hold the host and port info for the WebSocket
+ * connection.
+ * @param {string} host The host for the connection. However, if the host string
+ * begins with "ws:" or "wss:", then ignore port and use the string as the full
+ * endpoint URI.
+ * @param {number} port (optional) The port number for the connection. If
+ * omitted, use 9696.
+ */
+WebSocketTransport.ConnectionInfo = function WebSocketTransportConnectionInfo
+  (host, port)
+{
+  // Call the base constructor.
+  Transport.ConnectionInfo .call(this);
+
+  port = (port !== undefined ? port : 9696);
+
+  this.host = host;
+  this.port = port;
+};
+
+WebSocketTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
+WebSocketTransport.ConnectionInfo.prototype.name = "WebSocketTransport.ConnectionInfo";
+
+/**
+ * Check if the fields of this WebSocketTransport.ConnectionInfo equal the other
+ * WebSocketTransport.ConnectionInfo.
+ * @param {WebSocketTransport.ConnectionInfo} The other object to check.
+ * @return {boolean} True if the objects have equal fields, false if not.
+ */
+WebSocketTransport.ConnectionInfo.prototype.equals = function(other)
+{
+  if (other == null || other.host == undefined || other.port == undefined)
+    return false;
+  return this.host == other.host && this.port == other.port;
+};
+
+WebSocketTransport.ConnectionInfo.prototype.toString = function()
+{
+  if (this.hostIsUri())
+    return "{ uri: " + this.host + " }";
+  else
+    return "{ host: " + this.host + ", port: " + this.port + " }";
+};
+
+WebSocketTransport.ConnectionInfo.prototype.hostIsUri = function()
+{
+  return this.host.substr(0, 3) == "ws:" ||
+         this.host.substr(0, 4) == "wss:";
+}
+
+/**
+ * Determine whether this transport connecting according to connectionInfo is to
+ * a node on the current machine. WebSocket transports are always non-local.
+ * @param {WebSocketTransport.ConnectionInfo} connectionInfo This is ignored.
+ * @param {function} onResult This calls onResult(false) because WebSocket
+ * transports are always non-local.
+ * @param {function} onError This is ignored.
+ */
+WebSocketTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
+{
+  onResult(false);
+};
+
+/**
+ * Connect to a WebSocket according to the info in connectionInfo. Listen on
+ * the port to read an entire packet element and call
+ * elementListener.onReceivedElement(element). Note: this connect method
+ * previously took a Face object which is deprecated and renamed as the method
+ * connectByFace.
+ * @param {WebSocketTransport.ConnectionInfo} connectionInfo A
+ * WebSocketTransport.ConnectionInfo.
+ * @param {object} elementListener The elementListener with function
+ * onReceivedElement which must remain valid during the life of this object.
+ * @param {function} onopenCallback Once connected, call onopenCallback().
+ * @param {function} onclosedCallback (optional) If the connection is closed by
+ * the remote host, call onclosedCallback(). If omitted or null, don't call it.
+ */
+WebSocketTransport.prototype.connect = function
+  (connectionInfo, elementListener, onopenCallback, onclosedCallback)
+{
+  this.close();
+
+  var uri = connectionInfo.hostIsUri() ?
+    connectionInfo.host : 'ws://' + connectionInfo.host + ':' + connectionInfo.port;
+  this.ws = new WebSocket(uri);
+  if (LOG > 0) console.log('ws connection created.');
+    this.connectionInfo = connectionInfo;
+
+  this.ws.binaryType = "arraybuffer";
+
+  this.elementReader = new ElementReader(elementListener);
+  var self = this;
+  this.ws.onmessage = function(ev) {
+    var result = ev.data;
+    //console.log('RecvHandle called.');
+
+    if (result == null || result == undefined || result == "") {
+      console.log('INVALID ANSWER');
+    }
+    else if (result instanceof ArrayBuffer) {
+      // The Buffer constructor expects an instantiated array.
+      var bytearray = new Buffer(new Uint8Array(result));
+
+      if (LOG > 3) console.log('BINARY RESPONSE IS ' + bytearray.toString('hex'));
+
+      try {
+        // Find the end of the element and call onReceivedElement.
+        self.elementReader.onReceivedData(bytearray);
+      } catch (ex) {
+        console.log("NDN.ws.onmessage exception: " + ex);
+        return;
+      }
+    }
+  }
+
+  this.ws.onopen = function(ev) {
+    if (LOG > 3) console.log(ev);
+    if (LOG > 3) console.log('ws.onopen: WebSocket connection opened.');
+    if (LOG > 3) console.log('ws.onopen: ReadyState: ' + this.readyState);
+    // Face.registerPrefix will fetch the ndndid when needed.
+
+    onopenCallback();
+  }
+
+  this.ws.onerror = function(ev) {
+    console.log('ws.onerror: ReadyState: ' + this.readyState);
+    console.log(ev);
+    console.log('ws.onerror: WebSocket error: ' + ev.data);
+  }
+
+  this.ws.onclose = function(ev) {
+    console.log('ws.onclose: WebSocket connection closed.');
+    self.ws = null;
+
+    if (onclosedCallback != null)
+      onclosedCallback();
+  }
+};
+
+/**
+ * @deprecated This is deprecated. You should not call Transport.connect
+ * directly, since it is called by Face methods.
+ */
+WebSocketTransport.prototype.connectByFace = function(face, onopenCallback)
+{
+  this.connect
+    (face.connectionInfo, face, onopenCallback,
+     function() { face.closeByTransport(); });
+};
+
+/**
+ * Send the Uint8Array data.
+ */
+WebSocketTransport.prototype.send = function(data)
+{
+  if (this.ws != null) {
+    // If we directly use data.buffer to feed ws.send(),
+    // WebSocket may end up sending a packet with 10000 bytes of data.
+    // That is, WebSocket will flush the entire buffer
+    // regardless of the offset of the Uint8Array. So we have to create
+    // a new Uint8Array buffer with just the right size and copy the
+    // content from binaryInterest to the new buffer.
+    //    ---Wentao
+    var bytearray = new Uint8Array(data.length);
+    bytearray.set(data);
+    this.ws.send(bytearray.buffer);
+    if (LOG > 3) console.log('ws.send() returned.');
+  }
+  else
+    console.log('WebSocket connection is not established.');
+};
+
+/**
+ * Close the connection.
+ */
+WebSocketTransport.prototype.close = function()
+{
+  if (this.ws != null)
+    delete this.ws;
+}
+
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// The Face constructor uses TcpTransport by default which is not available in the browser, so override to WebSocketTransport.
+exports.TcpTransport = require("./transport/web-socket-transport").WebSocketTransport;
+/**
+ * This class represents a Name as an array of components where each is a byte array.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cheraoui, Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
+var LOG = require('./log.js').Log.LOG;
+var DecodingException = require('./encoding/decoding-exception.js').DecodingException;
+
+/**
+ * Create a new Name from components.
+ *
+ * @constructor
+ * @param {string|Name|Array<string|Array<number>|ArrayBuffer|Buffer|Name>} components if a string, parse it as a URI.  If a Name, add a deep copy of its components.
+ * Otherwise it is an array of components which are appended according to Name.append, so
+ * convert each and store it as an array of Buffer.  If a component is a string, encode as utf8.
+ */
+var Name = function Name(components)
+{
+  if (typeof components == 'string') {
+    if (LOG > 3) console.log('Content Name String ' + components);
+    this.components = Name.createNameArray(components);
+  }
+  else if (typeof components === 'object') {
+    this.components = [];
+    if (components instanceof Name)
+      this.append(components);
+    else {
+      for (var i = 0; i < components.length; ++i)
+        this.append(components[i]);
+    }
+  }
+  else if (components == null)
+    this.components = [];
+  else
+    if (LOG > 1) console.log("NO CONTENT NAME GIVEN");
+
+  this.changeCount = 0;
+};
+
+exports.Name = Name;
+
+/**
+ * Create a new GENERIC Name.Component with a copy of the given value.
+ * (To create an ImplicitSha256Digest component, use fromImplicitSha256Digest.)
+ * @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer} value If the value is a string, encode it as utf8 (but don't unescape).
+ * @constructor
+ */
+Name.Component = function NameComponent(value)
+{
+  if (typeof value === 'object' && value instanceof Name.Component) {
+    // The copy constructor.
+    this.value_ = value.value_;
+    this.type_ = value.type_;
+    return;
+  }
+
+  if (!value)
+    this.value_ = new Blob([]);
+  else if (typeof value === 'object' && typeof ArrayBuffer !== 'undefined' &&
+           value instanceof ArrayBuffer)
+    // Make a copy.  Turn the value into a Uint8Array since the Buffer
+    //   constructor doesn't take an ArrayBuffer.
+    this.value_ = new Blob(new Buffer(new Uint8Array(value)), false);
+  else if (typeof value === 'object' && value instanceof Blob)
+    this.value_ = value;
+  else
+    // Blob will make a copy if needed.
+    this.value_ = new Blob(value);
+
+  this.type_ = Name.Component.ComponentType.GENERIC;
+};
+
+/**
+ * A Name.Component.ComponentType specifies the recognized types of a name
+ * component.
+ */
+Name.Component.ComponentType = {
+  IMPLICIT_SHA256_DIGEST: 1,
+  GENERIC: 8
+};
+
+/**
+ * Get the component value.
+ * @return {Blob} The component value.
+ */
+Name.Component.prototype.getValue = function()
+{
+  return this.value_;
+};
+
+/**
+ * @deprecated Use getValue. This method returns a Buffer which is the former
+ * behavior of getValue, and should only be used while updating your code.
+ */
+Name.Component.prototype.getValueAsBuffer = function()
+{
+  // Assume the caller won't modify it.
+  return this.value_.buf();
+};
+
+/**
+ * @deprecated Use getValue which returns a Blob.
+ */
+Object.defineProperty(Name.Component.prototype, "value",
+  { get: function() { return this.getValueAsBuffer(); } });
+
+/**
+ * Convert this component value to a string by escaping characters according to the NDN URI Scheme.
+ * This also adds "..." to a value with zero or more ".".
+ * This adds a type code prefix as needed, such as "sha256digest=".
+ * @return {string} The escaped string.
+ */
+Name.Component.prototype.toEscapedString = function()
+{
+  if (this.type_ === Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST)
+    return "sha256digest=" + this.value_.toHex();
+  else
+    return Name.toEscapedString(this.value_.buf());
+};
+
+/**
+ * Check if this component is a segment number according to NDN naming
+ * conventions for "Segment number" (marker 0x00).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return {number}  True if this is a segment number.
+ */
+Name.Component.prototype.isSegment = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0x00 &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a segment byte offset according to NDN
+ * naming conventions for segment "Byte offset" (marker 0xFB).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return  True if this is a segment byte offset.
+ */
+Name.Component.prototype.isSegmentOffset = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFB &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a version number  according to NDN naming
+ * conventions for "Versioning" (marker 0xFD).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return {number}  True if this is a version number.
+ */
+Name.Component.prototype.isVersion = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFD &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a timestamp  according to NDN naming
+ * conventions for "Timestamp" (marker 0xFC).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return  True if this is a timestamp.
+ */
+Name.Component.prototype.isTimestamp = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFC &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a sequence number according to NDN naming
+ * conventions for "Sequencing" (marker 0xFE).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return  True if this is a sequence number.
+ */
+Name.Component.prototype.isSequenceNumber = function()
+{
+  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFE &&
+         this.isGeneric();
+};
+
+/**
+ * Check if this component is a generic component.
+ * @return {boolean} True if this is an generic component.
+ */
+Name.Component.prototype.isGeneric = function()
+{
+  return this.type_ === Name.Component.ComponentType.GENERIC;
+};
+
+/**
+ * Check if this component is an ImplicitSha256Digest component.
+ * @return {boolean} True if this is an ImplicitSha256Digest component.
+ */
+Name.Component.prototype.isImplicitSha256Digest = function()
+{
+  return this.type_ === Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST;
+};
+
+/**
+ * Interpret this name component as a network-ordered number and return an integer.
+ * @return {number} The integer number.
+ */
+Name.Component.prototype.toNumber = function()
+{
+  return DataUtils.bigEndianToUnsignedInt(this.value_.buf());
+};
+
+/**
+ * Interpret this name component as a network-ordered number with a marker and
+ * return an integer.
+ * @param {number} marker The required first byte of the component.
+ * @return {number} The integer number.
+ * @throws Error If the first byte of the component does not equal the marker.
+ */
+Name.Component.prototype.toNumberWithMarker = function(marker)
+{
+  if (this.value_.size() == 0 || this.value_.buf()[0] != marker)
+    throw new Error("Name component does not begin with the expected marker");
+
+  return DataUtils.bigEndianToUnsignedInt(this.value_.buf().slice(1));
+};
+
+/**
+ * Interpret this name component as a segment number according to NDN naming
+ * conventions for "Segment number" (marker 0x00).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return {number} The integer segment number.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toSegment = function()
+{
+  return this.toNumberWithMarker(0x00);
+};
+
+/**
+ * Interpret this name component as a segment byte offset according to NDN
+ * naming conventions for segment "Byte offset" (marker 0xFB).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return The integer segment byte offset.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toSegmentOffset = function()
+{
+  return this.toNumberWithMarker(0xFB);
+};
+
+/**
+ * Interpret this name component as a version number  according to NDN naming
+ * conventions for "Versioning" (marker 0xFD). Note that this returns
+ * the exact number from the component without converting it to a time
+ * representation.
+ * @return {number} The integer version number.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toVersion = function()
+{
+  return this.toNumberWithMarker(0xFD);
+};
+
+/**
+ * Interpret this name component as a timestamp  according to NDN naming
+ * conventions for "Timestamp" (marker 0xFC).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return The number of microseconds since the UNIX epoch (Thursday,
+ * 1 January 1970) not counting leap seconds.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toTimestamp = function()
+{
+  return this.toNumberWithMarker(0xFC);
+};
+
+/**
+ * Interpret this name component as a sequence number according to NDN naming
+ * conventions for "Sequencing" (marker 0xFE).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @return The integer sequence number.
+ * @throws Error If the first byte of the component is not the expected marker.
+ */
+Name.Component.prototype.toSequenceNumber = function()
+{
+  return this.toNumberWithMarker(0xFE);
+};
+
+/**
+ * Create a component whose value is the nonNegativeInteger encoding of the
+ * number.
+ * @param {number} number
+ * @return {Name.Component}
+ */
+Name.Component.fromNumber = function(number)
+{
+  var encoder = new TlvEncoder(8);
+  encoder.writeNonNegativeInteger(number);
+  return new Name.Component(new Blob(encoder.getOutput(), false));
+};
+
+/**
+ * Create a component whose value is the marker appended with the
+ * nonNegativeInteger encoding of the number.
+ * @param {number} number
+ * @param {number} marker
+ * @return {Name.Component}
+ */
+Name.Component.fromNumberWithMarker = function(number, marker)
+{
+  var encoder = new TlvEncoder(9);
+  // Encode backwards.
+  encoder.writeNonNegativeInteger(number);
+  encoder.writeNonNegativeInteger(marker);
+  return new Name.Component(new Blob(encoder.getOutput(), false));
+};
+
+/**
+ * Create a component with the encoded segment number according to NDN
+ * naming conventions for "Segment number" (marker 0x00).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * param {number} segment The segment number.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromSegment = function(segment)
+{
+  return Name.Component.fromNumberWithMarker(segment, 0x00);
+};
+
+/**
+ * Create a component with the encoded segment byte offset according to NDN
+ * naming conventions for segment "Byte offset" (marker 0xFB).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * param {number} segmentOffset The segment byte offset.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromSegmentOffset = function(segmentOffset)
+{
+  return Name.Component.fromNumberWithMarker(segmentOffset, 0xFB);
+};
+
+/**
+ * Create a component with the encoded version number according to NDN
+ * naming conventions for "Versioning" (marker 0xFD).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * Note that this encodes the exact value of version without converting from a
+ * time representation.
+ * param {number} version The version number.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromVersion = function(version)
+{
+  return Name.Component.fromNumberWithMarker(version, 0xFD);
+};
+
+/**
+ * Create a component with the encoded timestamp according to NDN naming
+ * conventions for "Timestamp" (marker 0xFC).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * param {number} timestamp The number of microseconds since the UNIX epoch (Thursday,
+ * 1 January 1970) not counting leap seconds.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromTimestamp = function(timestamp)
+{
+  return Name.Component.fromNumberWithMarker(timestamp, 0xFC);
+};
+
+/**
+ * Create a component with the encoded sequence number according to NDN naming
+ * conventions for "Sequencing" (marker 0xFE).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * param {number} sequenceNumber The sequence number.
+ * returns {Name.Component} The new Component.
+ */
+Name.Component.fromSequenceNumber = function(sequenceNumber)
+{
+  return Name.Component.fromNumberWithMarker(sequenceNumber, 0xFE);
+};
+
+/**
+ * Create a component of type ImplicitSha256DigestComponent, so that
+ * isImplicitSha256Digest() is true.
+ * @param {Blob|Buffer} digest The SHA-256 digest value.
+ * @return {Name.Component} The new Component.
+ * @throws DecodingException If the digest length is not 32 bytes.
+ */
+Name.Component.fromImplicitSha256Digest = function(digest)
+{
+  digestBlob = typeof digest === 'object' && digest instanceof Blob ?
+    digest : new Blob(digest, true);
+  if (digestBlob.size() !== 32)
+    throw new DecodingException
+      ("Name.Component.fromImplicitSha256Digest: The digest length must be 32 bytes");
+
+  var result = new Name.Component(digestBlob);
+  result.type_ = Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST;
+  return result;
+};
+
+/**
+ * Get the successor of this component, as described in Name.getSuccessor.
+ * @return {Name.Component} A new Name.Component which is the successor of this.
+ */
+Name.Component.prototype.getSuccessor = function()
+{
+  // Allocate an extra byte in case the result is larger.
+  var result = new Buffer(this.value_.size() + 1);
+
+  var carry = true;
+  for (var i = this.value_.size() - 1; i >= 0; --i) {
+    if (carry) {
+      result[i] = (this.value_.buf()[i] + 1) & 0xff;
+      carry = (result[i] === 0);
+    }
+    else
+      result[i] = this.value_.buf()[i];
+  }
+
+  if (carry)
+    // Assume all the bytes were set to zero (or the component was empty). In
+    // NDN ordering, carry does not mean to prepend a 1, but to make a component
+    // one byte longer of all zeros.
+    result[result.length - 1] = 0;
+  else
+    // We didn't need the extra byte.
+    result = result.slice(0, this.value_.size());
+
+  return new Name.Component(new Blob(result, false));
+};
+
+/**
+ * Check if this is the same component as other.
+ * @param {Name.Component} other The other Component to compare with.
+ * @return {Boolean} true if the components are equal, otherwise false.
+ */
+Name.Component.prototype.equals = function(other)
+{
+  return typeof other === 'object' && other instanceof Name.Component &&
+    this.value_.equals(other.value_) && this.type_ === other.type_;
+};
+
+/**
+ * Compare this to the other Component using NDN canonical ordering.
+ * @param {Name.Component} other The other Component to compare with.
+ * @return {number} 0 if they compare equal, -1 if this comes before other in
+ * the canonical ordering, or 1 if this comes after other in the canonical
+ * ordering.
+ *
+ * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
+ */
+Name.Component.prototype.compare = function(other)
+{
+  if (this.type_ < other.type_)
+    return -1;
+  if (this.type_ > other.type_)
+    return 1;
+
+  return Name.Component.compareBuffers(this.value_.buf(), other.value_.buf());
+};
+
+/**
+ * Do the work of Name.Component.compare to compare the component buffers.
+ * @param {Buffer} component1
+ * @param {Buffer} component2
+ * @return {number} 0 if they compare equal, -1 if component1 comes before
+ * component2 in the canonical ordering, or 1 if component1 comes after
+ * component2 in the canonical ordering.
+ */
+Name.Component.compareBuffers = function(component1, component2)
+{
+  if (component1.length < component2.length)
+    return -1;
+  if (component1.length > component2.length)
+    return 1;
+
+  for (var i = 0; i < component1.length; ++i) {
+    if (component1[i] < component2[i])
+      return -1;
+    if (component1[i] > component2[i])
+      return 1;
+  }
+
+  return 0;
+};
+
+/**
+ * @deprecated Use toUri.
+ */
+Name.prototype.getName = function()
+{
+  return this.toUri();
+};
+
+/** Parse uri as a URI and return an array of Buffer components.
+ */
+Name.createNameArray = function(uri)
+{
+  uri = uri.trim();
+  if (uri.length <= 0)
+    return [];
+
+  var iColon = uri.indexOf(':');
+  if (iColon >= 0) {
+    // Make sure the colon came before a '/'.
+    var iFirstSlash = uri.indexOf('/');
+    if (iFirstSlash < 0 || iColon < iFirstSlash)
+      // Omit the leading protocol such as ndn:
+      uri = uri.substr(iColon + 1, uri.length - iColon - 1).trim();
+  }
+
+  if (uri[0] == '/') {
+    if (uri.length >= 2 && uri[1] == '/') {
+      // Strip the authority following "//".
+      var iAfterAuthority = uri.indexOf('/', 2);
+      if (iAfterAuthority < 0)
+        // Unusual case: there was only an authority.
+        return [];
+      else
+        uri = uri.substr(iAfterAuthority + 1, uri.length - iAfterAuthority - 1).trim();
+    }
+    else
+      uri = uri.substr(1, uri.length - 1).trim();
+  }
+
+  var array = uri.split('/');
+
+  // Unescape the components.
+  var sha256digestPrefix = "sha256digest=";
+  for (var i = 0; i < array.length; ++i) {
+    var component;
+    if (array[i].substr(0, sha256digestPrefix.length) == sha256digestPrefix) {
+      var hexString = array[i].substr(sha256digestPrefix.length).trim();
+      component = Name.Component.fromImplicitSha256Digest
+        (new Blob(new Buffer(hexString, 'hex')), false);
+    }
+    else
+      component = new Name.Component(Name.fromEscapedString(array[i]));
+
+    if (component.getValue().isNull()) {
+      // Ignore the illegal componenent.  This also gets rid of a trailing '/'.
+      array.splice(i, 1);
+      --i;
+      continue;
+    }
+    else
+      array[i] = component;
+  }
+
+  return array;
+};
+
+/**
+ * Parse the uri according to the NDN URI Scheme and set the name with the
+ * components.
+ * @param {string} uri The URI string.
+ */
+Name.prototype.set = function(uri)
+{
+  this.components = Name.createNameArray(uri);
+  ++this.changeCount;
+};
+
+/**
+ * Convert the component to a Buffer and append a GENERIC component to this Name.
+ * Return this Name object to allow chaining calls to add.
+ * @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer|Name} component If a component is a string, encode as utf8 (but don't unescape).
+ * @return {Name}
+ */
+Name.prototype.append = function(component)
+{
+  if (typeof component == 'object' && component instanceof Name) {
+    var components;
+    if (component == this)
+      // special case, when we need to create a copy
+      components = this.components.slice(0, this.components.length);
+    else
+      components = component.components;
+
+    for (var i = 0; i < components.length; ++i)
+      this.components.push(new Name.Component(components[i]));
+  }
+  else if (typeof component === 'object' && component instanceof Name.Component)
+    // The Component is immutable, so use it as is.
+    this.components.push(component);
+  else
+    // Just use the Name.Component constructor.
+    this.components.push(new Name.Component(component));
+
+  ++this.changeCount;
+  return this;
+};
+
+/**
+ * @deprecated Use append.
+ */
+Name.prototype.add = function(component)
+{
+  return this.append(component);
+};
+
+/**
+ * Clear all the components.
+ */
+Name.prototype.clear = function()
+{
+  this.components = [];
+  ++this.changeCount;
+};
+
+/**
+ * Return the escaped name string according to NDN URI Scheme.
+ * @param {boolean} includeScheme (optional) If true, include the "ndn:" scheme
+ * in the URI, e.g. "ndn:/example/name". If false, just return the path, e.g.
+ * "/example/name". If ommitted, then just return the path which is the default
+ * case where toUri() is used for display.
+ * @return {String}
+ */
+Name.prototype.toUri = function(includeScheme)
+{
+  if (this.size() == 0)
+    return includeScheme ? "ndn:/" : "/";
+
+  var result = includeScheme ? "ndn:" : "";
+
+  for (var i = 0; i < this.size(); ++i)
+    result += "/"+ this.components[i].toEscapedString();
+
+  return result;
+};
+
+/**
+ * @deprecated Use toUri.
+ */
+Name.prototype.to_uri = function()
+{
+  return this.toUri();
+};
+
+Name.prototype.toString = function() { return this.toUri(); }
+
+/**
+ * Append a component with the encoded segment number according to NDN
+ * naming conventions for "Segment number" (marker 0x00).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @param {number} segment The segment number.
+ * @return {Name} This name so that you can chain calls to append.
+ */
+Name.prototype.appendSegment = function(segment)
+{
+  return this.append(Name.Component.fromSegment(segment));
+};
+
+/**
+ * Append a component with the encoded segment byte offset according to NDN
+ * naming conventions for segment "Byte offset" (marker 0xFB).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @param {number} segmentOffset The segment byte offset.
+ * @return {Name} This name so that you can chain calls to append.
+ */
+Name.prototype.appendSegmentOffset = function(segmentOffset)
+{
+  return this.append(Name.Component.fromSegmentOffset(segmentOffset));
+};
+
+/**
+ * Append a component with the encoded version number according to NDN
+ * naming conventions for "Versioning" (marker 0xFD).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * Note that this encodes the exact value of version without converting from a time representation.
+ * @param {number} version The version number.
+ * @return {Name} This name so that you can chain calls to append.
+ */
+Name.prototype.appendVersion = function(version)
+{
+  return this.append(Name.Component.fromVersion(version));
+};
+
+/**
+ * Append a component with the encoded timestamp according to NDN naming
+ * conventions for "Timestamp" (marker 0xFC).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @param {number} timestamp The number of microseconds since the UNIX epoch (Thursday,
+ * 1 January 1970) not counting leap seconds.
+ * @return This name so that you can chain calls to append.
+ */
+Name.prototype.appendTimestamp = function(timestamp)
+{
+  return this.append(Name.Component.fromTimestamp(timestamp));
+};
+
+/**
+ * Append a component with the encoded sequence number according to NDN naming
+ * conventions for "Sequencing" (marker 0xFE).
+ * http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ * @param {number} sequenceNumber The sequence number.
+ * @return This name so that you can chain calls to append.
+ */
+Name.prototype.appendSequenceNumber = function(sequenceNumber)
+{
+  return this.append(Name.Component.fromSequenceNumber(sequenceNumber));
+};
+
+/**
+ * Append a component of type ImplicitSha256DigestComponent, so that
+ * isImplicitSha256Digest() is true.
+ * @param {Blob|Buffer} digest The SHA-256 digest value.
+ * @return This name so that you can chain calls to append.
+ * @throws DecodingException If the digest length is not 32 bytes.
+ */
+Name.prototype.appendImplicitSha256Digest = function(digest)
+{
+  return this.append(Name.Component.fromImplicitSha256Digest(digest));
+};
+
+/**
+ * @deprecated Use appendSegment.
+ */
+Name.prototype.addSegment = function(number)
+{
+  return this.appendSegment(number);
+};
+
+/**
+ * Get a new name, constructed as a subset of components.
+ * @param {number} iStartComponent The index if the first component to get. If
+ * iStartComponent is -N then return return components starting from
+ * name.size() - N.
+ * @param {number} (optional) nComponents The number of components starting at
+ * iStartComponent. If omitted or greater than the size of this name, get until
+ * the end of the name.
+ * @return {Name} A new name.
+ */
+Name.prototype.getSubName = function(iStartComponent, nComponents)
+{
+  if (iStartComponent < 0)
+    iStartComponent = this.components.length - (-iStartComponent);
+
+  if (nComponents == undefined)
+    nComponents = this.components.length - iStartComponent;
+
+  var result = new Name();
+
+  var iEnd = iStartComponent + nComponents;
+  for (var i = iStartComponent; i < iEnd && i < this.components.length; ++i)
+    result.components.push(this.components[i]);
+
+  return result;
+};
+
+/**
+ * Return a new Name with the first nComponents components of this Name.
+ * @param {number} nComponents The number of prefix components.  If nComponents is -N then return the prefix up
+ * to name.size() - N. For example getPrefix(-1) returns the name without the final component.
+ * @return {Name} A new name.
+ */
+Name.prototype.getPrefix = function(nComponents)
+{
+  if (nComponents < 0)
+    return this.getSubName(0, this.components.length + nComponents);
+  else
+    return this.getSubName(0, nComponents);
+};
+
+/**
+ * @deprecated Use getPrefix(-nComponents).
+ */
+Name.prototype.cut = function(nComponents)
+{
+  return new Name(this.components.slice(0, this.components.length - nComponents));
+};
+
+/**
+ * Return the number of name components.
+ * @return {number}
+ */
+Name.prototype.size = function()
+{
+  return this.components.length;
+};
+
+/**
+ * Get a Name Component by index number.
+ * @param {Number} i The index of the component, starting from 0.  However, if i is negative, return the component
+ * at size() - (-i).
+ * @return {Name.Component} The name component at the index. You must not
+ * change the returned Name.Component object.
+ */
+Name.prototype.get = function(i)
+{
+  if (i >= 0) {
+    if (i >= this.components.length)
+      throw new Error("Name.get: Index is out of bounds");
+
+    return this.components[i];
+  }
+  else {
+    // Negative index.
+    if (i < -this.components.length)
+      throw new Error("Name.get: Index is out of bounds");
+
+    return this.components[this.components.length - (-i)];
+  }
+};
+
+/**
+ * @deprecated Use size().
+ */
+Name.prototype.getComponentCount = function()
+{
+  return this.components.length;
+};
+
+/**
+ * @deprecated To get just the component value array, use get(i).getValue().buf().
+ */
+Name.prototype.getComponent = function(i)
+{
+  return new Buffer(this.components[i].getValue().buf());
+};
+
+/**
+ * The "file name" in a name is the last component that isn't blank and doesn't start with one of the
+ *   special marker octets (for version, etc.).  Return the index in this.components of
+ *   the file name, or -1 if not found.
+ */
+Name.prototype.indexOfFileName = function()
+{
+  for (var i = this.size() - 1; i >= 0; --i) {
+    var component = this.components[i].getValue().buf();
+    if (component.length <= 0)
+      continue;
+
+    if (component[0] == 0 || component[0] == 0xC0 || component[0] == 0xC1 ||
+        (component[0] >= 0xF5 && component[0] <= 0xFF))
+      continue;
+
+    return i;
+  }
+
+  return -1;
+};
+
+/**
+ * Encode this Name for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+Name.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeName(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this Name.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Name.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeName(this, input.buf(), false);
+  else
+    wireFormat.decodeName(this, input, true);
+};
+
+/**
+ * Compare this to the other Name using NDN canonical ordering.  If the first
+ * components of each name are not equal, this returns -1 if the first comes
+ * before the second using the NDN canonical ordering for name components, or 1
+ * if it comes after. If they are equal, this compares the second components of
+ * each name, etc.  If both names are the same up to the size of the shorter
+ * name, this returns -1 if the first name is shorter than the second or 1 if it
+ * is longer. For example, std::sort gives: /a/b/d /a/b/cc /c /c/a /bb .  This
+ * is intuitive because all names with the prefix /a are next to each other.
+ * But it may be also be counter-intuitive because /c comes before /bb according
+ * to NDN canonical ordering since it is shorter.
+ * The first form of compare is simply compare(other). The second form is
+ * compare(iStartComponent, nComponents, other [, iOtherStartComponent] [, nOtherComponents])
+ * which is equivalent to
+ * self.getSubName(iStartComponent, nComponents).compare
+ * (other.getSubName(iOtherStartComponent, nOtherComponents)) .
+ * @param {number} iStartComponent The index if the first component of this name
+ * to get. If iStartComponent is -N then compare components starting from
+ * name.size() - N.
+ * @param {number} nComponents The number of components starting at
+ * iStartComponent. If greater than the size of this name, compare until the end
+ * of the name.
+ * @param {Name} other The other Name to compare with.
+ * @param {number} iOtherStartComponent (optional) The index if the first
+ * component of the other name to compare. If iOtherStartComponent is -N then
+ * compare components starting from other.size() - N. If omitted, compare
+ * starting from index 0.
+ * @param {number} nOtherComponents (optional) The number of components
+ * starting at iOtherStartComponent. If omitted or greater than the size of this
+ * name, compare until the end of the name.
+ * @return {number} 0 If they compare equal, -1 if self comes before other in
+ * the canonical ordering, or 1 if self comes after other in the canonical
+ * ordering.
+ * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
+ */
+Name.prototype.compare = function
+  (iStartComponent, nComponents, other, iOtherStartComponent, nOtherComponents)
+{
+  if (iStartComponent instanceof Name) {
+    // compare(other)
+    other = iStartComponent;
+    iStartComponent = 0;
+    nComponents = this.size();
+  }
+
+  if (iOtherStartComponent == undefined)
+    iOtherStartComponent = 0;
+  if (nOtherComponents == undefined)
+    nOtherComponents = other.size();
+
+  if (iStartComponent < 0)
+    iStartComponent = this.size() - (-iStartComponent);
+  if (iOtherStartComponent < 0)
+    iOtherStartComponent = other.size() - (-iOtherStartComponent);
+
+  nComponents = Math.min(nComponents, this.size() - iStartComponent);
+  nOtherComponents = Math.min(nOtherComponents, other.size() - iOtherStartComponent);
+
+  var count = Math.min(nComponents, nOtherComponents);
+  for (var i = 0; i < count; ++i) {
+    var comparison = this.components[iStartComponent + i].compare
+      (other.components[iOtherStartComponent + i]);
+    if (comparison == 0)
+      // The components at this index are equal, so check the next components.
+      continue;
+
+    // Otherwise, the result is based on the components at this index.
+    return comparison;
+  }
+
+  // The components up to min(this.size(), other.size()) are equal, so the
+  // shorter name is less.
+  if (nComponents < nOtherComponents)
+    return -1;
+  else if (nComponents > nOtherComponents)
+    return 1;
+  else
+    return 0;
+};
+
+/**
+ * Return true if this Name has the same components as name.
+ */
+Name.prototype.equals = function(name)
+{
+  if (this.components.length != name.components.length)
+    return false;
+
+  // Start from the last component because they are more likely to differ.
+  for (var i = this.components.length - 1; i >= 0; --i) {
+    if (!this.components[i].equals(name.components[i]))
+      return false;
+  }
+
+  return true;
+};
+
+/**
+ * @deprecated Use equals.
+ */
+Name.prototype.equalsName = function(name)
+{
+  return this.equals(name);
+};
+
+/**
+ * Find the last component in name that has a ContentDigest and return the digest value as Buffer,
+ *   or null if not found.  See Name.getComponentContentDigestValue.
+ */
+Name.prototype.getContentDigestValue = function()
+{
+  for (var i = this.size() - 1; i >= 0; --i) {
+    var digestValue = Name.getComponentContentDigestValue(this.components[i]);
+    if (digestValue != null)
+      return digestValue;
+  }
+
+  return null;
+};
+
+/**
+ * If component is a ContentDigest, return the digest value as a Buffer slice (don't modify!).
+ * If not a ContentDigest, return null.
+ * A ContentDigest component is Name.ContentDigestPrefix + 32 bytes + Name.ContentDigestSuffix.
+ */
+Name.getComponentContentDigestValue = function(component)
+{
+  if (typeof component == 'object' && component instanceof Name.Component)
+    component = component.getValue().buf();
+
+  var digestComponentLength = Name.ContentDigestPrefix.length + 32 + Name.ContentDigestSuffix.length;
+  // Check for the correct length and equal ContentDigestPrefix and ContentDigestSuffix.
+  if (component.length == digestComponentLength &&
+      DataUtils.arraysEqual(component.slice(0, Name.ContentDigestPrefix.length),
+                            Name.ContentDigestPrefix) &&
+      DataUtils.arraysEqual(component.slice
+         (component.length - Name.ContentDigestSuffix.length, component.length),
+                            Name.ContentDigestSuffix))
+   return component.slice(Name.ContentDigestPrefix.length, Name.ContentDigestPrefix.length + 32);
+ else
+   return null;
+};
+
+// Meta GUID "%C1.M.G%C1" + ContentDigest with a 32 byte BLOB.
+Name.ContentDigestPrefix = new Buffer([0xc1, 0x2e, 0x4d, 0x2e, 0x47, 0xc1, 0x01, 0xaa, 0x02, 0x85]);
+Name.ContentDigestSuffix = new Buffer([0x00]);
+
+
+/**
+ * Return value as an escaped string according to NDN URI Scheme.
+ * We can't use encodeURIComponent because that doesn't encode all the 
+ * characters we want to.
+ * This does not add a type code prefix such as "sha256digest=".
+ * @param {Buffer|Name.Component} value The value or Name.Component to escape.
+ * @return {string} The escaped string.
+ */
+Name.toEscapedString = function(value)
+{
+  if (typeof value == 'object' && value instanceof Name.Component)
+    value = value.getValue().buf();
+  else if (typeof value === 'object' && value instanceof Blob)
+    value = value.buf();
+
+  var result = "";
+  var gotNonDot = false;
+  for (var i = 0; i < value.length; ++i) {
+    if (value[i] != 0x2e) {
+      gotNonDot = true;
+      break;
+    }
+  }
+  if (!gotNonDot) {
+    // Special case for component of zero or more periods.  Add 3 periods.
+    result = "...";
+    for (var i = 0; i < value.length; ++i)
+      result += ".";
+  }
+  else {
+    for (var i = 0; i < value.length; ++i) {
+      var x = value[i];
+      // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
+      if (x >= 0x30 && x <= 0x39 || x >= 0x41 && x <= 0x5a ||
+          x >= 0x61 && x <= 0x7a || x == 0x2b || x == 0x2d ||
+          x == 0x2e || x == 0x5f)
+        result += String.fromCharCode(x);
+      else
+        result += "%" + (x < 16 ? "0" : "") + x.toString(16).toUpperCase();
+    }
+  }
+  return result;
+};
+
+/**
+ * Make a blob value by decoding the escapedString according to NDN URI Scheme.
+ * If escapedString is "", "." or ".." then return null, which means to skip the 
+ * component in the name.
+ * This does not check for a type code prefix such as "sha256digest=".
+ * @param {string} escapedString The escaped string to decode.
+ * @return {Blob} The unescaped Blob value. If the escapedString is not a valid
+ * escaped component, then the Blob isNull().
+ */
+Name.fromEscapedString = function(escapedString)
+{
+  var value = unescape(escapedString.trim());
+
+  if (value.match(/[^.]/) == null) {
+    // Special case for value of only periods.
+    if (value.length <= 2)
+      // Zero, one or two periods is illegal.  Ignore this componenent to be
+      //   consistent with the C implementation.
+      return new Blob();
+    else
+      // Remove 3 periods.
+      return new Blob
+        (DataUtils.toNumbersFromString(value.substr(3, value.length - 3)), false);
+  }
+  else
+    return new Blob(DataUtils.toNumbersFromString(value), false);
+};
+
+/**
+ * @deprecated Use fromEscapedString. This method returns a Buffer which is the former
+ * behavior of fromEscapedString, and should only be used while updating your code.
+ */
+Name.fromEscapedStringAsBuffer = function(escapedString)
+{
+  return Name.fromEscapedString(escapedString).buf();
+};
+
+/**
+ * Get the successor of this name which is defined as follows.
+ *
+ *     N represents the set of NDN Names, and X,Y ∈ N.
+ *     Operator < is defined by the NDN canonical order on N.
+ *     Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
+ *
+ * In plain words, the successor of a name is the same name, but with its last
+ * component advanced to a next possible value.
+ *
+ * Examples:
+ *
+ * - The successor of / is /%00
+ * - The successor of /%00%01/%01%02 is /%00%01/%01%03
+ * - The successor of /%00%01/%01%FF is /%00%01/%02%00
+ * - The successor of /%00%01/%FF%FF is /%00%01/%00%00%00
+ *
+ * @return {Name} A new name which is the successor of this.
+ */
+Name.prototype.getSuccessor = function()
+{
+  if (this.size() == 0) {
+    // Return "/%00".
+    var result = new Name();
+    result.append(new Blob(new Buffer([0]), false));
+    return result;
+  }
+  else
+    return this.getPrefix(-1).append(this.get(-1).getSuccessor());
+};
+
+/**
+ * Return true if the N components of this name are the same as the first N
+ * components of the given name.
+ * @param {Name} name The name to check.
+ * @return {Boolean} true if this matches the given name. This always returns
+ * true if this name is empty.
+ */
+Name.prototype.match = function(name)
+{
+  var i_name = this.components;
+  var o_name = name.components;
+
+  // This name is longer than the name we are checking it against.
+  if (i_name.length > o_name.length)
+    return false;
+
+  // Check if at least one of given components doesn't match. Check from last to
+  // first since the last components are more likely to differ.
+  for (var i = i_name.length - 1; i >= 0; --i) {
+    if (!i_name[i].equals(o_name[i]))
+      return false;
+  }
+
+  return true;
+};
+
+/**
+ * Return true if the N components of this name are the same as the first N
+ * components of the given name.
+ * @param {Name} name The name to check.
+ * @return {Boolean} true if this matches the given name. This always returns
+ * true if this name is empty.
+ */
+Name.prototype.isPrefixOf = function(name) { return this.match(name); }
+
+/**
+ * Get the change count, which is incremented each time this object is changed.
+ * @return {number} The change count.
+ */
+Name.prototype.getChangeCount = function()
+{
+  return this.changeCount;
+};
+
+// Put these requires at the bottom to avoid circular references.
+var TlvEncoder = require('./encoding/tlv/tlv-encoder.js').TlvEncoder;
+var WireFormat = require('./encoding/wire-format.js').WireFormat;
+/**
+ * This class represents an NDN KeyLocator object.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var Name = require('./name.js').Name;
+
+/**
+ * KeyLocator
+ */
+var KeyLocatorType = {
+  KEYNAME: 1,
+  KEY_LOCATOR_DIGEST: 2
+};
+
+exports.KeyLocatorType = KeyLocatorType;
+
+/**
+ * @constructor
+ */
+var KeyLocator = function KeyLocator(input, type)
+{
+  if (typeof input === 'object' && input instanceof KeyLocator) {
+    // Copy from the input KeyLocator.
+    this.type_ = input.type_;
+    this.keyName_ = new ChangeCounter(new Name(input.getKeyName()));
+    this.keyData_ = input.keyData_;
+  }
+  else {
+    this.type_ = type;
+    this.keyName_ = new ChangeCounter(new Name());
+    this.keyData_ = new Blob();
+
+    if (type == KeyLocatorType.KEYNAME)
+      this.keyName_.set(typeof input === 'object' && input instanceof Name ?
+        new Name(input) : new Name());
+    else if (type == KeyLocatorType.KEY_LOCATOR_DIGEST)
+      this.keyData_ = new Blob(input);
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.KeyLocator = KeyLocator;
+
+/**
+ * Get the key locator type. If KeyLocatorType.KEYNAME, you may also
+ * getKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also
+ * getKeyData() to get the digest.
+ * @return {number} The key locator type as a KeyLocatorType enum value,
+ * or null if not specified.
+ */
+KeyLocator.prototype.getType = function() { return this.type_; };
+
+/**
+ * Get the key name.  This is meaningful if getType() is KeyLocatorType.KEYNAME.
+ * @return {Name} The key name. If not specified, the Name is empty.
+ */
+KeyLocator.prototype.getKeyName = function()
+{
+  return this.keyName_.get();
+};
+
+/**
+ * Get the key data. If getType() is KeyLocatorType.KEY_LOCATOR_DIGEST, this is
+ * the digest bytes.
+ * @return {Blob} The key data, or an isNull Blob if not specified.
+ */
+KeyLocator.prototype.getKeyData = function()
+{
+  return this.keyData_;
+};
+
+/**
+ * @deprecated Use getKeyData. This method returns a Buffer which is the former
+ * behavior of getKeyData, and should only be used while updating your code.
+ */
+KeyLocator.prototype.getKeyDataAsBuffer = function()
+{
+  return this.getKeyData().buf();
+};
+
+/**
+ * Set the key locator type.  If KeyLocatorType.KEYNAME, you must also
+ * setKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also
+ * setKeyData() to the digest.
+ * @param {number} type The key locator type as a KeyLocatorType enum value.  If
+ * null, the type is unspecified.
+ */
+KeyLocator.prototype.setType = function(type)
+{
+  this.type_ = type;
+  ++this.changeCount_;
+};
+
+/**
+ * Set key name to a copy of the given Name.  This is the name if getType()
+ * is KeyLocatorType.KEYNAME.
+ * @param {Name} name The key name which is copied.
+ */
+KeyLocator.prototype.setKeyName = function(name)
+{
+  this.keyName_.set(typeof name === 'object' && name instanceof Name ?
+    new Name(name) : new Name());
+  ++this.changeCount_;
+};
+
+/**
+ * Set the key data to the given value. This is the digest bytes if getType() is
+ * KeyLocatorType.KEY_LOCATOR_DIGEST.
+ * @param {Blob} keyData A Blob with the key data bytes.
+ */
+KeyLocator.prototype.setKeyData = function(keyData)
+{
+  this.keyData_ = typeof keyData === 'object' && keyData instanceof Blob ?
+    keyData : new Blob(keyData);
+  ++this.changeCount_;
+};
+
+/**
+ * Clear the keyData and set the type to not specified.
+ */
+KeyLocator.prototype.clear = function()
+{
+  this.type_ = null;
+  this.keyName_.set(new Name());
+  this.keyData_ = new Blob();
+  ++this.changeCount_;
+};
+
+/**
+ * Check if this key locator has the same values as the given key locator.
+ * @param {KeyLocator} other The other key locator to check.
+ * @return {boolean} true if the key locators are equal, otherwise false.
+ */
+KeyLocator.prototype.equals = function(other)
+{
+    if (this.type_ != other.type_)
+      return false;
+
+    if (this.type_ == KeyLocatorType.KEYNAME) {
+      if (!this.getKeyName().equals(other.getKeyName()))
+        return false;
+    }
+    else if (this.type_ == KeyLocatorType.KEY_LOCATOR_DIGEST) {
+      if (!this.getKeyData().equals(other.getKeyData()))
         return false;
     }
 
     return true;
 };
 
-NDN.supported = NDN.getSupported();
-
-NDN.ndndIdFetcher = new Name('/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY');
-
-NDN.prototype.createRoute = function(host, port) {
-	this.host=host;
-	this.port=port;
-};
-
-
-NDN.KeyStore = new Array();
-
-var KeyStoreEntry = function KeyStoreEntry(name, rsa, time) {
-	this.keyName = name;  // KeyName
-	this.rsaKey = rsa;    // RSA key
-	this.timeStamp = time;  // Time Stamp
-};
-
-NDN.addKeyEntry = function(/* KeyStoreEntry */ keyEntry) {
-	var result = NDN.getKeyByName(keyEntry.keyName);
-	if (result == null)
-		NDN.KeyStore.push(keyEntry);
-	else
-		result = keyEntry;
-};
-
-NDN.getKeyByName = function(/* KeyName */ name) {
-	var result = null;
-
-	for (var i = 0; i < NDN.KeyStore.length; i++) {
-		if (NDN.KeyStore[i].keyName.contentName.match(name.contentName)) {
-            if (result == null ||
-                NDN.KeyStore[i].keyName.contentName.components.length > result.keyName.contentName.components.length)
-                result = NDN.KeyStore[i];
-        }
-	}
-
-	return result;
-};
-
-// For fetching data
-NDN.PITTable = new Array();
-
-var PITEntry = function PITEntry(interest, closure) {
-	this.interest = interest;  // Interest
-	this.closure = closure;    // Closure
-	this.timerID = -1;  // Timer ID
-};
-
-/*
- * Return the entry from NDN.PITTable where the name conforms to the interest selectors, and
- * the interest name is the longest that matches name.
+/**
+ * If the signature is a type that has a KeyLocator (so that,
+ * getFromSignature will succeed), return true.
+ * Note: This is a static method of KeyLocator instead of a method of
+ * Signature so that the Signature base class does not need to be overloaded
+ * with all the different kinds of information that various signature
+ * algorithms may use.
+ * @param {Signature} signature An object of a subclass of Signature.
+ * @return {boolean} True if the signature is a type that has a KeyLocator,
+ * otherwise false.
  */
-NDN.getEntryForExpressedInterest = function(/*Name*/ name) {
-    var result = null;
-
-	for (var i = 0; i < NDN.PITTable.length; i++) {
-		if (NDN.PITTable[i].interest.matches_name(name)) {
-            if (result == null ||
-                NDN.PITTable[i].interest.name.components.length > result.interest.name.components.length)
-                result = NDN.PITTable[i];
-        }
-	}
-
-	return result;
-};
-
-// For publishing data
-NDN.CSTable = new Array();
-
-var CSEntry = function CSEntry(name, closure) {
-	this.name = name;        // String
-	this.closure = closure;  // Closure
-};
-
-function getEntryForRegisteredPrefix(name) {
-	for (var i = 0; i < NDN.CSTable.length; i++) {
-		if (NDN.CSTable[i].name.match(name) != null)
-			return NDN.CSTable[i];
-	}
-	return null;
+KeyLocator.canGetFromSignature = function(signature)
+{
+  return signature instanceof Sha256WithRsaSignature ||
+         signature instanceof Sha256WithEcdsaSignature ||
+         signature instanceof HmacWithSha256Signature;
 }
 
-/*
- * Return a function that selects a host at random from hostList and returns { host: host, port: port }.
- * If no more hosts remain, return null.
+/**
+ * If the signature is a type that has a KeyLocator, then return it. Otherwise
+ * throw an error.
+ * @param {Signature} signature An object of a subclass of Signature.
+ * @return {KeyLocator} The signature's KeyLocator. It is an error if signature
+ * doesn't have a KeyLocator.
  */
-NDN.makeShuffledGetHostAndPort = function(hostList, port) {
-    // Make a copy.
-    hostList = hostList.slice(0, hostList.length);
-    DataUtils.shuffle(hostList);
+KeyLocator.getFromSignature = function(signature)
+{
+  if (signature instanceof Sha256WithRsaSignature ||
+      signature instanceof Sha256WithEcdsaSignature ||
+      signature instanceof HmacWithSha256Signature)
+    return signature.getKeyLocator();
+  else
+    throw new Error
+      ("KeyLocator.getFromSignature: Signature type does not have a KeyLocator");
+}
 
-    return function() {
-        if (hostList.length == 0)
-            return null;
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+KeyLocator.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.keyName_.checkChanged();
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
 
-        return { host: hostList.splice(0, 1)[0], port: port };
-    };
+  return this.changeCount_;
 };
 
-/** Encode name as an Interest. If template is not null, use its attributes.
- *  Send the interest to host:port, read the entire response and call
- *  closure.upcall(Closure.UPCALL_CONTENT (or Closure.UPCALL_CONTENT_UNVERIFIED),
- *                 new UpcallInfo(this, interest, 0, contentObject)).
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(KeyLocator.prototype, "type",
+  { get: function() { return this.getType(); },
+    set: function(val) { this.setType(val); } });
+/**
+ * @@deprecated Use getKeyData and setKeyData.
  */
-NDN.prototype.expressInterest = function(
-        // Name
-        name,
-        // Closure
-        closure,
-        // Interest
-        template) {
-	var interest = new Interest(name);
-    if (template != null) {
-		interest.minSuffixComponents = template.minSuffixComponents;
-		interest.maxSuffixComponents = template.maxSuffixComponents;
-		interest.publisherPublicKeyDigest = template.publisherPublicKeyDigest;
-		interest.exclude = template.exclude;
-		interest.childSelector = template.childSelector;
-		interest.answerOriginKind = template.answerOriginKind;
-		interest.scope = template.scope;
-		interest.interestLifetime = template.interestLifetime;
+Object.defineProperty(KeyLocator.prototype, "keyData",
+  { get: function() { return this.getKeyDataAsBuffer(); },
+    set: function(val) { this.setKeyData(val); } });
+
+// Put this last to avoid a require loop.
+var Sha256WithRsaSignature = require('./sha256-with-rsa-signature.js').Sha256WithRsaSignature;
+var Sha256WithEcdsaSignature = require('./sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature;
+var HmacWithSha256Signature = require('./hmac-with-sha256-signature.js').HmacWithSha256Signature;
+/**
+ * This class represents an NDN Data MetaInfo object.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('./name.js').Name;
+
+/**
+ * A ContentType specifies the content type in a MetaInfo object. If the
+ * content type in the packet is not a recognized enum value, then we use
+ * ContentType.OTHER_CODE and you can call MetaInfo.getOtherTypeCode(). We do
+ * this to keep the recognized content type values independent of packet
+ * encoding formats.
+ */
+var ContentType = {
+  BLOB:0,
+  LINK:1,
+  KEY: 2,
+  NACK:3,
+  OTHER_CODE: 0x7fff
+};
+
+exports.ContentType = ContentType;
+
+/**
+ * Create a new MetaInfo with the optional values.
+ * @constructor
+ */
+var MetaInfo = function MetaInfo(publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockId)
+{
+  if (timestamp)
+    throw new Error
+      ("MetaInfo constructor: timestamp support has been removed.");
+  if (locator)
+    throw new Error
+      ("MetaInfo constructor: locator support has been removed.");
+
+  if (typeof publisherOrMetaInfo === 'object' &&
+      publisherOrMetaInfo instanceof MetaInfo) {
+    // Copy values.
+    var metaInfo = publisherOrMetaInfo;
+    this.publisher_ = metaInfo.publisher_;
+    this.type_ = metaInfo.type_;
+    this.otherTypeCode_ = metaInfo.otherTypeCode_;
+    this.freshnessPeriod_ = metaInfo.freshnessPeriod_;
+    this.finalBlockId_ = metaInfo.finalBlockId_;
+  }
+  else {
+    if (publisherOrMetaInfo)
+      throw new Error
+        ("MetaInfo constructor: publisher support has been removed.");
+
+    this.type = type == null || type < 0 ? ContentType.BLOB : type;
+    this.otherTypeCode_ = -1;
+    this.freshnessSeconds = freshnessSeconds; // deprecated
+    this.finalBlockID = finalBlockId; // byte array // deprecated
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.MetaInfo = MetaInfo;
+
+/**
+ * Get the content type.
+ * @return {number} The content type as an int from ContentType. If this is
+ * ContentType.OTHER_CODE, then call getOtherTypeCode() to get the unrecognized
+ * content type code.
+ */
+MetaInfo.prototype.getType = function()
+{
+  return this.type_;
+};
+
+/**
+ * Get the content type code from the packet which is other than a recognized
+ * ContentType enum value. This is only meaningful if getType() is
+ * ContentType.OTHER_CODE.
+ * @return {number} The type code.
+ */
+MetaInfo.prototype.getOtherTypeCode = function()
+{
+  return this.otherTypeCode_;
+};
+
+/**
+ * Get the freshness period.
+ * @return {number} The freshness period in milliseconds, or null if not
+ * specified.
+ */
+MetaInfo.prototype.getFreshnessPeriod = function()
+{
+  return this.freshnessPeriod_;
+};
+
+/**
+ * Get the final block ID.
+ * @return {Name.Component} The final block ID as a Name.Component. If the
+ * Name.Component getValue().size() is 0, then the final block ID is not specified.
+ */
+MetaInfo.prototype.getFinalBlockId = function()
+{
+  return this.finalBlockId_;
+};
+
+/**
+ * @deprecated Use getFinalBlockId.
+ */
+MetaInfo.prototype.getFinalBlockID = function()
+{
+  return this.getFinalBlockId();
+};
+
+/**
+ * @deprecated Use getFinalBlockId. This method returns a Buffer which is the former
+ * behavior of getFinalBlockId, and should only be used while updating your code.
+ */
+MetaInfo.prototype.getFinalBlockIDAsBuffer = function()
+{
+  return this.finalBlockId_.getValue().buf();
+};
+
+/**
+ * Set the content type.
+ * @param {number} type The content type as an int from ContentType. If null,
+ * this uses ContentType.BLOB. If the packet's content type is not a recognized
+ * ContentType enum value, use ContentType.OTHER_CODE and call setOtherTypeCode().
+ */
+MetaInfo.prototype.setType = function(type)
+{
+  this.type_ = type == null || type < 0 ? ContentType.BLOB : type;
+  ++this.changeCount_;
+};
+
+/**
+ * Set the packet’s content type code to use when the content type enum is
+ * ContentType.OTHER_CODE. If the packet’s content type code is a recognized
+ * enum value, just call setType().
+ * @param {number} otherTypeCode The packet’s unrecognized content type code,
+ * which must be non-negative.
+ */
+MetaInfo.prototype.setOtherTypeCode = function(otherTypeCode)
+{
+  if (otherTypeCode < 0)
+    throw new Error("MetaInfo other type code must be non-negative");
+
+  this.otherTypeCode_ = otherTypeCode;
+  ++this.changeCount_;
+};
+
+/**
+ * Set the freshness period.
+ * @param {number} freshnessPeriod The freshness period in milliseconds, or null
+ * for not specified.
+ */
+MetaInfo.prototype.setFreshnessPeriod = function(freshnessPeriod)
+{
+  if (freshnessPeriod == null || freshnessPeriod < 0)
+    this.freshnessPeriod_ = null;
+  else
+    this.freshnessPeriod_ = freshnessPeriod;
+  ++this.changeCount_;
+};
+
+/**
+ * Set the final block ID.
+ * @param {Name.Component} finalBlockId The final block ID as a Name.Component.
+ * If not specified, set to a new default Name.Component(), or to a
+ * Name.Component where getValue().size() is 0.
+ */
+MetaInfo.prototype.setFinalBlockId = function(finalBlockId)
+{
+  this.finalBlockId_ = typeof finalBlockId === 'object' &&
+                       finalBlockId instanceof Name.Component ?
+    finalBlockId : new Name.Component(finalBlockId);
+  ++this.changeCount_;
+};
+
+/**
+ * @deprecated Use setFinalBlockId.
+ */
+MetaInfo.prototype.setFinalBlockID = function(finalBlockId)
+{
+  this.setFinalBlockId(finalBlockId);
+};
+
+/**
+ * Get the change count, which is incremented each time this object is changed.
+ * @return {number} The change count.
+ */
+MetaInfo.prototype.getChangeCount = function()
+{
+  return this.changeCount_;
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(MetaInfo.prototype, "type",
+  { get: function() { return this.getType(); },
+    set: function(val) { this.setType(val); } });
+/**
+ * @deprecated Use getFreshnessPeriod and setFreshnessPeriod.
+ */
+Object.defineProperty(MetaInfo.prototype, "freshnessSeconds",
+  { get: function() {
+      if (this.freshnessPeriod_ == null || this.freshnessPeriod_ < 0)
+        return null;
+      else
+        // Convert from milliseconds.
+        return this.freshnessPeriod_ / 1000.0;
+    },
+    set: function(val) {
+      if (val == null || val < 0)
+        this.freshnessPeriod_ = null;
+      else
+        // Convert to milliseconds.
+        this.freshnessPeriod_ = val * 1000.0;
+      ++this.changeCount_;
+    } });
+/**
+ * @deprecated Use getFinalBlockId and setFinalBlockId.
+ */
+Object.defineProperty(MetaInfo.prototype, "finalBlockID",
+  { get: function() { return this.getFinalBlockIDAsBuffer(); },
+    set: function(val) { this.setFinalBlockId(val); } });
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var KeyLocator = require('./key-locator.js').KeyLocator;
+
+/**
+ * Create a new Sha256WithEcdsaSignature object, possibly copying values from
+ * another object.
+ *
+ * @param {Sha256WithEcdsaSignature} value (optional) If value is a
+ * Sha256WithEcdsaSignature, copy its values.  If value is omitted, the 
+ * keyLocator is the default with unspecified values and the signature is
+ * unspecified.
+ * @constructor
+ */
+var Sha256WithEcdsaSignature = function Sha256WithEcdsaSignature(value)
+{
+  if (typeof value === 'object' && value instanceof Sha256WithEcdsaSignature) {
+    // Copy the values.
+    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
+    this.signature_ = value.signature_;
+  }
+  else {
+    this.keyLocator_ = new ChangeCounter(new KeyLocator());
+    this.signature_ = new Blob();
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.Sha256WithEcdsaSignature = Sha256WithEcdsaSignature;
+
+/**
+ * Create a new Sha256WithEcdsaSignature which is a copy of this object.
+ * @return {Sha256WithEcdsaSignature} A new object which is a copy of this
+ * object.
+ */
+Sha256WithEcdsaSignature.prototype.clone = function()
+{
+  return new Sha256WithEcdsaSignature(this);
+};
+
+/**
+ * Get the key locator.
+ * @return {KeyLocator} The key locator.
+ */
+Sha256WithEcdsaSignature.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_.get();
+};
+
+/**
+ * Get the data packet's signature bytes.
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+Sha256WithEcdsaSignature.prototype.getSignature = function()
+{
+  return this.signature_;
+};
+
+/**
+ * Set the key locator to a copy of the given keyLocator.
+ * @param {KeyLocator} keyLocator The KeyLocator to copy.
+ */
+Sha256WithEcdsaSignature.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_.set(typeof keyLocator === 'object' &&
+                       keyLocator instanceof KeyLocator ?
+    new KeyLocator(keyLocator) : new KeyLocator());
+  ++this.changeCount_;
+};
+
+/**
+ * Set the data packet's signature bytes.
+ * @param {Blob} signature
+ */
+Sha256WithEcdsaSignature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+Sha256WithEcdsaSignature.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.keyLocator_.checkChanged();
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var KeyLocator = require('./key-locator.js').KeyLocator;
+
+/**
+ * Create a new Sha256WithRsaSignature object, possibly copying values from
+ * another object.
+ *
+ * @param {Sha256WithRsaSignature} value (optional) If value is a
+ * Sha256WithRsaSignature, copy its values.  If value is omitted, the keyLocator
+ * is the default with unspecified values and the signature is unspecified.
+ * @constructor
+ */
+var Sha256WithRsaSignature = function Sha256WithRsaSignature(value)
+{
+  if (typeof value === 'object' && value instanceof Sha256WithRsaSignature) {
+    // Copy the values.
+    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
+    this.signature_ = value.signature_;
+  }
+  else {
+    this.keyLocator_ = new ChangeCounter(new KeyLocator());
+    this.signature_ = new Blob();
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.Sha256WithRsaSignature = Sha256WithRsaSignature;
+
+/**
+ * Create a new Sha256WithRsaSignature which is a copy of this object.
+ * @return {Sha256WithRsaSignature} A new object which is a copy of this object.
+ */
+Sha256WithRsaSignature.prototype.clone = function()
+{
+  return new Sha256WithRsaSignature(this);
+};
+
+/**
+ * Get the key locator.
+ * @return {KeyLocator} The key locator.
+ */
+Sha256WithRsaSignature.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_.get();
+};
+
+/**
+ * Get the data packet's signature bytes.
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+Sha256WithRsaSignature.prototype.getSignature = function()
+{
+  return this.signature_;
+};
+
+/**
+ * @deprecated Use getSignature. This method returns a Buffer which is the former
+ * behavior of getSignature, and should only be used while updating your code.
+ */
+Sha256WithRsaSignature.prototype.getSignatureAsBuffer = function()
+{
+  return this.signature_.buf();
+};
+
+/**
+ * Set the key locator to a copy of the given keyLocator.
+ * @param {KeyLocator} keyLocator The KeyLocator to copy.
+ */
+Sha256WithRsaSignature.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_.set(typeof keyLocator === 'object' &&
+                       keyLocator instanceof KeyLocator ?
+    new KeyLocator(keyLocator) : new KeyLocator());
+  ++this.changeCount_;
+};
+
+/**
+ * Set the data packet's signature bytes.
+ * @param {Blob} signature
+ */
+Sha256WithRsaSignature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+Sha256WithRsaSignature.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.keyLocator_.checkChanged();
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(Sha256WithRsaSignature.prototype, "keyLocator",
+  { get: function() { return this.getKeyLocator(); },
+    set: function(val) { this.setKeyLocator(val); } });
+/**
+ * @@deprecated Use getSignature and setSignature.
+ */
+Object.defineProperty(Sha256WithRsaSignature.prototype, "signature",
+  { get: function() { return this.getSignatureAsBuffer(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * A GenericSignature extends Signature and holds the encoding bytes of the
+ * SignatureInfo so that the application can process experimental signature
+ * types. When decoding a packet, if the type of SignatureInfo is not
+ * recognized, the library creates a GenericSignature.
+ * Create a new GenericSignature object, possibly copying values from another
+ * object.
+ *
+ * @param {GenericSignature} value (optional) If value is a GenericSignature,
+ * copy its values.
+ * @constructor
+ */
+var GenericSignature = function GenericSignature(value)
+{
+  if (typeof value === 'object' && value instanceof GenericSignature) {
+    // Copy the values.
+    this.signature_ = value.signature_;
+    this.signatureInfoEncoding_ = value.signatureInfoEncoding_;
+    this.typeCode_ = value.typeCode_;
+  }
+  else {
+    this.signature_ = new Blob();
+    this.signatureInfoEncoding_ = new Blob();
+    this.typeCode_ = null;
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.GenericSignature = GenericSignature;
+
+/**
+ * Create a new GenericSignature which is a copy of this object.
+ * @return {GenericSignature} A new object which is a copy of this object.
+ */
+GenericSignature.prototype.clone = function()
+{
+  return new GenericSignature(this);
+};
+
+/**
+ * Get the data packet's signature bytes.
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+GenericSignature.prototype.getSignature = function()
+{ 
+  return this.signature_;
+};
+
+/**
+ * @deprecated Use getSignature. This method returns a Buffer which is the former
+ * behavior of getSignature, and should only be used while updating your code.
+ */
+GenericSignature.prototype.getSignatureAsBuffer = function()
+{
+  return this.signature_.buf();
+};
+
+/**
+ * Get the bytes of the entire signature info encoding (including the type
+ * code).
+ * @return {Blob} The encoding bytes. If not specified, the value isNull().
+ */
+GenericSignature.prototype.getSignatureInfoEncoding = function()
+{
+  return this.signatureInfoEncoding_;
+};
+
+/**
+ * Get the type code of the signature type. When wire decode calls
+ * setSignatureInfoEncoding, it sets the type code. Note that the type code
+ * is ignored during wire encode, which simply uses getSignatureInfoEncoding()
+ * where the encoding already has the type code.
+ * @return {number} The type code, or null if not known.
+ */
+GenericSignature.prototype.getTypeCode = function() { return this.typeCode_; };
+
+/**
+ * Set the data packet's signature bytes.
+ * @param {Blob} signature
+ */
+GenericSignature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Set the bytes of the entire signature info encoding (including the type
+ * code).
+ * @param {Blob} signatureInfoEncoding A Blob with the encoding bytes.
+ * @param {number} (optional) The type code of the signature type, or null if
+ * not known. (When a GenericSignature is created by wire decoding, it sets
+ * the typeCode.)
+ */
+GenericSignature.prototype.setSignatureInfoEncoding = function
+  (signatureInfoEncoding, typeCode)
+{
+  this.signatureInfoEncoding_ =
+    typeof signatureInfoEncoding === 'object' && signatureInfoEncoding instanceof Blob ?
+      signatureInfoEncoding : new Blob(signatureInfoEncoding);
+  this.typeCode_ = typeCode;
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+GenericSignature.prototype.getChangeCount = function()
+{
+  return this.changeCount_;
+};
+
+/**
+ * @@deprecated Use getSignature and setSignature.
+ */
+Object.defineProperty(GenericSignature.prototype, "signature",
+  { get: function() { return this.getSignatureAsBuffer(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var KeyLocator = require('./key-locator.js').KeyLocator;
+
+/**
+ * An HmacWithSha256Signature holds the signature bits and other info
+ * representing an HmacWithSha256 signature in a packet.
+ * Create a new HmacWithSha256Signature object, possibly copying values from
+ * another object.
+ *
+ * @param {HmacWithSha256Signature} value (optional) If value is a
+ * HmacWithSha256Signature, copy its values.  If value is omitted, the keyLocator
+ * is the default with unspecified values and the signature is unspecified.
+ * @constructor
+ */
+var HmacWithSha256Signature = function HmacWithSha256Signature(value)
+{
+  if (typeof value === 'object' && value instanceof HmacWithSha256Signature) {
+    // Copy the values.
+    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
+    this.signature_ = value.signature_;
+  }
+  else {
+    this.keyLocator_ = new ChangeCounter(new KeyLocator());
+    this.signature_ = new Blob();
+  }
+
+  this.changeCount_ = 0;
+};
+
+exports.HmacWithSha256Signature = HmacWithSha256Signature;
+
+/**
+ * Create a new HmacWithSha256Signature which is a copy of this object.
+ * @return {HmacWithSha256Signature} A new object which is a copy of this object.
+ */
+HmacWithSha256Signature.prototype.clone = function()
+{
+  return new HmacWithSha256Signature(this);
+};
+
+/**
+ * Get the key locator.
+ * @return {KeyLocator} The key locator.
+ */
+HmacWithSha256Signature.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_.get();
+};
+
+/**
+ * Get the data packet's signature bytes.
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+HmacWithSha256Signature.prototype.getSignature = function()
+{
+  return this.signature_;
+};
+
+/**
+ * @deprecated Use getSignature. This method returns a Buffer which is the former
+ * behavior of getSignature, and should only be used while updating your code.
+ */
+HmacWithSha256Signature.prototype.getSignatureAsBuffer = function()
+{
+  return this.signature_.buf();
+};
+
+/**
+ * Set the key locator to a copy of the given keyLocator.
+ * @param {KeyLocator} keyLocator The KeyLocator to copy.
+ */
+HmacWithSha256Signature.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_.set(typeof keyLocator === 'object' &&
+                       keyLocator instanceof KeyLocator ?
+    new KeyLocator(keyLocator) : new KeyLocator());
+  ++this.changeCount_;
+};
+
+/**
+ * Set the data packet's signature bytes.
+ * @param {Blob} signature
+ */
+HmacWithSha256Signature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+HmacWithSha256Signature.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.keyLocator_.checkChanged();
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(HmacWithSha256Signature.prototype, "keyLocator",
+  { get: function() { return this.getKeyLocator(); },
+    set: function(val) { this.setKeyLocator(val); } });
+/**
+ * @@deprecated Use getSignature and setSignature.
+ */
+Object.defineProperty(HmacWithSha256Signature.prototype, "signature",
+  { get: function() { return this.getSignatureAsBuffer(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * This class represents an NDN Data Signature object.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * A DigestSha256Signature extends Signature and holds the signature bits (which
+ * are only the SHA256 digest) and an empty SignatureInfo for a data packet or
+ * signed interest.
+ *
+ * Create a new DigestSha256Signature object, possibly copying values from
+ * another object.
+ *
+ * @param {DigestSha256Signature} value (optional) If value is a
+ * DigestSha256Signature, copy its values.  If value is omitted, the signature
+ * is unspecified.
+ * @constructor
+ */
+var DigestSha256Signature = function DigestSha256Signature(value)
+{
+  if (typeof value === 'object' && value instanceof DigestSha256Signature)
+    // Copy the values.
+    this.signature_ = value.signature_;
+  else
+    this.signature_ = new Blob();
+
+  this.changeCount_ = 0;
+};
+
+exports.DigestSha256Signature = DigestSha256Signature;
+
+/**
+ * Create a new DigestSha256Signature which is a copy of this object.
+ * @return {DigestSha256Signature} A new object which is a copy of this object.
+ */
+DigestSha256Signature.prototype.clone = function()
+{
+  return new DigestSha256Signature(this);
+};
+
+/**
+ * Get the signature bytes (which are only the digest).
+ * @return {Blob} The signature bytes. If not specified, the value isNull().
+ */
+DigestSha256Signature.prototype.getSignature = function()
+{
+  return this.signature_;
+};
+
+/**
+ * Set the signature bytes to the given value.
+ * @param {Blob} signature
+ */
+DigestSha256Signature.prototype.setSignature = function(signature)
+{
+  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
+    signature : new Blob(signature);
+  ++this.changeCount_;
+};
+
+/**
+ * Get the change count, which is incremented each time this object is changed.
+ * @return {number} The change count.
+ */
+DigestSha256Signature.prototype.getChangeCount = function()
+{
+  return this.changeCount_;
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+/**
+ * @@deprecated Use getSignature and setSignature.
+ */
+Object.defineProperty(DigestSha256Signature.prototype, "signature",
+  { get: function() { return this.getSignature(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * This class represents an NDN Data object.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var SignedBlob = require('./util/signed-blob.js').SignedBlob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var Sha256WithRsaSignature = require('./sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var MetaInfo = require('./meta-info.js').MetaInfo; /** @ignore */
+var IncomingFaceId = require('./lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var Crypto = require('./crypto.js');
+
+/**
+ * Create a new Data with the optional values.  There are 2 forms of constructor:
+ * new Data([name] [, content]);
+ * new Data(name, metaInfo [, content]);
+ *
+ * @constructor
+ * @param {Name} name
+ * @param {MetaInfo} metaInfo
+ * @param {Buffer} content
+ */
+var Data = function Data(nameOrData, metaInfoOrContent, arg3)
+{
+  if (nameOrData instanceof Data) {
+    // The copy constructor.
+    var data = nameOrData;
+
+    // Copy the Data object.
+    this.name_ = new ChangeCounter(new Name(data.getName()));
+    this.metaInfo_ = new ChangeCounter(new MetaInfo(data.getMetaInfo()));
+    this.signature_ = new ChangeCounter(data.getSignature().clone());
+    this.content_ = data.content_;
+    this.defaultWireEncoding_ = data.getDefaultWireEncoding();
+    this.defaultFullName_ = data.defaultFullName_;
+    this.defaultWireEncodingFormat_ = data.defaultWireEncodingFormat_;
+  }
+  else {
+    var name = nameOrData;
+    if (typeof name === 'string')
+      this.name_ = new ChangeCounter(new Name(name));
+    else
+      this.name_ = new ChangeCounter(typeof name === 'object' && name instanceof Name ?
+         new Name(name) : new Name());
+
+    var metaInfo;
+    var content;
+    if (typeof metaInfoOrContent === 'object' &&
+        metaInfoOrContent instanceof MetaInfo) {
+      metaInfo = metaInfoOrContent;
+      content = arg3;
+    }
+    else {
+      metaInfo = null;
+      content = metaInfoOrContent;
+    }
+
+    this.metaInfo_ = new ChangeCounter(typeof metaInfo === 'object' && metaInfo instanceof MetaInfo ?
+      new MetaInfo(metaInfo) : new MetaInfo());
+
+    this.content_ = typeof content === 'object' && content instanceof Blob ?
+      content : new Blob(content, true);
+
+    this.signature_ = new ChangeCounter(new Sha256WithRsaSignature());
+    this.defaultWireEncoding_ = new SignedBlob();
+    this.defaultFullName_ = new Name();
+    this.defaultWireEncodingFormat_ = null;
+  }
+
+  this.getDefaultWireEncodingChangeCount_ = 0;
+  this.changeCount_ = 0;
+  this.lpPacket_ = null;
+};
+
+exports.Data = Data;
+
+/**
+ * Get the data packet's name.
+ * @return {Name} The name. If not specified, the name size() is 0.
+ */
+Data.prototype.getName = function()
+{
+  return this.name_.get();
+};
+
+/**
+ * Get the data packet's meta info.
+ * @return {MetaInfo} The meta info.
+ */
+Data.prototype.getMetaInfo = function()
+{
+  return this.metaInfo_.get();
+};
+
+/**
+ * Get the data packet's signature object.
+ * @return {Signature} The signature object.
+ */
+Data.prototype.getSignature = function()
+{
+  return this.signature_.get();
+};
+
+/**
+ * Get the data packet's content.
+ * @return {Blob} The content as a Blob, which isNull() if unspecified.
+ */
+Data.prototype.getContent = function()
+{
+  return this.content_;
+};
+
+/**
+ * @deprecated Use getContent. This method returns a Buffer which is the former
+ * behavior of getContent, and should only be used while updating your code.
+ */
+Data.prototype.getContentAsBuffer = function()
+{
+  return this.content_.buf();
+};
+
+/**
+ * Return the default wire encoding, which was encoded with
+ * getDefaultWireEncodingFormat().
+ * @return {SignedBlob} The default wire encoding, whose isNull() may be true
+ * if there is no default wire encoding.
+ */
+Data.prototype.getDefaultWireEncoding = function()
+{
+  if (this.getDefaultWireEncodingChangeCount_ != this.getChangeCount()) {
+    // The values have changed, so the default wire encoding is invalidated.
+    this.defaultWireEncoding_ = new SignedBlob();
+    this.defaultWireEncodingFormat_ = null;
+    this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
+  }
+
+  return this.defaultWireEncoding_;
+};
+
+/**
+ * Get the WireFormat which is used by getDefaultWireEncoding().
+ * @return {WireFormat} The WireFormat, which is only meaningful if the
+ * getDefaultWireEncoding() is not isNull().
+ */
+Data.prototype.getDefaultWireEncodingFormat = function()
+{
+  return this.defaultWireEncodingFormat_;
+};
+
+/**
+ * Get the incoming face ID according to the incoming packet header.
+ * @return {number} The incoming face ID. If not specified, return null.
+ */
+Data.prototype.getIncomingFaceId = function()
+{
+  var field =
+    this.lpPacket_ === null ? null : IncomingFaceId.getFirstHeader(this.lpPacket_);
+  return field === null ? null : field.getFaceId();
+};
+
+/**
+ * Get the Data packet's full name, which includes the final
+ * ImplicitSha256Digest component based on the wire encoding for a particular
+ * wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Name} The full name. You must not change the Name object - if you
+ * need to change it then make a copy.
+ */
+Data.prototype.getFullName = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  // The default full name depends on the default wire encoding.
+  if (!this.getDefaultWireEncoding().isNull() &&
+      this.defaultFullName_.size() > 0 &&
+      this.getDefaultWireEncodingFormat() == wireFormat)
+    // We already have a full name. A non-null default wire encoding means
+    // that the Data packet fields have not changed.
+    return this.defaultFullName_;
+
+  var fullName = new Name(this.getName());
+  var hash = Crypto.createHash('sha256');
+  // wireEncode will use the cached encoding if possible.
+  hash.update(this.wireEncode(wireFormat).buf());
+  fullName.appendImplicitSha256Digest(new Blob(hash.digest(), false));
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // wireEncode has already set defaultWireEncodingFormat_.
+    this.defaultFullName_ = fullName;
+
+  return fullName;
+};
+
+/**
+ * Set name to a copy of the given Name.
+ * @param {Name} name The Name which is copied.
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+Data.prototype.setName = function(name)
+{
+  this.name_.set(typeof name === 'object' && name instanceof Name ?
+    new Name(name) : new Name());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set metaInfo to a copy of the given MetaInfo.
+ * @param {MetaInfo} metaInfo The MetaInfo which is copied.
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+Data.prototype.setMetaInfo = function(metaInfo)
+{
+  this.metaInfo_.set(typeof metaInfo === 'object' && metaInfo instanceof MetaInfo ?
+    new MetaInfo(metaInfo) : new MetaInfo());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the signature to a copy of the given signature.
+ * @param {Signature} signature The signature object which is cloned.
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+Data.prototype.setSignature = function(signature)
+{
+  this.signature_.set(signature == null ?
+    new Sha256WithRsaSignature() : signature.clone());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the content to the given value.
+ * @param {Blob|Buffer} content The content bytes. If content is not a Blob,
+ * then create a new Blob to copy the bytes (otherwise take another pointer to
+ * the same Blob).
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+Data.prototype.setContent = function(content)
+{
+  this.content_ = typeof content === 'object' && content instanceof Blob ?
+    content : new Blob(content, true);
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Encode this Data for a particular wire format. If wireFormat is the default
+ * wire format, also set the defaultWireEncoding field to the encoded result.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {SignedBlob} The encoded buffer in a SignedBlob object.
+ */
+Data.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (!this.getDefaultWireEncoding().isNull() &&
+      this.getDefaultWireEncodingFormat() == wireFormat)
+    // We already have an encoding in the desired format.
+    return this.getDefaultWireEncoding();
+
+  var result = wireFormat.encodeData(this);
+  var wireEncoding = new SignedBlob
+    (result.encoding, result.signedPortionBeginOffset,
+     result.signedPortionEndOffset);
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // This is the default wire encoding.
+    this.setDefaultWireEncoding
+      (wireEncoding, WireFormat.getDefaultWireFormat());
+  return wireEncoding;
+};
+
+/**
+ * Decode the input using a particular wire format and update this Data. If
+ * wireFormat is the default wire format, also set the defaultWireEncoding to
+ * another pointer to the input.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Data.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var result;
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    result = wireFormat.decodeData(this, input.buf(), false);
+  else
+    result = wireFormat.decodeData(this, input, true);
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // This is the default wire encoding.  In the Blob constructor, set copy
+    // true, but if input is already a Blob, it won't copy.
+    this.setDefaultWireEncoding(new SignedBlob
+      (new Blob(input, true), result.signedPortionBeginOffset,
+       result.signedPortionEndOffset),
+      WireFormat.getDefaultWireFormat());
+  else
+    this.setDefaultWireEncoding(new SignedBlob(), null);
+};
+
+/**
+ * An internal library method to set the LpPacket for an incoming packet. The
+ * application should not call this.
+ * @param {LpPacket} lpPacket The LpPacket. This does not make a copy.
+ * @return {Data} This Data so that you can chain calls to update values.
+ * @note This is an experimental feature. This API may change in the future.
+ */
+Data.prototype.setLpPacket = function(lpPacket)
+{
+  this.lpPacket_ = lpPacket;
+  // Don't update changeCount_ since this doesn't affect the wire encoding.
+  return this;
+}
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+Data.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.name_.checkChanged();
+  changed = this.metaInfo_.checkChanged() || changed;
+  changed = this.signature_.checkChanged() || changed;
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+
+Data.prototype.setDefaultWireEncoding = function
+  (defaultWireEncoding, defaultWireEncodingFormat)
+{
+  this.defaultWireEncoding_ = defaultWireEncoding;
+  this.defaultWireEncodingFormat_ = defaultWireEncodingFormat;
+  // Set getDefaultWireEncodingChangeCount_ so that the next call to
+  // getDefaultWireEncoding() won't clear _defaultWireEncoding.
+  this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(Data.prototype, "name",
+  { get: function() { return this.getName(); },
+    set: function(val) { this.setName(val); } });
+Object.defineProperty(Data.prototype, "metaInfo",
+  { get: function() { return this.getMetaInfo(); },
+    set: function(val) { this.setMetaInfo(val); } });
+Object.defineProperty(Data.prototype, "signature",
+  { get: function() { return this.getSignature(); },
+    set: function(val) { this.setSignature(val); } });
+/**
+ * @deprecated Use getContent and setContent.
+ */
+Object.defineProperty(Data.prototype, "content",
+  { get: function() { return this.getContentAsBuffer(); },
+    set: function(val) { this.setContent(val); } });
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * Create a new SecurityException to report an exception from the security
+ * library, wrapping the given error object.
+ * Call with: throw new SecurityException(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+function SecurityException(error)
+{
+  if (error) {
+    error.__proto__ = SecurityException.prototype;
+    return error;
+  }
+}
+
+SecurityException.prototype = new Error();
+SecurityException.prototype.name = "SecurityException";
+
+exports.SecurityException = SecurityException;
+
+function UnrecognizedKeyFormatException(error)
+{
+  // Call the base constructor.
+  SecurityException.call(this, error);
+}
+UnrecognizedKeyFormatException.prototype = new SecurityException();
+UnrecognizedKeyFormatException.prototype.name = "UnrecognizedKeyFormatException";
+
+exports.UnrecognizedKeyFormatException = UnrecognizedKeyFormatException;
+
+function UnrecognizedDigestAlgorithmException(error)
+{
+  // Call the base constructor.
+  SecurityException.call(this, error);
+}
+UnrecognizedDigestAlgorithmException.prototype = new SecurityException();
+UnrecognizedDigestAlgorithmException.prototype.name = "UnrecognizedDigestAlgorithmException";
+
+exports.UnrecognizedDigestAlgorithmException = UnrecognizedDigestAlgorithmException;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * This module defines constants used by the security library.
+ */
+
+/**
+ * The KeyType integer is used by the Sqlite key storage, so don't change them.
+ * Make these the same as ndn-cxx in case the storage file is shared.
+ * @constructor
+ */
+var KeyType = function KeyType()
+{
+}
+
+exports.KeyType = KeyType;
+
+KeyType.RSA = 0;
+KeyType.ECDSA = 1;
+KeyType.AES = 128;
+
+var KeyClass = function KeyClass()
+{
+};
+
+exports.KeyClass = KeyClass;
+
+KeyClass.PUBLIC = 1;
+KeyClass.PRIVATE = 2;
+KeyClass.SYMMETRIC = 3;
+
+var DigestAlgorithm = function DigestAlgorithm()
+{
+};
+
+exports.DigestAlgorithm = DigestAlgorithm;
+
+DigestAlgorithm.SHA256 = 1;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var KeyType = require('./security-types.js').KeyType;
+
+/**
+ * KeyParams is a base class for key parameters. Its subclasses are used to
+ * store parameters for key generation. You should create one of the subclasses,
+ * for example RsaKeyParams.
+ * @constructor
+ */
+var KeyParams = function KeyParams(keyType)
+{
+  this.keyType = keyType;
+};
+
+exports.KeyParams = KeyParams;
+
+KeyParams.prototype.getKeyType = function()
+{
+  return this.keyType;
+};
+
+var RsaKeyParams = function RsaKeyParams(size)
+{
+  // Call the base constructor.
+  KeyParams.call(this, RsaKeyParams.getType());
+
+  if (size == null)
+    size = RsaKeyParams.getDefaultSize();
+  this.size = size;
+};
+
+RsaKeyParams.prototype = new KeyParams();
+RsaKeyParams.prototype.name = "RsaKeyParams";
+
+exports.RsaKeyParams = RsaKeyParams;
+
+RsaKeyParams.prototype.getKeySize = function()
+{
+  return this.size;
+};
+
+RsaKeyParams.getDefaultSize = function() { return 2048; };
+
+RsaKeyParams.getType = function() { return KeyType.RSA; };
+
+var EcdsaKeyParams = function EcdsaKeyParams(size)
+{
+  // Call the base constructor.
+  KeyParams.call(this, EcdsaKeyParams.getType());
+
+  if (size == null)
+    size = EcdsaKeyParams.getDefaultSize();
+  this.size = size;
+};
+
+EcdsaKeyParams.prototype = new KeyParams();
+EcdsaKeyParams.prototype.name = "EcdsaKeyParams";
+
+exports.EcdsaKeyParams = EcdsaKeyParams;
+
+EcdsaKeyParams.prototype.getKeySize = function()
+{
+  return this.size;
+};
+
+EcdsaKeyParams.getDefaultSize = function() { return 256; };
+
+EcdsaKeyParams.getType = function() { return KeyType.ECDSA; };
+
+var AesKeyParams = function AesKeyParams(size)
+{
+  // Call the base constructor.
+  KeyParams.call(this, AesKeyParams.getType());
+
+  if (size == null)
+    size = AesKeyParams.getDefaultSize();
+  this.size = size;
+};
+
+AesKeyParams.prototype = new KeyParams();
+AesKeyParams.prototype.name = "AesKeyParams";
+
+exports.AesKeyParams = AesKeyParams;
+
+AesKeyParams.prototype.getKeySize = function()
+{
+  return this.size;
+};
+
+AesKeyParams.getDefaultSize = function() { return 64; };
+
+AesKeyParams.getType = function() { return KeyType.AES; };
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DerDecodingException = require('../../encoding/der/der-decoding-exception.js').DerDecodingException; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var UnrecognizedKeyFormatException = require('../security-exception.js').UnrecognizedKeyFormatException; /** @ignore */
+var KeyType = require('../security-types.js').KeyType; /** @ignore */
+var DigestAlgorithm = require('../security-types.js').DigestAlgorithm;
+
+/**
+ * Create a new PublicKey by decoding the keyDer. Set the key type from the
+ * decoding.
+ * @param {Blob} keyDer The blob of the SubjectPublicKeyInfo DER.
+ * @throws UnrecognizedKeyFormatException if can't decode the key DER.
+ * @constructor
+ */
+var PublicKey = function PublicKey(keyDer)
+{
+  if (!keyDer) {
+    this.keyDer = new Blob();
+    this.keyType = null;
+    return;
+  }
+
+  this.keyDer = keyDer;
+
+  // Get the public key OID.
+  var oidString = null;
+  try {
+    var parsedNode = DerNode.parse(keyDer.buf(), 0);
+    var rootChildren = parsedNode.getChildren();
+    var algorithmIdChildren = DerNode.getSequence(rootChildren, 0).getChildren();
+    oidString = algorithmIdChildren[0].toVal();
+  }
+  catch (ex) {
+    throw new UnrecognizedKeyFormatException(new Error
+      ("PublicKey.decodeKeyType: Error decoding the public key: " + ex.message));
+  }
+
+  // Verify that the we can decode.
+  if (oidString == PublicKey.RSA_ENCRYPTION_OID) {
+    this.keyType = KeyType.RSA;
+    // TODO: Check RSA decoding.
+  }
+  else if (oidString == PublicKey.EC_ENCRYPTION_OID) {
+    this.keyType = KeyType.ECDSA;
+    // TODO: Check EC decoding.
+  }
+};
+
+exports.PublicKey = PublicKey;
+
+/**
+ * Encode the public key into DER.
+ * @return {DerNode} The encoded DER syntax tree.
+ */
+PublicKey.prototype.toDer = function()
+{
+  return DerNode.parse(this.keyDer.buf());
+};
+
+/**
+ * Get the key type.
+ * @return {number} The key type as an int from KeyType.
+ */
+PublicKey.prototype.getKeyType = function()
+{
+  return this.keyType;
+};
+
+/**
+ * Get the digest of the public key.
+ * @param {number} digestAlgorithm (optional) The integer from DigestAlgorithm,
+ * such as DigestAlgorithm.SHA256. If omitted, use DigestAlgorithm.SHA256 .
+ * @return {Blob} The digest value.
+ */
+PublicKey.prototype.getDigest = function(digestAlgorithm)
+{
+  if (digestAlgorithm == undefined)
+    digestAlgorithm = DigestAlgorithm.SHA256;
+
+  if (digestAlgorithm == DigestAlgorithm.SHA256) {
+    var hash = Crypto.createHash('sha256');
+    hash.update(this.keyDer.buf());
+    return new Blob(hash.digest(), false);
+  }
+  else
+    throw new SecurityException(new Error("Wrong format!"));
+};
+
+/**
+ * Get the raw bytes of the public key in DER format.
+ * @return {Blob} The public key DER.
+ */
+PublicKey.prototype.getKeyDer = function()
+{
+  return this.keyDer;
+};
+
+PublicKey.RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1";
+PublicKey.EC_ENCRYPTION_OID = "1.2.840.10045.2.1";
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var OID = require('../../encoding/oid.js').OID;
+
+/**
+ * A CertificateExtension represents the Extension entry in a certificate.
+ * Create a new CertificateExtension.
+ * @param {string|OID} oid The oid of subject description entry.
+ * @param {boolean} isCritical If true, the extension must be handled.
+ * @param {Blob} value The extension value.
+ * @constructor
+ */
+var CertificateExtension = function CertificateExtension(oid, isCritical, value)
+{
+  if (typeof oid === 'string')
+    this.extensionId = new OID(oid);
+  else
+    // Assume oid is already an OID.
+    this.extensionId = oid;
+
+  this.isCritical = isCritical;
+  this.extensionValue = value;
+};
+
+exports.CertificateExtension = CertificateExtension;
+
+/**
+ * Encode the object into a DER syntax tree.
+ * @return {DerNode} The encoded DER syntax tree.
+ */
+CertificateExtension.prototype.toDer = function()
+{
+  var root = new DerNode.DerSequence();
+
+  var extensionId = new DerNode.DerOid(this.extensionId);
+  var isCritical = new DerNode.DerBoolean(this.isCritical);
+  var extensionValue = new DerNode.DerOctetString(this.extensionValue.buf());
+
+  root.addChild(extensionId);
+  root.addChild(isCritical);
+  root.addChild(extensionValue);
+
+  root.getSize();
+
+  return root;
+};
+
+CertificateExtension.prototype.toDerBlob = function()
+{
+  return this.toDer().encode();
+};
+
+CertificateExtension.prototype.getOid = function()
+{
+  return this.extensionId;
+};
+
+CertificateExtension.prototype.getIsCritical = function()
+{
+  return this.isCritical;
+};
+
+CertificateExtension.prototype.getValue = function()
+{
+  return this.extensionValue;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var OID = require('../../encoding/oid.js').OID; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode;
+
+/**
+ * A CertificateSubjectDescription represents the SubjectDescription entry in a
+ * Certificate.
+ * Create a new CertificateSubjectDescription.
+ * @param {string|OID} oid The oid of the subject description entry.
+ * @param {string} value The value of the subject description entry.
+ * @constructor
+ */
+var CertificateSubjectDescription = function CertificateSubjectDescription
+  (oid, value)
+{
+  if (typeof oid === 'string')
+    this.oid = new OID(oid);
+  else
+    // Assume oid is already an OID.
+    this.oid = oid;
+
+  this.value = value;
+};
+
+exports.CertificateSubjectDescription = CertificateSubjectDescription;
+
+/**
+ * Encode the object into a DER syntax tree.
+ * @return {DerNode} The encoded DER syntax tree.
+ */
+CertificateSubjectDescription.prototype.toDer = function()
+{
+  var root = new DerNode.DerSequence();
+
+  var oid = new DerNode.DerOid(this.oid);
+  // Use Blob to convert the String to a ByteBuffer.
+  var value = new DerNode.DerPrintableString(new Blob(this.value).buf());
+
+  root.addChild(oid);
+  root.addChild(value);
+
+  return root;
+};
+
+CertificateSubjectDescription.prototype.getOidString = function()
+{
+  return this.oid.toString();
+};
+
+CertificateSubjectDescription.prototype.getValue = function()
+{
+  return this.value;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var ContentType = require('../../meta-info.js').ContentType; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var KeyType = require('../../security/security-types.js').KeyType; /** @ignore */
+var PublicKey = require('./public-key.js').PublicKey; /** @ignore */
+var CertificateSubjectDescription = require('./certificate-subject-description.js').CertificateSubjectDescription; /** @ignore */
+var CertificateExtension = require('./certificate-extension.js').CertificateExtension;
+
+/**
+ * Create a Certificate from the content in the data packet (if not omitted).
+ * @param {Data} data (optional) The data packet with the content to decode.
+ * If omitted, create a Certificate with default values and the Data content
+ * is empty.
+ * @constructor
+ */
+var Certificate = function Certificate(data)
+{
+  // Call the base constructor.
+  if (data != undefined)
+    Data.call(this, data);
+  else
+    Data.call(this);
+
+  this.subjectDescriptionList = [];  // of CertificateSubjectDescription
+  this.extensionList = [];           // of CertificateExtension
+  this.notBefore = Number.MAX_VALUE; // MillisecondsSince1970
+  this.notAfter = -Number.MAX_VALUE; // MillisecondsSince1970
+  this.key = new PublicKey();
+
+  if (data != undefined)
+    this.decode();
+};
+Certificate.prototype = new Data();
+Certificate.prototype.name = "Certificate";
+
+exports.Certificate = Certificate;
+
+/**
+ * Encode the contents of the certificate in DER format and set the Content
+ * and MetaInfo fields.
+ */
+Certificate.prototype.encode = function()
+{
+  var root = this.toDer();
+  this.setContent(root.encode());
+  this.getMetaInfo().setType(ContentType.KEY);
+};
+
+/**
+ * Add a subject description.
+ * @param {CertificateSubjectDescription} description The description to be added.
+ */
+Certificate.prototype.addSubjectDescription = function(description)
+{
+  this.subjectDescriptionList.push(description);
+};
+
+/**
+ * Get the subject description list.
+ * @return {Array<CertificateSubjectDescription>} The subject description list.
+ */
+Certificate.prototype.getSubjectDescriptionList = function()
+{
+  return this.subjectDescriptionList;
+};
+
+/**
+ * Add a certificate extension.
+ * @param {CertificateSubjectDescription} extension The extension to be added.
+ */
+Certificate.prototype.addExtension = function(extension)
+{
+  this.extensionList.push(extension);
+};
+
+/**
+ * Get the certificate extension list.
+ * @return {Array<CertificateExtension>} The extension list.
+ */
+Certificate.prototype.getExtensionList = function()
+{
+  return this.extensionList;
+};
+
+Certificate.prototype.setNotBefore = function(notBefore)
+{
+  this.notBefore = notBefore;
+};
+
+Certificate.prototype.getNotBefore = function()
+{
+  return this.notBefore;
+};
+
+Certificate.prototype.setNotAfter = function(notAfter)
+{
+  this.notAfter = notAfter;
+};
+
+Certificate.prototype.getNotAfter = function()
+{
+  return this.notAfter;
+};
+
+Certificate.prototype.setPublicKeyInfo = function(key)
+{
+  this.key = key;
+};
+
+Certificate.prototype.getPublicKeyInfo = function()
+{
+  return this.key;
+};
+
+/**
+ * Check if the certificate is valid.
+ * @return {Boolean} True if the current time is earlier than notBefore.
+ */
+Certificate.prototype.isTooEarly = function()
+{
+  var now = new Date().getTime();
+  return now < this.notBefore;
+};
+
+/**
+ * Check if the certificate is valid.
+ * @return {Boolean} True if the current time is later than notAfter.
+ */
+Certificate.prototype.isTooLate = function()
+{
+  var now = new Date().getTime();
+  return now > this.notAfter;
+};
+
+/**
+ * Encode the certificate fields in DER format.
+ * @return {DerSequence} The DER encoded contents of the certificate.
+ */
+Certificate.prototype.toDer = function()
+{
+  var root = new DerNode.DerSequence();
+  var validity = new DerNode.DerSequence();
+  var notBefore = new DerNode.DerGeneralizedTime(this.notBefore);
+  var notAfter = new DerNode.DerGeneralizedTime(this.notAfter);
+
+  validity.addChild(notBefore);
+  validity.addChild(notAfter);
+
+  root.addChild(validity);
+
+  var subjectList = new DerNode.DerSequence();
+  for (var i = 0; i < this.subjectDescriptionList.length; ++i)
+    subjectList.addChild(this.subjectDescriptionList[i].toDer());
+
+  root.addChild(subjectList);
+  root.addChild(this.key.toDer());
+
+  if (this.extensionList.length > 0) {
+    var extensionList = new DerNode.DerSequence();
+    for (var i = 0; i < this.extensionList.length; ++i)
+      extensionList.addChild(this.extensionList[i].toDer());
+    root.addChild(extensionList);
+  }
+
+  return root;
+};
+
+/**
+ * Populate the fields by the decoding DER data from the Content.
+ */
+Certificate.prototype.decode = function()
+{
+  var root = DerNode.parse(this.getContent().buf());
+
+  // We need to ensure that there are:
+  //   validity (notBefore, notAfter)
+  //   subject list
+  //   public key
+  //   (optional) extension list
+
+  var rootChildren = root.getChildren();
+  // 1st: validity info
+  var validityChildren = DerNode.getSequence(rootChildren, 0).getChildren();
+  this.notBefore = validityChildren[0].toVal();
+  this.notAfter = validityChildren[1].toVal();
+
+  // 2nd: subjectList
+  var subjectChildren = DerNode.getSequence(rootChildren, 1).getChildren();
+  for (var i = 0; i < subjectChildren.length; ++i) {
+    var sd = DerNode.getSequence(subjectChildren, i);
+    var descriptionChildren = sd.getChildren();
+    var oidStr = descriptionChildren[0].toVal();
+    var value = descriptionChildren[1].toVal().buf().toString('binary');
+
+    this.addSubjectDescription(new CertificateSubjectDescription(oidStr, value));
+  }
+
+  // 3rd: public key
+  var publicKeyInfo = rootChildren[2].encode();
+  this.key =  new PublicKey(publicKeyInfo);
+
+  if (rootChildren.length > 3) {
+    var extensionChildren = DerNode.getSequence(rootChildren, 3).getChildren();
+    for (var i = 0; i < extensionChildren.length; ++i) {
+      var extInfo = DerNode.getSequence(extensionChildren, i);
+
+      var children = extInfo.getChildren();
+      var oidStr = children[0].toVal();
+      var isCritical = children[1].toVal();
+      var value = children[2].toVal();
+      this.addExtension(new CertificateExtension(oidStr, isCritical, value));
+    }
+  }
+};
+
+/**
+ * Override to call the base class wireDecode then populate the certificate
+ * fields.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Certificate.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  Data.prototype.wireDecode.call(this, input, wireFormat);
+  this.decode();
+};
+
+Certificate.prototype.toString = function()
+{
+  var s = "Certificate name:\n";
+  s += "  " + this.getName().toUri() + "\n";
+  s += "Validity:\n";
+
+  var notBeforeStr = Certificate.toIsoString(Math.round(this.notBefore));
+  var notAfterStr = Certificate.toIsoString(Math.round(this.notAfter));
+
+  s += "  NotBefore: " + notBeforeStr + "\n";
+  s += "  NotAfter: " + notAfterStr + "\n";
+  for (var i = 0; i < this.subjectDescriptionList.length; ++i) {
+    var sd = this.subjectDescriptionList[i];
+    s += "Subject Description:\n";
+    s += "  " + sd.getOidString() + ": " + sd.getValue() + "\n";
+  }
+
+  s += "Public key bits:\n";
+  var keyDer = this.key.getKeyDer();
+  var encodedKey = keyDer.buf().toString('base64');
+  for (var i = 0; i < encodedKey.length; i += 64)
+    s += encodedKey.substring(i, Math.min(i + 64, encodedKey.length)) + "\n";
+
+  if (this.extensionList.length > 0) {
+    s += "Extensions:\n";
+    for (var i = 0; i < this.extensionList.length; ++i) {
+      var ext = this.extensionList[i];
+      s += "  OID: " + ext.getOid() + "\n";
+      s += "  Is critical: " + (ext.getIsCritical() ? 'Y' : 'N') + "\n";
+
+      s += "  Value: " + ext.getValue().toHex() + "\n" ;
+    }
+  }
+
+  return s;
+};
+
+/**
+ * Convert a UNIX timestamp to ISO time representation with the "T" in the middle.
+ * @param {type} msSince1970 Timestamp as milliseconds since Jan 1, 1970.
+ * @return {string} The string representation.
+ */
+Certificate.toIsoString = function(msSince1970)
+{
+  var utcTime = new Date(Math.round(msSince1970));
+  return utcTime.getUTCFullYear() +
+         Certificate.to2DigitString(utcTime.getUTCMonth() + 1) +
+         Certificate.to2DigitString(utcTime.getUTCDate()) +
+         "T" +
+         Certificate.to2DigitString(utcTime.getUTCHours()) +
+         Certificate.to2DigitString(utcTime.getUTCMinutes()) +
+         Certificate.to2DigitString(utcTime.getUTCSeconds());
+};
+
+/**
+ * A private method to zero pad an integer to 2 digits.
+ * @param {number} x The number to pad.  Assume it is a non-negative integer.
+ * @return {string} The padded string.
+ */
+Certificate.to2DigitString = function(x)
+{
+  var result = x.toString();
+  return result.length === 1 ? "0" + result : result;
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var SecurityException = require('../../security//security-exception.js').SecurityException; /** @ignore */
+var Certificate = require('./certificate.js').Certificate; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat;
+
+/**
+ * @constructor
+ */
+var IdentityCertificate = function IdentityCertificate(data)
+{
+  // Call the base constructor.
+  if (data != undefined)
+    // This works if data is Data or IdentityCertificate.
+    Certificate.call(this, data);
+  else
+    Certificate.call(this);
+
+  this.publicKeyName = new Name();
+
+  if (data instanceof IdentityCertificate) {
+    // The copy constructor.
+    this.publicKeyName = new Name(data.publicKeyName);
+  }
+  else if (data instanceof Data) {
+    if (!IdentityCertificate.isCorrectName(data.getName()))
+      throw new SecurityException(new Error("Wrong Identity Certificate Name!"));
+
+    this.setPublicKeyName();
+  }
+};
+IdentityCertificate.prototype = new Certificate();
+IdentityCertificate.prototype.name = "IdentityCertificate";
+
+exports.IdentityCertificate = IdentityCertificate;
+
+/**
+ * Override the base class method to check that the name is a valid identity
+ * certificate name.
+ * @param {Name} name The identity certificate name which is copied.
+ * @return {Data} This Data so that you can chain calls to update values.
+ */
+IdentityCertificate.prototype.setName = function(name)
+{
+  if (!IdentityCertificate.isCorrectName(name))
+    throw new SecurityException(new Error("Wrong Identity Certificate Name!"));
+
+  // Call the super class method.
+  Certificate.prototype.setName.call(this, name);
+  this.setPublicKeyName();
+  return this;
+};
+
+/**
+ * Override to call the base class wireDecode then update the public key name.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+IdentityCertificate.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  Certificate.prototype.wireDecode.call(this, input, wireFormat);
+  this.setPublicKeyName();
+};
+
+IdentityCertificate.prototype.getPublicKeyName = function()
+{
+  return this.publicKeyName;
+};
+
+IdentityCertificate.isIdentityCertificate = function(certificate)
+{
+  return IdentityCertificate.isCorrectName(certificate.getName());
+};
+
+/**
+ * Get the public key name from the full certificate name.
+ * @param {Name} certificateName The full certificate name.
+ * @return {Name} The related public key name.
+ */
+IdentityCertificate.certificateNameToPublicKeyName = function(certificateName)
+{
+  var idString = "ID-CERT";
+  var foundIdString = false;
+  var idCertComponentIndex = certificateName.size() - 1;
+  for (; idCertComponentIndex + 1 > 0; --idCertComponentIndex) {
+    if (certificateName.get(idCertComponentIndex).toEscapedString() == idString) {
+      foundIdString = true;
+      break;
+    }
+  }
+
+  if (!foundIdString)
+    throw new Error
+      ("Incorrect identity certificate name " + certificateName.toUri());
+
+  var tempName = certificateName.getSubName(0, idCertComponentIndex);
+  var keyString = "KEY";
+  var foundKeyString = false;
+  var keyComponentIndex = 0;
+  for (; keyComponentIndex < tempName.size(); keyComponentIndex++) {
+    if (tempName.get(keyComponentIndex).toEscapedString() == keyString) {
+      foundKeyString = true;
+      break;
+    }
+  }
+
+  if (!foundKeyString)
+    throw new Error
+      ("Incorrect identity certificate name " + certificateName.toUri());
+
+  return tempName
+    .getSubName(0, keyComponentIndex)
+    .append(tempName.getSubName
+            (keyComponentIndex + 1, tempName.size() - keyComponentIndex - 1));
+};
+
+IdentityCertificate.isCorrectName = function(name)
+{
+  var i = name.size() - 1;
+
+  var idString = "ID-CERT";
+  for (; i >= 0; i--) {
+    if (name.get(i).toEscapedString() == idString)
+      break;
+  }
+
+  if (i < 0)
+    return false;
+
+  var keyIdx = 0;
+  var keyString = "KEY";
+  for (; keyIdx < name.size(); keyIdx++) {
+    if(name.get(keyIdx).toEscapedString() == keyString)
+      break;
+  }
+
+  if (keyIdx >= name.size())
+    return false;
+
+  return true;
+};
+
+IdentityCertificate.prototype.setPublicKeyName = function()
+{
+  this.publicKeyName = IdentityCertificate.certificateNameToPublicKeyName
+    (this.getName());
+};
+
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise;
+
+/**
+ * IdentityStorage is a base class for the storage of identity, public keys and
+ * certificates. Private keys are stored in PrivateKeyStorage.
+ * This is an abstract base class.  A subclass must implement the methods.
+ * @constructor
+ */
+var IdentityStorage = function IdentityStorage()
+{
+};
+
+exports.IdentityStorage = IdentityStorage;
+
+/**
+ * Check if the specified identity already exists.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns true if the identity
+ * exists.
+ */
+IdentityStorage.prototype.doesIdentityExistPromise = function
+  (identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.doesIdentityExistPromise is not implemented"));
+};
+
+/**
+ * Check if the specified identity already exists.
+ * @param {Name} identityName The identity name.
+ * @return {boolean} true if the identity exists, otherwise false.
+ * @throws Error If doesIdentityExistPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.doesIdentityExist = function(identityName)
+{
+  return SyncPromise.getValue(this.doesIdentityExistPromise(identityName, true));
+};
+
+/**
+ * Add a new identity. Do nothing if the identity already exists.
+ * @param {Name} identityName The identity name to be added.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the identity is
+ * added.
+ */
+IdentityStorage.prototype.addIdentityPromise = function(identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.addIdentityPromise is not implemented"));
+};
+
+/**
+ * Add a new identity. Do nothing if the identity already exists.
+ * @param {Name} identityName The identity name to be added.
+ * @throws Error If addIdentityPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.addIdentity = function(identityName)
+{
+  return SyncPromise.getValue(this.addIdentityPromise(identityName, true));
+};
+
+/**
+ * Revoke the identity.
+ * @return {boolean} true if the identity was revoked, false if not.
+ */
+IdentityStorage.prototype.revokeIdentity = function()
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.revokeIdentity is not implemented"));
+};
+
+/**
+ * Generate a name for a new key belonging to the identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useKsk If true, generate a KSK name, otherwise a DSK name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the generated key Name.
+ */
+IdentityStorage.prototype.getNewKeyNamePromise = function
+  (identityName, useKsk, useSync)
+{
+  var timestamp = Math.floor(new Date().getTime() / 1000.0);
+  while (timestamp <= IdentityStorage.lastTimestamp)
+    // Make the timestamp unique.
+    timestamp += 1;
+  IdentityStorage.lastTimestamp = timestamp;
+
+  // Get the number of seconds as a string.
+  var seconds = "" + timestamp;
+
+  var keyIdStr;
+  if (useKsk)
+    keyIdStr = "ksk-" + seconds;
+  else
+    keyIdStr = "dsk-" + seconds;
+
+  var keyName = new Name(identityName).append(keyIdStr);
+
+  return this.doesKeyExistPromise(keyName, useSync)
+  .then(function(exists) {
+    if (exists)
+      throw new SecurityException(new Error("Key name already exists"));
+
+    return SyncPromise.resolve(keyName);
+  });
+};
+
+/**
+ * Generate a name for a new key belonging to the identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useKsk If true, generate a KSK name, otherwise a DSK name.
+ * @return {Name} The generated key name.
+ * @throws Error If getNewKeyNamePromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.getNewKeyName = function(identityName, useKsk)
+{
+  return SyncPromise.getValue
+    (this.getNewKeyNamePromise(identityName, useKsk, true));
+};
+
+/**
+ * Check if the specified key already exists.
+ * @param {Name} keyName The name of the key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns true if the key exists.
+ */
+IdentityStorage.prototype.doesKeyExistPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.doesKeyExistPromise is not implemented"));
+};
+
+/**
+ * Check if the specified key already exists.
+ * @param {Name} keyName The name of the key.
+ * @return {boolean} true if the key exists, otherwise false.
+ * @throws Error If doesKeyExistPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.doesKeyExist = function(keyName)
+{
+  return SyncPromise.getValue(this.doesKeyExistPromise(keyName, true));
+};
+
+/**
+ * Add a public key to the identity storage. Also call addIdentity to ensure
+ * that the identityName for the key exists. However, if the key already
+ * exists, do nothing.
+ * @param {Name} keyName The name of the public key to be added.
+ * @param {number} keyType Type of the public key to be added from KeyType, such
+ * as KeyType.RSA..
+ * @param {Blob} publicKeyDer A blob of the public key DER to be added.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when complete.
+ */
+IdentityStorage.prototype.addKeyPromise = function
+  (keyName, keyType, publicKeyDer, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.addKeyPromise is not implemented"));
+};
+
+/**
+ * Add a public key to the identity storage. Also call addIdentity to ensure
+ * that the identityName for the key exists.
+ * @param {Name} keyName The name of the public key to be added.
+ * @param {number} keyType Type of the public key to be added from KeyType, such
+ * as KeyType.RSA..
+ * @param {Blob} publicKeyDer A blob of the public key DER to be added.
+ * @throws SecurityException if a key with the keyName already exists.
+ * @throws Error If addKeyPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.addKey = function(keyName, keyType, publicKeyDer)
+{
+  return SyncPromise.getValue
+    (this.addKeyPromise(keyName, keyType, publicKeyDer, true));
+};
+
+/**
+ * Get the public key DER blob from the identity storage.
+ * @param {Name} keyName The name of the requested public key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the DER Blob, or a
+ * promise rejected with SecurityException if the key doesn't exist.
+ */
+IdentityStorage.prototype.getKeyPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getKeyPromise is not implemented"));
+};
+
+/**
+ * Get the public key DER blob from the identity storage.
+ * @param {Name} keyName The name of the requested public key.
+ * @return {Blob} The DER Blob.
+ * @throws SecurityException if the key doesn't exist.
+ * @throws Error If getKeyPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.getKey = function(keyName)
+{
+  return SyncPromise.getValue(this.getKeyPromise(keyName, true));
+};
+
+/**
+ * Activate a key.  If a key is marked as inactive, its private part will not be
+ * used in packet signing.
+ * @param {Name} keyName name of the key
+ */
+IdentityStorage.prototype.activateKey = function(keyName)
+{
+  throw new Error("IdentityStorage.activateKey is not implemented");
+};
+
+/**
+ * Deactivate a key. If a key is marked as inactive, its private part will not
+ * be used in packet signing.
+ * @param {Name} keyName name of the key
+ */
+IdentityStorage.prototype.deactivateKey = function(keyName)
+{
+  throw new Error("IdentityStorage.deactivateKey is not implemented");
+};
+
+/**
+ * Check if the specified certificate already exists.
+ * @param {Name} certificateName The name of the certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns true if the certificate
+ * exists.
+ */
+IdentityStorage.prototype.doesCertificateExistPromise = function
+  (certificateName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.doesCertificateExistPromise is not implemented"));
+};
+
+/**
+ * Check if the specified certificate already exists.
+ * @param {Name} certificateName The name of the certificate.
+ * @return {boolean} true if the certificate exists, otherwise false.
+ * @throws Error If doesCertificateExistPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.doesCertificateExist = function(certificateName)
+{
+  return SyncPromise.getValue
+    (this.doesCertificateExistPromise(certificateName, true));
+};
+
+/**
+ * Add a certificate to the identity storage. Also call addKey to ensure that
+ * the certificate key exists. If the certificate is already installed, don't
+ * replace it.
+ * @param {IdentityCertificate} certificate The certificate to be added.  This
+ * makes a copy of the certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when finished.
+ */
+IdentityStorage.prototype.addCertificatePromise = function(certificate, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.addCertificatePromise is not implemented"));
+};
+
+/**
+ * Add a certificate to the identity storage.
+ * @param {IdentityCertificate} certificate The certificate to be added.  This
+ * makes a copy of the certificate.
+ * @throws SecurityException if the certificate is already installed.
+ * @throws Error If addCertificatePromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.addCertificate = function(certificate)
+{
+  return SyncPromise.getValue(this.addCertificatePromise(certificate, true));
+};
+
+/**
+ * Get a certificate from the identity storage.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the requested
+ * IdentityCertificate, or a promise rejected with SecurityException if the
+ * certificate doesn't exist.
+ */
+IdentityStorage.prototype.getCertificatePromise = function
+  (certificateName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getCertificatePromise is not implemented"));
+};
+
+/**
+ * Get a certificate from the identity storage.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @return {IdentityCertificate} The requested certificate.
+ * @throws SecurityException if the certificate doesn't exist.
+ * @throws Error If getCertificatePromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.getCertificate = function(certificateName)
+{
+  return SyncPromise.getValue(this.getValuePromise(certificateName, true));
+};
+
+/**
+ * Get the TPM locator associated with this storage.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise|SyncPromise} A promise which returns the TPM locator, or a
+ * promise rejected with SecurityException if the TPM locator doesn't exist.
+ */
+IdentityStorage.prototype.getTpmLocatorPromise = function(useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getTpmLocatorPromise is not implemented"));
+};
+
+/**
+ * Get the TPM locator associated with this storage.
+ * @return {string} The TPM locator.
+ * @throws SecurityException if the TPM locator doesn't exist.
+ * @throws Error If getTpmLocatorPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+IdentityStorage.prototype.getTpmLocator = function()
+{
+  return SyncPromise.getValue(this.getTpmLocatorPromise(true));
+};
+
+/*****************************************
+ *           Get/Set Default             *
+ *****************************************/
+
+/**
+ * Get the default identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the Name of default
+ * identity, or a promise rejected with SecurityException if the default
+ * identity is not set.
+ */
+IdentityStorage.prototype.getDefaultIdentityPromise = function(useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getDefaultIdentityPromise is not implemented"));
+};
+
+/**
+ * Get the default identity.
+ * @return {Name} The name of default identity.
+ * @throws SecurityException if the default identity is not set.
+ * @throws Error If getDefaultIdentityPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultIdentity = function()
+{
+  return SyncPromise.getValue
+    (this.getDefaultIdentityPromise(true));
+};
+
+/**
+ * Get the default key name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the default key Name,
+ * or a promise rejected with SecurityException if the default key name for the
+ * identity is not set.
+ */
+IdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
+  (identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getDefaultKeyNameForIdentityPromise is not implemented"));
+};
+
+/**
+ * Get the default key name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @return {Name} The default key name.
+ * @throws SecurityException if the default key name for the identity is not set.
+ * @throws Error If getDefaultKeyNameForIdentityPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultKeyNameForIdentity = function(identityName)
+{
+  return SyncPromise.getValue
+    (this.getDefaultKeyNameForIdentityPromise(identityName, true));
+};
+
+/**
+ * Get the default certificate name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the default certificate
+ * Name, or a promise rejected with SecurityException if the default key name
+ * for the identity is not set or the default certificate name for the key name
+ * is not set.
+ */
+IdentityStorage.prototype.getDefaultCertificateNameForIdentityPromise = function
+  (identityName, useSync)
+{
+  var thisStorage = this;
+  return this.getDefaultKeyNameForIdentityPromise(identityName)
+  .then(function(keyName) {
+    return thisStorage.getDefaultCertificateNameForKeyPromise(keyName);
+  });
+};
+
+/**
+ * Get the default certificate name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @return {Name} The default certificate name.
+ * @throws SecurityException if the default key name for the identity is not
+ * set or the default certificate name for the key name is not set.
+ * @throws Error If getDefaultCertificateNameForIdentityPromise doesn't return
+ * a SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultCertificateNameForIdentity = function
+  (identityName)
+{
+  return SyncPromise.getValue
+    (this.getDefaultCertificateNameForIdentityPromise(identityName, true));
+};
+
+/**
+ * Get the default certificate name for the specified key.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the default certificate
+ * Name, or a promise rejected with SecurityException if the default certificate
+ * name for the key name is not set.
+ */
+IdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
+  (keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getDefaultCertificateNameForKeyPromise is not implemented"));
+};
+
+/**
+ * Get the default certificate name for the specified key.
+ * @param {Name} keyName The key name.
+ * @return {Name} The default certificate name.
+ * @throws SecurityException if the default certificate name for the key name
+ * is not set.
+ * @throws Error If getDefaultCertificateNameForKeyPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultCertificateNameForKey = function(keyName)
+{
+  return SyncPromise.getValue
+    (this.getDefaultCertificateNameForKeyPromise(keyName, true));
+};
+
+/**
+ * Append all the identity names to the nameList.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default identity name. If
+ * false, add only the non-default identity names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IdentityStorage.prototype.getAllIdentitiesPromise = function
+  (nameList, isDefault, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getAllIdentitiesPromise is not implemented"));
+};
+
+/**
+ * Append all the key names of a particular identity to the nameList.
+ * @param {Name} identityName The identity name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default key name. If false,
+ * add only the non-default key names.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the names are
+ * added to nameList.
+ */
+IdentityStorage.prototype.getAllKeyNamesOfIdentityPromise = function
+  (identityName, nameList, isDefault, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getAllKeyNamesOfIdentityPromise is not implemented"));
+};
+
+/**
+ * Append all the certificate names of a particular key name to the nameList.
+ * @param {Name} keyName The key name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default certificate name.
+ * If false, add only the non-default certificate names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IdentityStorage.prototype.getAllCertificateNamesOfKeyPromise = function
+  (keyName, nameList, isDefault, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.getAllCertificateNamesOfKeyPromise is not implemented"));
+};
+
+/**
+ * Append all the key names of a particular identity to the nameList.
+ * @param {Name} identityName The identity name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default key name. If false,
+ * add only the non-default key names.
+ * @throws Error If getAllKeyNamesOfIdentityPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.getAllKeyNamesOfIdentity = function
+  (identityName, nameList, isDefault)
+{
+  return SyncPromise.getValue
+    (this.getAllKeyNamesOfIdentityPromise(identityName, nameList, isDefault, true));
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default
+ * identity is set.
+ */
+IdentityStorage.prototype.setDefaultIdentityPromise = function
+  (identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.setDefaultIdentityPromise is not implemented"));
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @throws Error If setDefaultIdentityPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+IdentityStorage.prototype.setDefaultIdentity = function(identityName)
+{
+  return SyncPromise.getValue
+    (this.setDefaultIdentityPromise(identityName, true));
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default key
+ * name is set.
+ */
+IdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
+  (keyName, identityNameCheck, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.setDefaultKeyNameForIdentityPromise is not implemented"));
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @throws Error If setDefaultKeyNameForIdentityPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.setDefaultKeyNameForIdentity = function
+  (keyName, identityNameCheck)
+{
+  return SyncPromise.getValue
+    (this.setDefaultKeyNameForIdentityPromise(keyName, identityNameCheck, true));
+};
+
+/**
+ * Set the default key name for the specified identity.
+ * @param {Name} keyName The key name.
+ * @param {Name} certificateName The certificate name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default
+ * certificate name is set.
+ */
+IdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
+  (keyName, certificateName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.setDefaultCertificateNameForKeyPromise is not implemented"));
+};
+
+/**
+ * Set the default key name for the specified identity.
+ * @param {Name} keyName The key name.
+ * @param {Name} certificateName The certificate name.
+ * @throws Error If setDefaultCertificateNameForKeyPromise doesn't return a
+ * SyncPromise which is already fulfilled.
+ */
+IdentityStorage.prototype.setDefaultCertificateNameForKey = function
+  (keyName, certificateName)
+{
+  return SyncPromise.getValue
+    (this.setDefaultCertificateNameForKeyPromise(keyName, certificateName, true));
+};
+
+/**
+ * Get the certificate of the default identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the requested
+ * IdentityCertificate or null if not found.
+ */
+IdentityStorage.prototype.getDefaultCertificatePromise = function(useSync)
+{
+  var thisStorage = this;
+  return this.getDefaultIdentityPromise(useSync)
+  .then(function(identityName) {
+    return thisStorage.getDefaultCertificateNameForIdentityPromise
+      (identityName, useSync);
+  }, function(ex) {
+    // The default is not defined.
+    return SyncPromise.resolve(null);
+  })
+  .then(function(certName) {
+    if (certName == null)
+      return SyncPromise.resolve(null);
+
+    return thisStorage.getCertificatePromise(certName, useSync);
+  });
+};
+
+/**
+ * Get the certificate of the default identity.
+ * @return {IdentityCertificate} The requested certificate.  If not found,
+ * return null.
+ * @throws Error If getDefaultCertificatePromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.getDefaultCertificate = function()
+{
+  return SyncPromise.getValue
+    (this.getDefaultCertificatePromise(true));
+};
+
+/*****************************************
+ *            Delete Methods             *
+ *****************************************/
+
+/**
+ * Delete a certificate.
+ * @param {Name} certificateName The certificate name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the certificate
+ * info is deleted.
+ */
+IdentityStorage.prototype.deleteCertificateInfoPromise = function
+  (certificateName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.deleteCertificateInfoPromise is not implemented"));
+};
+
+/**
+ * Delete a certificate.
+ * @param {Name} certificateName The certificate name.
+ * @throws Error If deleteCertificateInfoPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.deleteCertificateInfo = function(certificateName)
+{
+  return SyncPromise.getValue
+    (this.deleteCertificateInfoPromise(certificateName, true));
+};
+
+/**
+ * Delete a public key and related certificates.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the public key
+ * info is deleted.
+ */
+IdentityStorage.prototype.deletePublicKeyInfoPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject
+    (new Error("IdentityStorage.deletePublicKeyInfoPromise is not implemented"));
+};
+
+/**
+ * Delete a public key and related certificates.
+ * @param {Name} keyName The key name.
+ * @throws Error If deletePublicKeyInfoPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.deletePublicKeyInfo = function(keyName)
+{
+  return SyncPromise.getValue
+    (this.deletePublicKeyInfoPromise(keyName, true));
+};
+
+/**
+ * Delete an identity and related public keys and certificates.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the identity info
+ * is deleted.
+ */
+IdentityStorage.prototype.deleteIdentityInfoPromise = function
+  (identityName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("IdentityStorage.deleteIdentityInfoPromise is not implemented"));
+};
+
+/**
+ * Delete an identity and related public keys and certificates.
+ * @param {Name} identityName The identity name.
+ * @throws Error If deleteIdentityInfoPromise doesn't return a SyncPromise
+ * which is already fulfilled.
+ */
+IdentityStorage.prototype.deleteIdentityInfo = function(identityName)
+{
+  return SyncPromise.getValue
+    (this.deleteIdentityInfoPromise(identityName, true));
+};
+
+// Track the lastTimestamp so that each timestamp is unique.
+IdentityStorage.lastTimestamp = Math.floor(new Date().getTime() / 1000.0);
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Don't require modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbIdentityStorage extends IdentityStorage and implements its methods
+ * to store identity, public key and certificate objects using the browser's
+ * IndexedDB service.
+ * @constructor
+ */
+var IndexedDbIdentityStorage = function IndexedDbIdentityStorage()
+{
+  IdentityStorage.call(this);
+
+  this.database = new Dexie("ndnsec-public-info");
+  // The database schema imitates MemoryIdentityStorage.
+  this.database.version(1).stores({
+    // A table for global values. It currently only has the defaultIdentityUri.
+    // "key" is the key like "defaultIdentityUri" // string
+    // "value" is the value. For "defaultIdentityUri" the value is the
+    //         default identity name URI, or absent if not defined. // string
+    globals: "key",
+
+    // "identityNameUri" is the identity name URI          // string
+    // "defaultKeyUri" is the default key name URI or null // string
+    identity: "identityNameUri",
+
+    // "keyNameUri" is the key name URI                             // string
+    // "keyType" is the type of the public key            // number from KeyType
+    // "keyDer" is the public key DER                               // Uint8Array
+    // "defaultCertificateUri" is the default cert name URI or null // string
+    publicKey: "keyNameUri",
+
+    // "certificateNameUri" is the certificate name URI // string
+    // "encoding" is the certificate wire encoding      // Uint8Array
+    certificate: "certificateNameUri"
+  });
+  this.database.open();
+};
+
+IndexedDbIdentityStorage.prototype = new IdentityStorage();
+IndexedDbIdentityStorage.prototype.name = "IndexedDbIdentityStorage";
+
+/**
+ * Check if the specified identity already exists.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns true if the identity exists.
+ */
+IndexedDbIdentityStorage.prototype.doesIdentityExistPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.doesIdentityExistPromise is only supported for async")));
+
+  return this.database.identity.where("identityNameUri").equals
+    (identityName.toUri())
+  .count()
+  .then(function(count) {
+    return Promise.resolve(count > 0);
+  });
+};
+
+/**
+ * Add a new identity. Do nothing if the identity already exists.
+ * @param {Name} identityName The identity name to be added.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the identity is added.
+ */
+IndexedDbIdentityStorage.prototype.addIdentityPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.addIdentityPromise is only supported for async")));
+
+  var thisStorage = this;
+  return this.doesIdentityExistPromise(identityName)
+  .then(function(exists) {
+    if (exists)
+      // Do nothing.
+      return Promise.resolve();
+
+    return thisStorage.database.identity.put
+      ({ identityNameUri: identityName.toUri(), defaultKeyUri: null });
+  });
+};
+
+/**
+ * Check if the specified key already exists.
+ * @param {Name} keyName The name of the key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns true if the key exists.
+ */
+IndexedDbIdentityStorage.prototype.doesKeyExistPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.doesKeyExistPromise is only supported for async")));
+
+  return this.database.publicKey.where("keyNameUri").equals(keyName.toUri())
+  .count()
+  .then(function(count) {
+    return Promise.resolve(count > 0);
+  });
+};
+
+/**
+ * Add a public key to the identity storage. Also call addIdentity to ensure
+ * that the identityName for the key exists. However, if the key already
+   * exists, do nothing.
+ * @param {Name} keyName The name of the public key to be added.
+ * @param {number} keyType Type of the public key to be added from KeyType, such
+ * as KeyType.RSA..
+ * @param {Blob} publicKeyDer A blob of the public key DER to be added.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when complete.
+ */
+IndexedDbIdentityStorage.prototype.addKeyPromise = function
+  (keyName, keyType, publicKeyDer, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.addKeyPromise is only supported for async")));
+
+  if (keyName.size() === 0)
+    return Promise.resolve();
+
+  var thisStorage = this;
+  return this.doesKeyExistPromise(keyName)
+  .then(function(exists) {
+    if (exists)
+      return Promise.resolve();
+
+    var identityName = keyName.getPrefix(-1);
+    return thisStorage.addIdentityPromise(identityName)
+    .then(function() {
+      return thisStorage.database.publicKey.put
+        ({ keyNameUri: keyName.toUri(), keyType: keyType,
+           keyDer: new Blob(publicKeyDer, true).buf(),
+           defaultCertificate: null });
+    });
+  });
+};
+
+/**
+ * Get the public key DER blob from the identity storage.
+ * @param {Name} keyName The name of the requested public key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the DER Blob, or a promise rejected
+ * with SecurityException if the key doesn't exist.
+ */
+IndexedDbIdentityStorage.prototype.getKeyPromise = function(keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getKeyPromise is only supported for async")));
+
+  if (keyName.size() === 0)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage::getKeyPromise: Empty keyName")));
+
+  return this.database.publicKey.get(keyName.toUri())
+  .then(function(publicKeyEntry) {
+    if (publicKeyEntry)
+      return Promise.resolve(new Blob(publicKeyEntry.keyDer));
+    else
+      return Promise.reject(new SecurityException(new Error
+        ("IndexedDbIdentityStorage::getKeyPromise: The key does not exist")));
+  });
+};
+
+/**
+ * Check if the specified certificate already exists.
+ * @param {Name} certificateName The name of the certificate.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns true if the certificate exists.
+ */
+IndexedDbIdentityStorage.prototype.doesCertificateExistPromise = function
+  (certificateName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.doesCertificateExistPromise is only supported for async")));
+
+  return this.database.certificate.where("certificateNameUri").equals
+    (certificateName.toUri())
+  .count()
+  .then(function(count) {
+    return Promise.resolve(count > 0);
+  });
+};
+
+/**
+ * Add a certificate to the identity storage. Also call addKey to ensure that
+ * the certificate key exists. If the certificate is already installed, don't
+ * replace it.
+ * @param {IdentityCertificate} certificate The certificate to be added.  This
+ * makes a copy of the certificate.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when finished.
+ */
+IndexedDbIdentityStorage.prototype.addCertificatePromise = function
+  (certificate, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.addCertificatePromise is only supported for async")));
+
+  var certificateName = certificate.getName();
+  var keyName = certificate.getPublicKeyName();
+
+  var thisStorage = this;
+  return this.addKeyPromise
+    (keyName, certificate.getPublicKeyInfo().getKeyType(),
+     certificate.getPublicKeyInfo().getKeyDer(), useSync)
+  .then(function() {
+    return thisStorage.doesCertificateExistPromise(certificateName);
+  })
+  .then(function(exists) {
+    if (exists)
+      return Promise.resolve();
+
+    // Insert the certificate.
+    // wireEncode returns the cached encoding if available.
+    return thisStorage.database.certificate.put
+      ({ certificateNameUri: certificateName.toUri(),
+         encoding: certificate.wireEncode().buf() });
+  });
+};
+
+/**
+ * Get a certificate from the identity storage.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the requested
+ * IdentityCertificate, or a promise rejected with SecurityException if the
+ * certificate doesn't exist.
+ */
+IndexedDbIdentityStorage.prototype.getCertificatePromise = function
+  (certificateName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getCertificatePromise is only supported for async")));
+
+  return this.database.certificate.get(certificateName.toUri())
+  .then(function(certificateEntry) {
+    if (certificateEntry) {
+      var certificate = new IdentityCertificate();
+      try {
+        certificate.wireDecode(certificateEntry.encoding);
+      } catch (ex) {
+        return Promise.reject(new SecurityException(new Error
+          ("IndexedDbIdentityStorage::getCertificatePromise: The certificate cannot be decoded")));
+      }
+      return Promise.resolve(certificate);
     }
     else
-        interest.interestLifetime = 4000;   // default interest timeout value in milliseconds.
+      return Promise.reject(new SecurityException(new Error
+        ("IndexedDbIdentityStorage::getCertificatePromise: The certificate does not exist")));
+  });
+};
 
-	if (this.host == null || this.port == null) {
-        if (this.getHostAndPort == null)
-            console.log('ERROR: host OR port NOT SET');
-        else {
-            var thisNDN = this;
-            this.connectAndExecute
-                (function() { thisNDN.reconnectAndExpressInterest(interest, closure); });
+/*****************************************
+ *           Get/Set Default             *
+ *****************************************/
+
+/**
+ * Get the default identity.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the Name of default identity,
+ * or a promise rejected with SecurityException if the default identity is not
+ * set.
+ */
+IndexedDbIdentityStorage.prototype.getDefaultIdentityPromise = function(useSync)
+{
+  return this.database.globals.get("defaultIdentityUri")
+  .then(function(defaultIdentityEntry) {
+    if (defaultIdentityEntry)
+      return Promise.resolve(new Name(defaultIdentityEntry.value));
+    else
+      throw new SecurityException(new Error
+        ("IndexedDbIdentityStorage.getDefaultIdentity: The default identity is not defined"));
+  });
+};
+
+/**
+ * Get the default key name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the default key Name, or a
+ * promise rejected with SecurityException if the default key name for the
+ * identity is not set.
+ */
+IndexedDbIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getDefaultKeyNameForIdentityPromise is only supported for async")));
+
+  return this.database.identity.get(identityName.toUri())
+  .then(function(identityEntry) {
+    if (identityEntry) {
+      if (identityEntry.defaultKeyUri != null)
+        return Promise.resolve(new Name(identityEntry.defaultKeyUri));
+      else
+        throw new SecurityException(new Error("No default key set."));
+    }
+    else
+      throw new SecurityException(new Error("Identity not found."));
+  });
+};
+
+/**
+ * Get the default certificate name for the specified key.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns the default certificate Name,
+ * or a promise rejected with SecurityException if the default certificate name
+ * for the key name is not set.
+ */
+IndexedDbIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getDefaultCertificateNameForKeyPromise is only supported for async")));
+
+  return this.database.publicKey.get(keyName.toUri())
+  .then(function(publicKeyEntry) {
+    if (publicKeyEntry) {
+      if (publicKeyEntry.defaultCertificateUri != null)
+        return Promise.resolve(new Name(publicKeyEntry.defaultCertificateUri));
+      else
+        throw new SecurityException(new Error("No default certificate set."));
+    }
+    else
+      throw new SecurityException(new Error("Key not found."));
+  });
+};
+
+/**
+ * Append all the identity names to the nameList.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default identity name. If
+ * false, add only the non-default identity names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IndexedDbIdentityStorage.prototype.getAllIdentitiesPromise = function
+  (nameList, isDefault, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getAllIdentitiesPromise is only supported for async")));
+
+  var defaultIdentityName = null;
+  var thisStorage = this;
+  return this.getDefaultIdentityPromise()
+  .then(function(localDefaultIdentityName) {
+    defaultIdentityName = localDefaultIdentityName;
+    return SyncPromise.resolve();
+  }, function(err) {
+    // The default identity name was not found.
+    return SyncPromise.resolve();
+  })
+  .then(function() {
+    return thisStorage.database.identity.each(function(identityEntry) {
+      var identityName = new Name(identityEntry.identityNameUri);
+      var identityNameIsDefault =
+        (defaultIdentityName !== null && identityName.equals(defaultIdentityName));
+      if (isDefault && identityNameIsDefault)
+        nameList.push(identityName);
+      else if (!isDefault && !identityNameIsDefault)
+        nameList.push(identityName);
+    });
+  });
+};
+
+/**
+ * Append all the key names of a particular identity to the nameList.
+ * @param {Name} identityName The identity name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default key name. If false,
+ * add only the non-default key names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IndexedDbIdentityStorage.prototype.getAllKeyNamesOfIdentityPromise = function
+  (identityName, nameList, isDefault, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getAllKeyNamesOfIdentityPromise is only supported for async")));
+
+  var defaultKeyName = null;
+  var thisStorage = this;
+  return this.getDefaultKeyNameForIdentityPromise(identityName)
+  .then(function(localDefaultKeyName) {
+    defaultKeyName = localDefaultKeyName;
+    return SyncPromise.resolve();
+  }, function(err) {
+    // The default key name was not found.
+    return SyncPromise.resolve();
+  })
+  .then(function() {
+    // Iterate through each publicKey a to find ones that match identityName.
+    // This is a little inefficient, but we don't expect the in-browser
+    // database to be very big, we don't expect to use this function often (for
+    // deleting an identity), and this is simpler than complicating the database
+    // schema to store the identityName with each publicKey.
+    return thisStorage.database.publicKey.each(function(publicKeyEntry) {
+      var keyName = new Name(publicKeyEntry.keyNameUri);
+      var keyIdentityName = keyName.getPrefix(-1);
+
+      if (keyIdentityName.equals(identityName)) {
+        var keyNameIsDefault =
+          (defaultKeyName !== null && keyName.equals(defaultKeyName));
+        if (isDefault && keyNameIsDefault)
+          nameList.push(keyName);
+        else if (!isDefault && !keyNameIsDefault)
+          nameList.push(keyName);
+      }
+    });
+  });
+};
+
+/**
+ * Append all the certificate names of a particular key name to the nameList.
+ * @param {Name} keyName The key name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default certificate name.
+ * If false, add only the non-default certificate names.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the names are added to
+ * nameList.
+ */
+IndexedDbIdentityStorage.prototype.getAllCertificateNamesOfKeyPromise = function
+  (keyName, nameList, isDefault, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.getAllCertificateNamesOfKeyPromise is only supported for async")));
+
+  var defaultCertificateName = null;
+  var thisStorage = this;
+  return this.getDefaultCertificateNameForKeyPromise(keyName)
+  .then(function(localDefaultCertificateName) {
+    defaultCertificateName = localDefaultCertificateName;
+    return SyncPromise.resolve();
+  }, function(err) {
+    // The default certificate name was not found.
+    return SyncPromise.resolve();
+  })
+  .then(function() {
+    // Iterate through each certificate record a to find ones that match keyName.
+    // This is a little inefficient, but we don't expect the in-browser
+    // database to be very big, we don't expect to use this function often (for
+    // deleting an identity), and this is simpler than complicating the database
+    // schema to store the keyName with each certificate record.
+    return thisStorage.database.certificate.each(function(certificateEntry) {
+      var certificateName = new Name(certificateEntry.certificateNameUri);
+      var certificateKeyName = IdentityCertificate.certificateNameToPublicKeyName
+        (certificateName);
+
+      if (certificateKeyName.equals(keyName)) {
+        var certificateNameIsDefault =
+          (defaultCertificateName !== null &&
+           certificateName.equals(defaultCertificateName));
+        if (isDefault && certificateNameIsDefault)
+          nameList.push(certificateName);
+        else if (!isDefault && !certificateNameIsDefault)
+          nameList.push(certificateName);
+      }
+    });
+  });
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the default identity is set.
+ */
+IndexedDbIdentityStorage.prototype.setDefaultIdentityPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.setDefaultIdentityPromise is only supported for async")));
+
+  var thisStorage = this;
+  return this.doesIdentityExistPromise(identityName)
+  .then(function(exists) {
+    if (exists)
+      return thisStorage.database.globals.put
+        ({ key: "defaultIdentityUri", value: identityName.toUri() });
+    else
+      // The identity doesn't exist, so clear the default.
+      return thisStorage.database.globals.delete("defaultIdentityUri");
+  });
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the default key name is
+ * set.
+ */
+IndexedDbIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
+  (keyName, identityNameCheck, useSync)
+{
+  useSync = (typeof identityNameCheck === "boolean") ? identityNameCheck : useSync;
+  identityNameCheck = (identityNameCheck instanceof Name) ? identityNameCheck : null;
+
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.setDefaultKeyNameForIdentityPromise is only supported for async")));
+
+  var identityName = keyName.getPrefix(-1);
+
+  if (identityNameCheck != null && identityNameCheck.size() > 0 &&
+      !identityNameCheck.equals(identityName))
+    return Promise.reject(new SecurityException(new Error
+      ("The specified identity name does not match the key name")));
+
+  // update does nothing if the identityName doesn't exist.
+  return this.database.identity.update
+    (identityName.toUri(), { defaultKeyUri: keyName.toUri() });
+};
+
+/**
+ * Set the default key name for the specified identity.
+ * @param {Name} keyName The key name.
+ * @param {Name} certificateName The certificate name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the default certificate
+ * name is set.
+ */
+IndexedDbIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
+  (keyName, certificateName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.setDefaultCertificateNameForKeyPromise is only supported for async")));
+
+  // update does nothing if the keyName doesn't exist.
+  return this.database.publicKey.update
+    (keyName.toUri(), { defaultCertificateUri: certificateName.toUri() });
+};
+
+/*****************************************
+ *            Delete Methods             *
+ *****************************************/
+
+/**
+ * Delete a certificate.
+ * @param {Name} certificateName The certificate name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the certificate info is
+ * deleted.
+ */
+IndexedDbIdentityStorage.prototype.deleteCertificateInfoPromise = function
+  (certificateName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.deleteCertificateInfoPromise is only supported for async")));
+
+  if (certificateName.size() === 0)
+    return Promise.resolve();
+
+  return this.database.certificate.delete(certificateName.toUri());
+};
+
+/**
+ * Delete a public key and related certificates.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the public key info is
+ * deleted.
+ */
+IndexedDbIdentityStorage.prototype.deletePublicKeyInfoPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.deletePublicKeyInfoPromise is only supported for async")));
+
+  if (keyName.size() === 0)
+    return Promise.resolve();
+
+  var thisStorage = this;
+  return this.database.publicKey.delete(keyName.toUri())
+  .then(function() {
+    // Iterate through each certificate to find ones that match keyName. This is
+    // a little inefficient, but we don't expect the in-browswer database to be
+    // very big, we don't expect to delete often, and this is simpler than
+    // complicating the database schema to store the keyName with each certificate.
+    return thisStorage.database.certificate.each(function(certificateEntry) {
+      if (IdentityCertificate.certificateNameToPublicKeyName
+          (new Name(certificateEntry.certificateNameUri)).equals(keyName))
+        thisStorage.database.certificate.delete
+          (certificateEntry.certificateNameUri);
+    });
+  });
+};
+
+/**
+ * Delete an identity and related public keys and certificates.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which fulfills when the identity info is
+ * deleted.
+ */
+IndexedDbIdentityStorage.prototype.deleteIdentityInfoPromise = function
+  (identityName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbIdentityStorage.deleteIdentityInfoPromise is only supported for async")));
+
+  var thisStorage = this;
+  return this.database.identity.delete(identityName.toUri())
+  // Iterate through each publicKey and certificate to find ones that match
+  // identityName. This is a little inefficient, but we don't expect the
+  // in-browswer database to be very big, we don't expect to delete often, and
+  // this is simpler than complicating the database schema to store the
+  // identityName with each publicKey and certificate.
+  .then(function() {
+    return thisStorage.database.publicKey.each(function(publicKeyEntry) {
+      var keyIdentityName = new Name(publicKeyEntry.keyNameUri).getPrefix(-1);
+      if (keyIdentityName.equals(identityName))
+        thisStorage.database.publicKey.delete(publicKeyEntry.keyNameUri);
+    });
+  })
+  .then(function() {
+    return thisStorage.database.certificate.each(function(certificateEntry) {
+      var certificateKeyName = IdentityCertificate.certificateNameToPublicKeyName
+        (new Name(certificateEntry.certificateNameUri));
+      var certificateIdentityName = certificateKeyName.getPrefix(-1);
+      if (certificateIdentityName.equals(identityName))
+        thisStorage.database.certificate.delete
+          (certificateEntry.certificateNameUri);
+    });
+  });
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var IdentityStorage = require('./identity-storage.js').IdentityStorage;
+
+/**
+ * MemoryIdentityStorage extends IdentityStorage and implements its methods to
+ * store identity, public key and certificate objects in memory. The application
+ * must get the objects through its own means and add the objects to the
+ * MemoryIdentityStorage object. To use permanent file-based storage, see
+ * BasicIdentityStorage.
+ * @constructor
+ */
+var MemoryIdentityStorage = function MemoryIdentityStorage()
+{
+  // Call the base constructor.
+  IdentityStorage.call(this);
+
+  // The map key is the identityName.toUri(). The value is the object
+  //   {defaultKey // Name
+  //   }.
+  this.identityStore = {};
+  // The default identity in identityStore, or "" if not defined.
+  this.defaultIdentity = "";
+  // The key is the keyName.toUri(). The value is the object
+  //  {keyType, // number from KeyType
+  //   keyDer   // Blob
+  //   defaultCertificate // Name
+  //  }.
+  this.keyStore = {};
+  // The key is the key is the certificateName.toUri(). The value is the
+  //   encoded certificate.
+  this.certificateStore = {};
+};
+
+MemoryIdentityStorage.prototype = new IdentityStorage();
+MemoryIdentityStorage.prototype.name = "MemoryIdentityStorage";
+
+exports.MemoryIdentityStorage = MemoryIdentityStorage;
+/**
+ * Check if the specified identity already exists.
+ * @param {Name} identityName The identity name.
+ * @return {SyncPromise} A promise which returns true if the identity exists.
+ */
+MemoryIdentityStorage.prototype.doesIdentityExistPromise = function(identityName)
+{
+  return SyncPromise.resolve
+    (this.identityStore[identityName.toUri()] !== undefined);
+};
+
+/**
+ * Add a new identity. Do nothing if the identity already exists.
+ * @param {Name} identityName The identity name to be added.
+ * @return {SyncPromise} A promise which fulfills when the identity is added.
+ */
+MemoryIdentityStorage.prototype.addIdentityPromise = function(identityName)
+{
+  var identityUri = identityName.toUri();
+  if (this.identityStore[identityUri] === undefined)
+    this.identityStore[identityUri] = { defaultKey: null };
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Check if the specified key already exists.
+ * @param {Name} keyName The name of the key.
+ * @return {SyncPromise} A promise which returns true if the key exists.
+ */
+MemoryIdentityStorage.prototype.doesKeyExistPromise = function(keyName)
+{
+  return SyncPromise.resolve(this.keyStore[keyName.toUri()] !== undefined);
+};
+
+/**
+ * Add a public key to the identity storage. Also call addIdentity to ensure
+ * that the identityName for the key exists. However, if the key already
+ * exists, do nothing.
+ * @param {Name} keyName The name of the public key to be added.
+ * @param {number} keyType Type of the public key to be added from KeyType, such
+ * as KeyType.RSA..
+ * @param {Blob} publicKeyDer A blob of the public key DER to be added.
+ * @return {SyncPromise} A promise which fulfills when complete.
+ */
+MemoryIdentityStorage.prototype.addKeyPromise = function
+  (keyName, keyType, publicKeyDer)
+{
+  if (keyName.size() === 0)
+    return SyncPromise.resolve();
+
+  if (this.doesKeyExist(keyName))
+    return SyncPromise.resolve();
+
+  var identityName = keyName.getSubName(0, keyName.size() - 1);
+
+  this.addIdentity(identityName);
+
+  this.keyStore[keyName.toUri()] =
+    { keyType: keyType, keyDer: new Blob(publicKeyDer), defaultCertificate: null };
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Get the public key DER blob from the identity storage.
+ * @param {Name} keyName The name of the requested public key.
+ * @return {SyncPromise} A promise which returns the DER Blob, or a promise
+ * rejected with SecurityException if the key doesn't exist.
+ */
+MemoryIdentityStorage.prototype.getKeyPromise = function(keyName)
+{
+  if (keyName.size() === 0)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage::getKeyPromise: Empty keyName")));
+
+  var keyNameUri = keyName.toUri();
+  var entry = this.keyStore[keyNameUri];
+  if (entry === undefined)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage::getKeyPromise: The key does not exist")));
+
+  return SyncPromise.resolve(entry.keyDer);
+};
+
+/**
+ * Check if the specified certificate already exists.
+ * @param {Name} certificateName The name of the certificate.
+ * @return {SyncPromise} A promise which returns true if the certificate exists.
+ */
+MemoryIdentityStorage.prototype.doesCertificateExistPromise = function
+  (certificateName)
+{
+  return SyncPromise.resolve
+    (this.certificateStore[certificateName.toUri()] !== undefined);
+};
+
+/**
+ * Add a certificate to the identity storage. Also call addKey to ensure that
+ * the certificate key exists. If the certificate is already installed, don't
+ * replace it.
+ * @param {IdentityCertificate} certificate The certificate to be added.  This
+ * makes a copy of the certificate.
+ * @return {SyncPromise} A promise which fulfills when finished.
+ */
+MemoryIdentityStorage.prototype.addCertificatePromise = function(certificate)
+{
+  var certificateName = certificate.getName();
+  var keyName = certificate.getPublicKeyName();
+
+  this.addKey(keyName, certificate.getPublicKeyInfo().getKeyType(),
+         certificate.getPublicKeyInfo().getKeyDer());
+
+  if (this.doesCertificateExist(certificateName))
+    return SyncPromise.resolve();
+
+  // Insert the certificate.
+  // wireEncode returns the cached encoding if available.
+  this.certificateStore[certificateName.toUri()] = certificate.wireEncode();
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Get a certificate from the identity storage.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @return {SyncPromise} A promise which returns the requested
+ * IdentityCertificate, or a promise rejected with SecurityException if the
+ * certificate doesn't exist.
+ */
+MemoryIdentityStorage.prototype.getCertificatePromise = function
+  (certificateName)
+{
+  var certificateNameUri = certificateName.toUri();
+  if (this.certificateStore[certificateNameUri] === undefined)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage::getCertificatePromise: The certificate does not exist")));
+
+  var certificate = new IdentityCertificate();
+  try {
+    certificate.wireDecode(this.certificateStore[certificateNameUri]);
+  } catch (ex) {
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage::getCertificatePromise: The certificate cannot be decoded")));
+  }
+  return SyncPromise.resolve(certificate);
+};
+
+/**
+ * Get the TPM locator associated with this storage.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise|SyncPromise} A promise which returns the TPM locator, or a
+ * promise rejected with SecurityException if the TPM locator doesn't exist.
+ */
+IdentityStorage.prototype.getTpmLocatorPromise = function(useSync)
+{
+  return SyncPromise.resolve("tpm-memory:");
+};
+
+/*****************************************
+ *           Get/Set Default             *
+ *****************************************/
+
+/**
+ * Get the default identity.
+ * @return {SyncPromise} A promise which returns the Name of default identity,
+ * or a promise rejected with SecurityException if the default identity is not
+ * set.
+ */
+MemoryIdentityStorage.prototype.getDefaultIdentityPromise = function()
+{
+  if (this.defaultIdentity.length === 0)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryIdentityStorage.getDefaultIdentity: The default identity is not defined")));
+
+  return SyncPromise.resolve(new Name(this.defaultIdentity));
+};
+
+/**
+ * Get the default key name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @return {SyncPromise} A promise which returns the default key Name, or a
+ * promise rejected with SecurityException if the default key name for the
+ * identity is not set.
+ */
+MemoryIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
+  (identityName)
+{
+  var identityUri = identityName.toUri();
+  if (this.identityStore[identityUri] !== undefined) {
+    if (this.identityStore[identityUri].defaultKey != null)
+      return SyncPromise.resolve(this.identityStore[identityUri].defaultKey);
+    else
+      return SyncPromise.reject(new SecurityException(new Error
+        ("No default key set.")));
+  }
+  else
+    return SyncPromise.reject(new SecurityException(new Error("Identity not found.")));
+};
+
+/**
+ * Get the default certificate name for the specified key.
+ * @param {Name} keyName The key name.
+ * @return {SyncPromise} A promise which returns the default certificate Name,
+ * or a promise rejected with SecurityException if the default certificate name
+ * for the key name is not set.
+ */
+MemoryIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
+  (keyName)
+{
+  var keyUri = keyName.toUri();
+  if (this.keyStore[keyUri] !== undefined) {
+    if (this.keyStore[keyUri].defaultCertificate != null)
+      return SyncPromise.resolve(this.keyStore[keyUri].defaultCertificate);
+    else
+      return SyncPromise.reject(new SecurityException(new Error
+        ("No default certificate set.")));
+  }
+  else
+    return SyncPromise.reject(new SecurityException(new Error("Key not found.")));
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @return {SyncPromise} A promise which fulfills when the default identity is set.
+ */
+MemoryIdentityStorage.prototype.setDefaultIdentityPromise = function
+  (identityName)
+{
+  var identityUri = identityName.toUri();
+  if (this.identityStore[identityUri] !== undefined)
+    this.defaultIdentity = identityUri;
+  else
+    // The identity doesn't exist, so clear the default.
+    this.defaultIdentity = "";
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @return {SyncPromise} A promise which fulfills when the default key name is
+ * set.
+ */
+MemoryIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
+  (keyName, identityNameCheck)
+{
+  identityNameCheck = (identityNameCheck instanceof Name) ? identityNameCheck : null;
+
+  var identityName = keyName.getPrefix(-1);
+
+  if (identityNameCheck != null && identityNameCheck.size() > 0 &&
+      !identityNameCheck.equals(identityName))
+    return SyncPromise.reject(new SecurityException(new Error
+      ("The specified identity name does not match the key name")));
+
+  var identityUri = identityName.toUri();
+  if (this.identityStore[identityUri] !== undefined)
+    this.identityStore[identityUri].defaultKey = new Name(keyName);
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Set the default key name for the specified identity.
+ * @param {Name} keyName The key name.
+ * @param {Name} certificateName The certificate name.
+ * @return {SyncPromise} A promise which fulfills when the default certificate
+ * name is set.
+ */
+MemoryIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
+  (keyName, certificateName)
+{
+  var keyUri = keyName.toUri();
+  if (this.keyStore[keyUri] !== undefined)
+    this.keyStore[keyUri].defaultCertificate = new Name(certificateName);
+
+  return SyncPromise.resolve();
+};
+
+/*****************************************
+ *            Delete Methods             *
+ *****************************************/
+
+/**
+ * Delete a certificate.
+ * @param {Name} certificateName The certificate name.
+ * @return {SyncPromise} A promise which fulfills when the certificate
+ * info is deleted.
+ */
+MemoryIdentityStorage.prototype.deleteCertificateInfoPromise = function
+  (certificateName)
+{
+  return SyncPromise.reject(new Error
+    ("MemoryIdentityStorage.deleteCertificateInfoPromise is not implemented"));
+};
+
+/**
+ * Delete a public key and related certificates.
+ * @param {Name} keyName The key name.
+ * @return {SyncPromise} A promise which fulfills when the public key info is
+ * deleted.
+ */
+MemoryIdentityStorage.prototype.deletePublicKeyInfoPromise = function(keyName)
+{
+  return SyncPromise.reject(new Error
+    ("MemoryIdentityStorage.deletePublicKeyInfoPromise is not implemented"));
+};
+
+/**
+ * Delete an identity and related public keys and certificates.
+ * @param {Name} identity The identity name.
+ * @return {SyncPromise} A promise which fulfills when the identity info is
+ * deleted.
+ */
+MemoryIdentityStorage.prototype.deleteIdentityInfoPromise = function(identity)
+{
+  return SyncPromise.reject(new Error
+    ("MemoryIdentityStorage.deleteIdentityInfoPromise is not implemented"));
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode;
+
+/**
+ * PrivateKeyStorage is an abstract class which declares methods for working
+ * with a private key storage. You should use a subclass.
+ * @constructor
+ */
+var PrivateKeyStorage = function PrivateKeyStorage()
+{
+};
+
+exports.PrivateKeyStorage = PrivateKeyStorage;
+
+/**
+ * Generate a pair of asymmetric keys.
+ * @param {Name} keyName The name of the key pair.
+ * @param {KeyParams} params The parameters of the key.
+ * @param {boolean} (optional) useSync If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the pair is
+ * generated.
+ */
+PrivateKeyStorage.prototype.generateKeyPairPromise = function
+  (keyName, params, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("PrivateKeyStorage.generateKeyPairPromise is not implemented"));
+};
+
+/**
+ * Generate a pair of asymmetric keys.
+ * @param {Name} keyName The name of the key pair.
+ * @param {KeyParams} params The parameters of the key.
+ * @throws Error If generateKeyPairPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+PrivateKeyStorage.prototype.generateKeyPair = function(keyName, params)
+{
+  SyncPromise.getValue(this.generateKeyPairPromise(keyName, params, true));
+};
+
+/**
+ * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
+ * @param {Name} keyName The name of the key pair.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key pair is
+ * deleted.
+ */
+PrivateKeyStorage.prototype.deleteKeyPairPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("PrivateKeyStorage.deleteKeyPairPromise is not implemented"));
+};
+
+/**
+ * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
+ * @param {Name} keyName The name of the key pair.
+ * @throws Error If deleteKeyPairPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+PrivateKeyStorage.prototype.deleteKeyPair = function(keyName)
+{
+  SyncPromise.getValue(this.deleteKeyPairPromise(keyName, true));
+};
+
+/**
+ * Get the public key
+ * @param {Name} keyName The name of public key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the PublicKey.
+ */
+PrivateKeyStorage.prototype.getPublicKeyPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("PrivateKeyStorage.getPublicKeyPromise is not implemented"));
+};
+
+/**
+ * Get the public key
+ * @param {Name} keyName The name of public key.
+ * @return {PublicKey} The public key.
+ * @throws Error If getPublicKeyPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+PrivateKeyStorage.prototype.getPublicKey = function(keyName)
+{
+  return SyncPromise.getValue(this.getPublicKeyPromise(keyName, true));
+};
+
+/**
+ * Fetch the private key for keyName and sign the data to produce a signature Blob.
+ * @param {Buffer} data Pointer to the input byte array.
+ * @param {Name} keyName The name of the signing key.
+ * @param {number} digestAlgorithm (optional) The digest algorithm from
+ * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
+ * DigestAlgorithm.SHA256.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the signature Blob.
+ */
+PrivateKeyStorage.prototype.signPromise = function
+  (data, keyName, digestAlgorithm, useSync)
+{
+  return SyncPromise.reject(new Error("PrivateKeyStorage.sign is not implemented"));
+};
+
+/**
+ * Fetch the private key for keyName and sign the data to produce a signature Blob.
+ * @param {Buffer} data Pointer to the input byte array.
+ * @param {Name} keyName The name of the signing key.
+ * @param {number} digestAlgorithm (optional) The digest algorithm from
+ * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
+ * DigestAlgorithm.SHA256.
+ * @return {Blob} The signature Blob.
+ * @throws Error If signPromise doesn't return a SyncPromise which is already
+ * fulfilled.
+ */
+PrivateKeyStorage.prototype.sign = function(data, keyName, digestAlgorithm)
+{
+  return SyncPromise.getValue
+    (this.signPromise(data, keyName, digestAlgorithm, true));
+};
+
+/**
+ * Decrypt data.
+ * @param {Name} keyName The name of the decrypting key.
+ * @param {Buffer} data The byte to be decrypted.
+ * @param {boolean} isSymmetric (optional) If true symmetric encryption is used,
+ * otherwise asymmetric encryption is used. If omitted, use asymmetric
+ * encryption.
+ * @return {Blob} The decrypted data.
+ */
+PrivateKeyStorage.prototype.decrypt = function(keyName, data, isSymmetric)
+{
+  throw new Error("PrivateKeyStorage.decrypt is not implemented");
+};
+
+/**
+ * Encrypt data.
+ * @param {Name} keyName The name of the encrypting key.
+ * @param {Buffer} data The byte to be encrypted.
+ * @param {boolean} isSymmetric (optional) If true symmetric encryption is used,
+ * otherwise asymmetric encryption is used. If omitted, use asymmetric
+ * encryption.
+ * @return {Blob} The encrypted data.
+ */
+PrivateKeyStorage.prototype.encrypt = function(keyName, data, isSymmetric)
+{
+  throw new Error("PrivateKeyStorage.encrypt is not implemented");
+};
+
+/**
+ * @brief Generate a symmetric key.
+ * @param {Name} keyName The name of the key.
+ * @param {KeyParams} params The parameters of the key.
+ */
+PrivateKeyStorage.prototype.generateKey = function(keyName, params)
+{
+  throw new Error("PrivateKeyStorage.generateKey is not implemented");
+};
+
+/**
+ * Check if a particular key exists.
+ * @param {Name} keyName The name of the key.
+ * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
+ * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns true if the key exists.
+ */
+PrivateKeyStorage.prototype.doesKeyExistPromise = function
+  (keyName, keyClass, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("PrivateKeyStorage.doesKeyExist is not implemented"));
+};
+
+/**
+ * Check if a particular key exists.
+ * @param {Name} keyName The name of the key.
+ * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
+ * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
+ * @return {boolean} True if the key exists.
+ * @throws Error If doesKeyExistPromise doesn't return a SyncPromise which
+ * is already fulfilled.
+ */
+PrivateKeyStorage.prototype.doesKeyExist = function(keyName, keyClass)
+{
+  return SyncPromise.getValue(this.doesKeyExistPromise(keyName, keyClass, true));
+};
+
+/**
+ * Encode the private key to a PKCS #8 private key. We do this explicitly here
+ * to avoid linking to extra OpenSSL libraries.
+ * @param {Buffer} privateKeyDer The input private key DER.
+ * @param {OID} oid The OID of the privateKey.
+ * @param {DerNode} parameters The DerNode of the parameters for the OID.
+ * @return {Blob} The PKCS #8 private key DER.
+ */
+PrivateKeyStorage.encodePkcs8PrivateKey = function
+  (privateKeyDer, oid, parameters)
+{
+  var algorithmIdentifier = new DerNode.DerSequence();
+  algorithmIdentifier.addChild(new DerNode.DerOid(oid));
+  algorithmIdentifier.addChild(parameters);
+
+  var result = new DerNode.DerSequence();
+  result.addChild(new DerNode.DerInteger(0));
+  result.addChild(algorithmIdentifier);
+  result.addChild(new DerNode.DerOctetString(privateKeyDer));
+
+  return result.encode();
+};
+
+/**
+ * Encode the RSAKey private key as a PKCS #1 private key.
+ * @param {RSAKey} rsaKey The RSAKey private key.
+ * @return {Blob} The PKCS #1 private key DER.
+ */
+PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey = function(rsaKey)
+{
+  // Imitate KJUR getEncryptedPKCS5PEMFromRSAKey.
+  var result = new DerNode.DerSequence();
+
+  result.addChild(new DerNode.DerInteger(0));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.n)));
+  result.addChild(new DerNode.DerInteger(rsaKey.e));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.d)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.p)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.q)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.dmp1)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.dmq1)));
+  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.coeff)));
+
+  return result.encode();
+};
+
+/**
+ * Encode the public key values in the RSAKey private key as a
+ * SubjectPublicKeyInfo.
+ * @param {RSAKey} rsaKey The RSAKey private key with the public key values.
+ * @return {Blob} The SubjectPublicKeyInfo DER.
+ */
+PrivateKeyStorage.encodePublicKeyFromRSAKey = function(rsaKey)
+{
+  var rsaPublicKey = new DerNode.DerSequence();
+
+  rsaPublicKey.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.n)));
+  rsaPublicKey.addChild(new DerNode.DerInteger(rsaKey.e));
+
+  var algorithmIdentifier = new DerNode.DerSequence();
+  algorithmIdentifier.addChild
+    (new DerNode.DerOid(new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID)));
+  algorithmIdentifier.addChild(new DerNode.DerNull());
+
+  var result = new DerNode.DerSequence();
+
+  result.addChild(algorithmIdentifier);
+  result.addChild(new DerNode.DerBitString(rsaPublicKey.encode().buf(), 0));
+
+  return result.encode();
+};
+
+/**
+ * Convert a BigInteger to a Buffer.
+ * @param {BigInteger} bigInteger The BigInteger.
+ * @return {Buffer} The Buffer.
+ */
+PrivateKeyStorage.bigIntegerToBuffer = function(bigInteger)
+{
+  // Imitate KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex.
+  var hex = bigInteger.toString(16);
+  if (hex.substr(0, 1) == "-")
+    throw new Error
+      ("PrivateKeyStorage.bigIntegerToBuffer: Negative integers are not currently supported");
+
+  if (hex.length % 2 == 1)
+    // Odd number of characters.
+    hex = "0" + hex;
+  else {
+    if (! hex.match(/^[0-7]/))
+      // The first byte is >= 0x80, so prepend a zero to keep it positive.
+      hex = "00" + hex;
+  }
+
+  return new Buffer(hex, 'hex');
+};
+
+PrivateKeyStorage.RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1";
+PrivateKeyStorage.EC_ENCRYPTION_OID = "1.2.840.10045.2.1";
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var PublicKey = require('../certificate/public-key.js').PublicKey; /** @ignore */
+var KeyClass = require('../security-types.js').KeyClass; /** @ignore */
+var KeyType = require('../security-types').KeyType; /** @ignore */
+var DigestAlgorithm = require('../security-types.js').DigestAlgorithm; /** @ignore */
+var DataUtils = require('../../encoding/data-utils.js').DataUtils; /** @ignore */
+var PrivateKeyStorage = require('./private-key-storage.js').PrivateKeyStorage; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var OID = require('../../encoding/oid.js').OID; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
+var rsaKeygen = null;
+try {
+  // This should be installed with: sudo npm install rsa-keygen
+  rsaKeygen = require('rsa-keygen');
+}
+catch (e) {}
+
+/**
+ * MemoryPrivateKeyStorage class extends PrivateKeyStorage to implement private
+ * key storage in memory.
+ * @constructor
+ */
+var MemoryPrivateKeyStorage = function MemoryPrivateKeyStorage()
+{
+  // Call the base constructor.
+  PrivateKeyStorage.call(this);
+
+  // The key is the keyName.toUri(). The value is security.certificate.PublicKey.
+  this.publicKeyStore = {};
+  // The key is the keyName.toUri(). The value is the object
+  //  {keyType,     // number from KeyType
+  //   privateKey   // The PEM-encoded private key.
+  //  }.
+  this.privateKeyStore = {};
+};
+
+MemoryPrivateKeyStorage.prototype = new PrivateKeyStorage();
+MemoryPrivateKeyStorage.prototype.name = "MemoryPrivateKeyStorage";
+
+exports.MemoryPrivateKeyStorage = MemoryPrivateKeyStorage;
+
+/**
+ * Set the public key for the keyName.
+ * @param {Name} keyName The key name.
+ * @param {number} keyType The KeyType, such as KeyType.RSA.
+ * @param {Buffer} publicKeyDer The public key DER byte array.
+ */
+MemoryPrivateKeyStorage.prototype.setPublicKeyForKeyName = function
+  (keyName, keyType, publicKeyDer)
+{
+  this.publicKeyStore[keyName.toUri()] = new PublicKey
+    (new Blob(publicKeyDer, true));
+};
+
+/**
+ * Set the private key for the keyName.
+ * @param {Name} keyName The key name.
+ * @param {number} keyType The KeyType, such as KeyType.RSA.
+ * @param {Buffer} privateKeyDer The private key DER byte array.
+ */
+MemoryPrivateKeyStorage.prototype.setPrivateKeyForKeyName = function
+  (keyName, keyType, privateKeyDer)
+{
+  // Encode the DER as PEM.
+  var keyBase64 = privateKeyDer.toString('base64');
+  var keyPem;
+  if (keyType === KeyType.RSA) {
+    keyPem = "-----BEGIN RSA PRIVATE KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END RSA PRIVATE KEY-----";
+  }
+  else if (keyType === KeyType.ECDSA) {
+    keyPem = "-----BEGIN EC PRIVATE KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END EC PRIVATE KEY-----";
+  }
+  else
+    throw new SecurityException(new Error
+      ("MemoryPrivateKeyStorage: KeyType is not supported"));
+
+  this.privateKeyStore[keyName.toUri()] =
+    { keyType: keyType, privateKey: keyPem };
+};
+
+/**
+ * Set the public and private key for the keyName.
+ * @param {Name} keyName The key name.
+ * @param {number} keyType The KeyType, such as KeyType.RSA.
+ * @param {Buffer} publicKeyDer The public key DER byte array.
+ * @param {Buffer} privateKeyDer The private key DER byte array.
+ */
+MemoryPrivateKeyStorage.prototype.setKeyPairForKeyName = function
+  (keyName, keyType, publicKeyDer, privateKeyDer)
+{
+  this.setPublicKeyForKeyName(keyName, keyType, publicKeyDer);
+  this.setPrivateKeyForKeyName(keyName, keyType, privateKeyDer);
+};
+
+/**
+ * Generate a pair of asymmetric keys.
+ * @param {Name} keyName The name of the key pair.
+ * @param {KeyParams} params The parameters of the key.
+ * @param {boolean} useSync (optional) If true then use blocking crypto and
+ * return a SyncPromise which is already fulfilled. If omitted or false, if
+ * possible use crypto.subtle and return an async Promise, otherwise use
+ * blocking crypto and return a SyncPromise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the pair is
+ * generated.
+ */
+MemoryPrivateKeyStorage.prototype.generateKeyPairPromise = function
+  (keyName, params, useSync)
+{
+  if (this.doesKeyExist(keyName, KeyClass.PUBLIC))
+    return SyncPromise.reject(new SecurityException(new Error
+      ("Public key already exists")));
+  if (this.doesKeyExist(keyName, KeyClass.PRIVATE))
+    return SyncPromise.reject(new SecurityException(new Error
+      ("Private key already exists")));
+
+  var thisStore = this;
+
+  if (UseSubtleCrypto() && !useSync) {
+    if (params.getKeyType() === KeyType.RSA) {
+      var privateKey = null;
+      var publicKeyDer = null;
+
+      return crypto.subtle.generateKey
+        ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
+           publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+           hash: {name: "SHA-256"} },
+         true, ["sign", "verify"])
+      .then(function(key) {
+        privateKey = key.privateKey;
+
+        // Export the public key to DER.
+        return crypto.subtle.exportKey("spki", key.publicKey);
+      })
+      .then(function(exportedPublicKey) {
+        publicKeyDer = new Blob(new Uint8Array(exportedPublicKey), false).buf();
+
+        // Export the private key to DER.
+        return crypto.subtle.exportKey("pkcs8", privateKey);
+      })
+      .then(function(pkcs8Der) {
+        // Crypto.subtle exports the private key as PKCS #8. Decode it to find
+        // the inner private key DER.
+        var parsedNode = DerNode.parse
+          (new Blob(new Uint8Array(pkcs8Der), false).buf());
+        // Get the value of the 3rd child which is the octet string.
+        var privateKeyDer = parsedNode.getChildren()[2].toVal();
+
+        // Save the key pair.
+        thisStore.setKeyPairForKeyName
+          (keyName, params.getKeyType(), publicKeyDer, privateKeyDer.buf());
+
+        // sign will use subtleKey directly.
+        thisStore.privateKeyStore[keyName.toUri()].subtleKey = privateKey;
+
+        return Promise.resolve();
+      });
+    }
+    else
+      return SyncPromise.reject(new SecurityException(new Error
+        ("Only RSA key generation currently supported")));
+  }
+  else {
+    return SyncPromise.resolve()
+    .then(function() {
+      if (typeof RSAKey !== 'undefined') {
+        // Assume we are in the browser.
+        if (params.getKeyType() === KeyType.RSA) {
+          var rsaKey = new RSAKey();
+          rsaKey.generate(params.getKeySize(), '010001');
+          thisStore.setKeyPairForKeyName
+            (keyName, params.getKeyType(),
+             PrivateKeyStorage.encodePublicKeyFromRSAKey(rsaKey).buf(),
+             PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey(rsaKey).buf());
         }
-    }
-    else
-        this.reconnectAndExpressInterest(interest, closure);
+        else
+          return SyncPromise.reject(new SecurityException(new Error
+            ("Only RSA key generation currently supported")));
+      }
+      else {
+        // Assume we are in Node.js.
+        var publicKeyDer;
+        var privateKeyPem;
+
+        if (params.getKeyType() === KeyType.RSA) {
+          if (!rsaKeygen)
+            return SyncPromise.reject(new SecurityException(new Error
+              ("Need to install rsa-keygen: sudo npm install rsa-keygen")));
+
+          var keyPair = rsaKeygen.generate(params.getKeySize());
+
+          // Get the public key DER from the PEM string.
+          var publicKeyBase64 = keyPair.public_key.toString().replace
+            ("-----BEGIN PUBLIC KEY-----", "").replace
+            ("-----END PUBLIC KEY-----", "");
+          publicKeyDer = new Buffer(publicKeyBase64, 'base64');
+
+          privateKeyPem = keyPair.private_key.toString();
+        }
+        else
+          return SyncPromise.reject(new SecurityException(new Error
+            ("Only RSA key generation currently supported")));
+
+        thisStore.setPublicKeyForKeyName(keyName, params.getKeyType(), publicKeyDer);
+        thisStore.privateKeyStore[keyName.toUri()] =
+          { keyType: params.getKeyType(), privateKey: privateKeyPem };
+      }
+
+      return SyncPromise.resolve();
+    });
+  }
 };
 
+/**
+ * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
+ * @param {Name} keyName The name of the key pair.
+ * @return {SyncPromise} A promise that fulfills when the key pair is deleted.
+ */
+MemoryPrivateKeyStorage.prototype.deleteKeyPairPromise = function(keyName)
+{
+  var keyUri = keyName.toUri();
+
+  delete this.publicKeyStore[keyUri];
+  delete this.privateKeyStore[keyUri];
+
+  return SyncPromise.resolve();
+};
+
+/**
+ * Get the public key
+ * @param {Name} keyName The name of public key.
+ * @return {SyncPromise} A promise that returns the PublicKey.
+ */
+MemoryPrivateKeyStorage.prototype.getPublicKeyPromise = function(keyName)
+{
+  var keyUri = keyName.toUri();
+  var publicKey = this.publicKeyStore[keyUri];
+  if (publicKey === undefined)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryPrivateKeyStorage: Cannot find public key " + keyName.toUri())));
+
+  return SyncPromise.resolve(publicKey);
+};
+
+/**
+ * Fetch the private key for keyName and sign the data to produce a signature Blob.
+ * @param {Buffer} data Pointer to the input byte array.
+ * @param {Name} keyName The name of the signing key.
+ * @param {number} digestAlgorithm (optional) The digest algorithm from
+ * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
+ * DigestAlgorithm.SHA256.
+ * @param {boolean} useSync (optional) If true then use blocking crypto and
+ * return a SyncPromise which is already fulfilled. If omitted or false, if
+ * possible use crypto.subtle and return an async Promise, otherwise use
+ * blocking crypto and return a SyncPromise.
+ * @return {Promise|SyncPromise} A promise that returns the signature Blob.
+ */
+MemoryPrivateKeyStorage.prototype.signPromise = function
+  (data, keyName, digestAlgorithm, useSync)
+{
+  useSync = (typeof digestAlgorithm === "boolean") ? digestAlgorithm : useSync;
+  digestAlgorithm = (typeof digestAlgorithm === "boolean" || !digestAlgorithm) ? DigestAlgorithm.SHA256 : digestAlgorithm;
+
+  if (digestAlgorithm != DigestAlgorithm.SHA256)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryPrivateKeyStorage.sign: Unsupported digest algorithm")));
+
+  // Find the private key.
+  var keyUri = keyName.toUri();
+  var privateKey = this.privateKeyStore[keyUri];
+  if (privateKey === undefined)
+    return SyncPromise.reject(new SecurityException(new Error
+      ("MemoryPrivateKeyStorage: Cannot find private key " + keyUri)));
+
+  if (UseSubtleCrypto() && !useSync){
+    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};
+
+    if (!privateKey.subtleKey){
+      //this is the first time in the session that we're using crypto subtle with this key
+      //so we have to convert to pkcs8 and import it.
+      //assigning it to privateKey.subtleKey means we only have to do this once per session,
+      //giving us a small, but not insignificant, performance boost.
+      var privateDER = DataUtils.privateKeyPemToDer(privateKey.privateKey);
+      var pkcs8 = PrivateKeyStorage.encodePkcs8PrivateKey
+        (privateDER, new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),
+         new DerNode.DerNull()).buf();
+
+      var promise = crypto.subtle.importKey("pkcs8", pkcs8.buffer, algo, true, ["sign"]).then(function(subtleKey){
+        //cache the crypto.subtle key object
+        privateKey.subtleKey = subtleKey;
+        return crypto.subtle.sign(algo, subtleKey, data);
+      });
+    } else {
+      // The crypto.subtle key has been cached on a previous sign or from keygen.
+      var promise = crypto.subtle.sign(algo, privateKey.subtleKey, data);
+    }
+
+    return promise.then(function(signature){
+      var result = new Blob(new Uint8Array(signature), true);
+      return Promise.resolve(result);
+    });
+  } else {
+    var signer;
+    if (privateKey.keyType === KeyType.RSA)
+      signer = Crypto.createSign("RSA-SHA256");
+    else if (privateKey.keyType === KeyType.ECDSA)
+      // Just create a "sha256". The Crypto library will infer ECDSA from the key.
+      signer = Crypto.createSign("sha256");
+    else
+      // We don't expect this to happen since setPrivateKeyForKeyName already checked.
+      return SyncPromise.reject(new SecurityException(new Error
+        ("MemoryPrivateKeyStorage.sign: Unrecognized private key type")));
+
+    signer.update(data);
+    var signature = new Buffer
+      (DataUtils.toNumbersIfString(signer.sign(privateKey.privateKey)));
+    var result = new Blob(signature, false);
+
+    return SyncPromise.resolve(result);
+  }
+};
+
+/**
+ * Check if a particular key exists.
+ * @param {Name} keyName The name of the key.
+ * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
+ * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
+ * @return {SyncPromise} A promise which returns true if the key exists.
+ */
+MemoryPrivateKeyStorage.prototype.doesKeyExistPromise = function
+  (keyName, keyClass)
+{
+  var keyUri = keyName.toUri();
+  var result = false;
+  if (keyClass == KeyClass.PUBLIC)
+    result = this.publicKeyStore[keyUri] !== undefined;
+  else if (keyClass == KeyClass.PRIVATE)
+    result = this.privateKeyStore[keyUri] !== undefined;
+
+  return SyncPromise.resolve(result);
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+var Crypto = require('../../crypto.js');
+// Don't require other modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbPrivateKeyStorage extends PrivateKeyStorage to implement private key
+ * storage using the browser's IndexedDB service.
+ * @constructor
+ */
+var IndexedDbPrivateKeyStorage = function IndexedDbPrivateKeyStorage()
+{
+  PrivateKeyStorage.call(this);
+
+  this.database = new Dexie("ndnsec-tpm");
+  this.database.version(1).stores({
+    // "nameHash" is transformName(keyName) // string
+    // "encoding" is the public key DER     // Uint8Array
+    publicKey: "nameHash",
+
+    // "nameHash" is transformName(keyName)     // string
+    // "encoding" is the PKCS 8 private key DER // Uint8Array
+    privateKey: "nameHash"
+  });
+  this.database.open();
+};
+
+IndexedDbPrivateKeyStorage.prototype = new PrivateKeyStorage();
+IndexedDbPrivateKeyStorage.prototype.name = "IndexedDbPrivateKeyStorage";
+
+/**
+ * Generate a pair of asymmetric keys.
+ * @param {Name} keyName The name of the key pair.
+ * @param {KeyParams} params The parameters of the key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the pair is generated.
+ */
+IndexedDbPrivateKeyStorage.prototype.generateKeyPairPromise = function
+  (keyName, params, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.generateKeyPairPromise is only supported for async")));
+
+  var thisStorage = this;
+
+  return thisStorage.doesKeyExistPromise(keyName, KeyClass.PUBLIC)
+  .then(function(exists) {
+    if (exists)
+      throw new Error("Public key already exists");
+
+    return thisStorage.doesKeyExistPromise(keyName, KeyClass.PRIVATE);
+  })
+  .then(function(exists) {
+    if (exists)
+      throw new Error("Private key already exists");
+
+    if (params.getKeyType() === KeyType.RSA) {
+      var privateKey = null;
+      var publicKeyDer = null;
+
+      return crypto.subtle.generateKey
+        ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
+           publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+           hash: {name: "SHA-256"} },
+         true, ["sign", "verify"])
+      .then(function(key) {
+        privateKey = key.privateKey;
+
+        // Export the public key to DER.
+        return crypto.subtle.exportKey("spki", key.publicKey);
+      })
+      .then(function(exportedPublicKey) {
+        publicKeyDer = new Uint8Array(exportedPublicKey);
+
+        // Export the private key to DER.
+        return crypto.subtle.exportKey("pkcs8", privateKey);
+      })
+      .then(function(pkcs8Der) {
+        // Save the key pair
+        return thisStorage.database.transaction
+          ("rw", thisStorage.database.privateKey, thisStorage.database.publicKey, function () {
+            thisStorage.database.publicKey.put
+              ({nameHash: IndexedDbPrivateKeyStorage.transformName(keyName),
+                encoding: publicKeyDer});
+            thisStorage.database.privateKey.put
+              ({nameHash: IndexedDbPrivateKeyStorage.transformName(keyName),
+                encoding: new Uint8Array(pkcs8Der)});
+          });
+      });
+    }
+    else
+      throw new Error("Only RSA key generation currently supported");
+  });
+};
+
+
+/**
+ * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
+ * @param {Name} keyName The name of the key pair.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key pair is deleted.
+ */
+IndexedDbPrivateKeyStorage.prototype.deleteKeyPairPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.deleteKeyPairPromise is only supported for async")));
+
+  var thisStorage = this;
+  // delete does nothing if the key doesn't exist.
+  return this.database.publicKey.delete
+    (IndexedDbPrivateKeyStorage.transformName(keyName))
+  .then(function() {
+    return thisStorage.database.privateKey.delete
+      (IndexedDbPrivateKeyStorage.transformName(keyName));
+  });
+};
+
+/**
+ * Get the public key
+ * @param {Name} keyName The name of public key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns the PublicKey.
+ */
+IndexedDbPrivateKeyStorage.prototype.getPublicKeyPromise = function
+  (keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.getPublicKeyPromise is only supported for async")));
+
+  return this.database.publicKey.get
+    (IndexedDbPrivateKeyStorage.transformName(keyName))
+  .then(function(publicKeyEntry) {
+    return Promise.resolve(new PublicKey(new Blob(publicKeyEntry.encoding)));
+  });
+};
+
+/**
+ * Fetch the private key for keyName and sign the data to produce a signature Blob.
+ * @param {Buffer} data Pointer to the input byte array.
+ * @param {Name} keyName The name of the signing key.
+ * @param {number} digestAlgorithm (optional) The digest algorithm from
+ * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
+ * DigestAlgorithm.SHA256.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns the signature Blob.
+ */
+IndexedDbPrivateKeyStorage.prototype.signPromise = function
+  (data, keyName, digestAlgorithm, useSync)
+{
+  useSync = (typeof digestAlgorithm === "boolean") ? digestAlgorithm : useSync;
+  digestAlgorithm = (typeof digestAlgorithm === "boolean" || !digestAlgorithm) ? DigestAlgorithm.SHA256 : digestAlgorithm;
+
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.signPromise is only supported for async")));
+
+  if (digestAlgorithm != DigestAlgorithm.SHA256)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.sign: Unsupported digest algorithm")));
+
+  // TODO: Support non-RSA keys.
+  var algo = { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256" }};
+
+  // Find the private key.
+  return this.database.privateKey.get
+    (IndexedDbPrivateKeyStorage.transformName(keyName))
+  .then(function(privateKeyEntry) {
+    return crypto.subtle.importKey
+      ("pkcs8", new Blob(privateKeyEntry.encoding).buf(), algo, true, ["sign"]);
+  })
+  .then(function(privateKey) {
+    return crypto.subtle.sign(algo, privateKey, data);
+  })
+  .then(function(signature) {
+    return Promise.resolve(new Blob(new Uint8Array(signature), true));
+  });
+};
+
+/**
+ * Check if a particular key exists.
+ * @param {Name} keyName The name of the key.
+ * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
+ * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise which returns true if the key exists.
+ */
+IndexedDbPrivateKeyStorage.prototype.doesKeyExistPromise = function
+  (keyName, keyClass, useSync)
+{
+  if (useSync)
+    return Promise.reject(new SecurityException(new Error
+      ("IndexedDbPrivateKeyStorage.doesKeyExistPromise is only supported for async")));
+
+  var table = null;
+  if (keyClass == KeyClass.PUBLIC)
+    table = this.database.publicKey;
+  else if (keyClass == KeyClass.PRIVATE)
+    table = this.database.privateKey;
+  else
+    // Silently say that anything else doesn't exist.
+    return Promise.resolve(false);
+
+  return table.where("nameHash").equals
+    (IndexedDbPrivateKeyStorage.transformName(keyName))
+  .count()
+  .then(function(count) {
+    return Promise.resolve(count > 0);
+  });
+};
+
+/**
+ * Transform the key name into the base64 encoding of the hash (the same as in
+ * FilePrivateKeyStorage without the file name extension).
+ */
+IndexedDbPrivateKeyStorage.transformName = function(keyName)
+{
+  var hash = Crypto.createHash('sha256');
+  hash.update(new Buffer(keyName.toUri()));
+  var fileName = hash.digest('base64');
+  return fileName.replace(/\//g, '%');
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var ConfigFile = require('../../util/config-file.js').ConfigFile; /** @ignore */
+var DigestSha256Signature = require('../../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
+var Sha256WithRsaSignature = require('../../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var Sha256WithEcdsaSignature = require('../../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
+var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var DigestAlgorithm = require('../security-types.js').DigestAlgorithm; /** @ignore */
+var KeyType = require('../security-types.js').KeyType; /** @ignore */
+var RsaKeyParams = require('../key-params.js').RsaKeyParams; /** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var PublicKey = require('../certificate/public-key.js').PublicKey; /** @ignore */
+var CertificateSubjectDescription = require('../certificate/certificate-subject-description.js').CertificateSubjectDescription; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var BasicIdentityStorage = require('./basic-identity-storage.js').BasicIdentityStorage; /** @ignore */
+var FilePrivateKeyStorage = require('./file-private-key-storage.js').FilePrivateKeyStorage;
+
+/**
+ * An IdentityManager is the interface of operations related to identity, keys,
+ * and certificates.
+ *
+ * Create a new IdentityManager to use the IdentityStorage and
+ * PrivateKeyStorage.
+ * @param {IdentityStorage} identityStorage An object of a subclass of
+ * IdentityStorage. In Node.js, if this is omitted then use BasicIdentityStorage.
+ * @param {PrivateKeyStorage} privateKeyStorage An object of a subclass of
+ * PrivateKeyStorage. In Node.js, if this is omitted then use the default
+ * PrivateKeyStorage for your system, which is FilePrivateKeyStorage for any
+ * system other than OS X. (OS X key chain storage is not yet implemented, so
+ * you must supply a different PrivateKeyStorage.)
+ * @throws SecurityException if this is not in Node.js and identityStorage or
+ * privateKeyStorage is omitted.
+ * @constructor
+ */
+var IdentityManager = function IdentityManager
+  (identityStorage, privateKeyStorage)
+{
+  if (privateKeyStorage) {
+    // Don't call checkTpm() when using a custom PrivateKeyStorage.
+    if (!identityStorage)
+        // We don't expect this to happen.
+        throw new Error
+          ("IdentityManager: A custom privateKeyStorage is supplied with a null identityStorage")
+
+    this.identityStorage = identityStorage;
+    this.privateKeyStorage = privateKeyStorage;
+  }
+  else {
+    if (!ConfigFile)
+      // Assume we are in the browser.
+      throw new SecurityException(new Error
+        ("IdentityManager: If not in Node.js then you must supply identityStorage and privateKeyStorage."));
+    var config = new ConfigFile();
+
+    var canonicalTpmLocator = [null];
+    var thisStorage = this;
+    // Make the function that BasicIdentityStorage will call the first time it
+    // is used. It has to be an async promise becuase getTpmLocatorPromise is async.
+    function initialCheckPromise() 
+    {
+      return thisStorage.checkTpmPromise_(canonicalTpmLocator[0]);
+    }
+
+    this.identityStorage = identityStorage ? identityStorage
+      : IdentityManager.getDefaultIdentityStorage_(config, initialCheckPromise);
+    this.privateKeyStorage = IdentityManager.getDefaultPrivateKeyStorage_
+      (config, canonicalTpmLocator);
+  }
+};
+
+exports.IdentityManager = IdentityManager;
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @param {Name} identityName The name of the identity.
+ * @params {KeyParams} params The key parameters if a key needs to be generated
+ * for the identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the name of the default
+ * certificate of the identity.
+ */
+IdentityManager.prototype.createIdentityAndCertificatePromise = function
+  (identityName, params, useSync)
+{
+  var thisManager = this;
+  var generateKey = true;
+  var keyName = null;
+
+  return this.identityStorage.addIdentityPromise(identityName, useSync)
+  .then(function() {
+    return thisManager.identityStorage.getDefaultKeyNameForIdentityPromise
+      (identityName, useSync)
+    .then(function(localKeyName) {
+      keyName = localKeyName;
+
+      // Set generateKey.
+      return thisManager.identityStorage.getKeyPromise(keyName, useSync)
+      .then(function(publicKeyDer) {
+        var key = new PublicKey(publicKeyDer);
+        if (key.getKeyType() == params.getKeyType())
+          // The key exists and has the same type, so don't need to generate one.
+          generateKey = false;
+        return SyncPromise.resolve();
+      });
+    }, function(err) {
+      if (!(err instanceof SecurityException))
+        throw err;
+
+      // The key doesn't exist, so leave generateKey true.
+      return SyncPromise.resolve();
+    });
+  })
+  .then(function() {
+    if (generateKey)
+      return thisManager.generateKeyPairPromise(identityName, true, params, useSync)
+      .then(function(localKeyName) {
+        keyName = localKeyName;
+        return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
+          (keyName, useSync);
+      });
+    else
+      // Don't generate a key pair. Use the existing keyName.
+      return SyncPromise.resolve();
+  })
+  .then(function() {
+    return thisManager.identityStorage.getDefaultCertificateNameForKeyPromise
+      (keyName, useSync)
+    .then(function(certName) {
+      // The cert exists, so don't need to make it.
+      return SyncPromise.resolve(certName);
+    }, function(err) {
+      if (!(err instanceof SecurityException))
+        throw err;
+
+      // The cert doesn't exist, so make one.
+      var certName;
+      return thisManager.selfSignPromise(keyName, useSync)
+      .then(function(selfCert) {
+        certName = selfCert.getName();
+        return thisManager.addCertificateAsIdentityDefaultPromise(selfCert, useSync);
+      })
+      .then(function() {
+        return SyncPromise.resolve(certName);
+      });
+    });
+  });
+};
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @param {Name} identityName The name of the identity.
+ * @params {KeyParams} params The key parameters if a key needs to be generated
+ * for the identity.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with the name of the default certificate of the identity. If omitted, the
+ * return value is described below. (Some crypto libraries only use a callback,
+ * so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some crypto libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the name of the default
+ * certificate of the identity. Otherwise, if onComplete is supplied then return
+ * undefined and use onComplete as described above.
+ */
+IdentityManager.prototype.createIdentityAndCertificate = function
+  (identityName, params, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.createIdentityAndCertificatePromise(identityName, params, !onComplete));
+};
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @deprecated Use createIdentityAndCertificate which returns the
+ * certificate name instead of the key name. You can use
+ * IdentityCertificate.certificateNameToPublicKeyName to convert the
+ * certificate name to the key name.
+ * @param {Name} identityName The name of the identity.
+ * @params {KeyParams} params The key parameters if a key needs to be generated
+ * for the identity.
+ * @return {Name} The key name of the auto-generated KSK of the identity.
+ */
+IdentityManager.prototype.createIdentity = function(identityName, params)
+{
+  return IdentityCertificate.certificateNameToPublicKeyName
+    (this.createIdentityAndCertificate(identityName, params));
+};
+
+/**
+ * Delete the identity from the public and private key storage. If the
+ * identity to be deleted is the current default system default, this will not
+ * delete the identity and will return immediately.
+ * @param {Name} identityName The name of the identity.
+ * @param {function} onComplete (optional) This calls onComplete() when the
+ * operation is complete. If omitted, do not use it. (Some database libraries
+ * only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.deleteIdentity = function
+  (identityName, onComplete, onError)
+{
+  var useSync = !onComplete;
+  var thisManager = this;
+
+  var doDelete = true;
+
+  var mainPromise = this.identityStorage.getDefaultIdentityPromise(useSync)
+  .then(function(defaultIdentityName) {
+    if (defaultIdentityName.equals(identityName))
+      // Don't delete the default identity!
+      doDelete = false;
+
+    return SyncPromise.resolve();
+  }, function(err) {
+    // There is no default identity to check.
+    return SyncPromise.resolve();
+  })
+  .then(function() {
+    if (!doDelete)
+      return SyncPromise.resolve();
+
+    var keysToDelete = [];
+    return thisManager.identityStorage.getAllKeyNamesOfIdentityPromise
+      (identityName, keysToDelete, true)
+    .then(function() {
+      return thisManager.identityStorage.getAllKeyNamesOfIdentityPromise
+        (identityName, keysToDelete, false);
+    })
+    .then(function() {
+      return thisManager.identityStorage.deleteIdentityInfoPromise(identityName);
+    })
+    .then(function() {
+      // Recursively loop through keysToDelete, calling deleteKeyPairPromise.
+      function deleteKeyLoop(i) {
+        if (i >= keysToDelete.length)
+          return SyncPromise.resolve();
+
+        return thisManager.privateKeyStorage.deleteKeyPairPromise(keysToDelete[i])
+        .then(function() {
+          return deleteKeyLoop(i + 1);
+        });
+      }
+
+      return deleteKeyLoop(0);
+    });
+  });
+
+  return SyncPromise.complete(onComplete, onError, mainPromise);
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default
+ * identity is set.
+ */
+IdentityManager.prototype.setDefaultIdentityPromise = function
+  (identityName, useSync)
+{
+  return this.identityStorage.setDefaultIdentityPromise(identityName, useSync);
+};
+
+/**
+ * Set the default identity.  If the identityName does not exist, then clear the
+ * default identity so that getDefaultIdentity() throws an exception.
+ * @param {Name} identityName The default identity name.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.setDefaultIdentity = function
+  (identityName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.setDefaultIdentityPromise(identityName, !onComplete));
+};
+
+/**
+ * Get the default identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the Name of default
+ * identity, or a promise rejected with SecurityException if the default
+ * identity is not set.
+ */
+IdentityManager.prototype.getDefaultIdentityPromise = function(useSync)
+{
+  return this.identityStorage.getDefaultIdentityPromise(useSync);
+};
+
+/**
+ * Get the default identity.
+ * @param {function} onComplete (optional) This calls onComplete(identityName)
+ * with name of the default identity. If omitted, the return value is described
+ * below. (Some database libraries only use a callback, so onComplete is required
+ * to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the name of the default
+ * identity. Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * @throws SecurityException if the default identity is not set. However, if
+ * onComplete and onError are defined, then if there is an exception return
+ * undefined and call onError(exception).
+ */
+IdentityManager.prototype.getDefaultIdentity = function(onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getDefaultIdentityPromise(!onComplete));
+};
+
+/**
+ * Get the certificate of the default identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the requested
+ * IdentityCertificate or null if not found.
+ */
+IdentityManager.prototype.getDefaultCertificatePromise = function(useSync)
+{
+  return this.identityStorage.getDefaultCertificatePromise(useSync);
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
+ * a Data-Signing-Key (DSK).
+ * @param {number} keySize The size of the key.
+ * @return {Name} The generated key name.
+ */
+IdentityManager.prototype.generateRSAKeyPair = function
+  (identityName, isKsk, keySize)
+{
+  // For now, require sync. This method may be removed from the API.
+  return SyncPromise.getValue
+    (this.generateKeyPairPromise
+     (identityName, isKsk, new RsaKeyParams(keySize), true));
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.setDefaultKeyForIdentity = function
+  (keyName, identityNameCheck, onComplete, onError)
+{
+  onError = (typeof identityNameCheck === "function") ? onComplete : onError;
+  onComplete = (typeof identityNameCheck === "function") ?
+    identityNameCheck : onComplete;
+  identityNameCheck = (typeof identityNameCheck === "function" || !identityNameCheck) ?
+    new Name() : identityNameCheck;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.setDefaultKeyNameForIdentityPromise
+      (keyName, identityNameCheck, !onComplete));
+};
+
+/**
+ * Get the default key for an identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {function} onComplete (optional) This calls onComplete(keyName)
+ * with name of the default key. If omitted, the return value is described
+ * below. (Some database libraries only use a callback, so onComplete is required
+ * to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the default key name.
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete
+ * as described above.
+ * @throws SecurityException if the default key name for the identity is not set.
+ * However, if onComplete and onError are defined, then if there is an exception
+ * return undefined and call onError(exception).
+ */
+IdentityManager.prototype.getDefaultKeyNameForIdentity = function
+  (identityName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getDefaultKeyNameForIdentityPromise
+      (identityName, !onComplete));
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity and set it as default
+ * key for the identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
+ * a Data-Signing-Key (DSK).
+ * @param {number} keySize The size of the key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which returns the generated key name.
+ */
+IdentityManager.prototype.generateRSAKeyPairAsDefaultPromise = function
+  (identityName, isKsk, keySize, useSync)
+{
+  var newKeyName;
+  var thisManager = this;
+  return this.generateKeyPairPromise(identityName, isKsk, new RsaKeyParams(keySize))
+  .then(function(localKeyName) {
+    newKeyName = localKeyName;
+
+    return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
+      (newKeyName);
+  })
+  .then(function() {
+    return SyncPromise.resolve(newKeyName);
+  });
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity and set it as default
+ * key for the identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
+ * a Data-Signing-Key (DSK).
+ * @param {number} keySize The size of the key.
+ * @return {Name} The generated key name.
+ */
+IdentityManager.prototype.generateRSAKeyPairAsDefault = function
+  (identityName, isKsk, keySize)
+{
+  return SyncPromise.getValue
+    (this.generateRSAKeyPairAsDefaultPromise(identityName, isKsk, keySize, true));
+};
+
+/**
+ * Get the public key with the specified name.
+ * @param {Name} keyName The name of the key.
+ * @param {function} onComplete (optional) This calls onComplete(publicKey)
+ * with PublicKey. If omitted, the return value is described below. (Some database
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {PublicKey} If onComplete is omitted, return the public key.
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete
+ * as described above.
+ */
+IdentityManager.prototype.getPublicKey = function(keyName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getKeyPromise(keyName, !onComplete)
+    .then(function(keyDer) {
+      return SyncPromise.resolve(new PublicKey(keyDer));
+    }));
+};
+
+// TODO: Add two versions of createIdentityCertificate.
+
+/**
+ * Prepare an unsigned identity certificate.
+ * @param {Name} keyName The key name, e.g., `/{identity_name}/ksk-123456`.
+ * @param {PublicKey} publicKey (optional) The public key to sign. If ommited,
+ * use the keyName to get the public key from the identity storage.
+ * @param {Name} signingIdentity The signing identity.
+ * @param {number} notBefore See IdentityCertificate.
+ * @param {number} notAfter See IdentityCertificate.
+ * @param {Array<CertificateSubjectDescription>} subjectDescription A list of
+ * CertificateSubjectDescription. See IdentityCertificate. If null or empty,
+ * this adds a an ATTRIBUTE_NAME based on the keyName.
+ * @param {Name} certPrefix (optional) The prefix before the `KEY` component. If
+ * null or omitted, this infers the certificate name according to the relation
+ * between the signingIdentity and the subject identity. If the signingIdentity
+ * is a prefix of the subject identity, `KEY` will be inserted after the
+ * signingIdentity, otherwise `KEY` is inserted after subject identity (i.e.,
+ * before `ksk-...`).
+ * @param {function} onComplete (optional) This calls onComplete(certificate)
+ * with the unsigned IdentityCertificate, or null if the inputs are invalid. If
+ * omitted, the return value is described below. (Some database libraries only
+ * use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {IdentityCertificate} If onComplete is omitted, return the the
+ * unsigned IdentityCertificate, or null if the inputs are invalid. Otherwise,
+ * if onComplete is supplied then return undefined and use onComplete as
+ * described above.
+ */
+IdentityManager.prototype.prepareUnsignedIdentityCertificate = function
+  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
+   certPrefix, onComplete, onError)
+{
+  if (!(publicKey instanceof PublicKey)) {
+    // The publicKey was omitted. Shift arguments.
+    onError = onComplete;
+    onComplete = certPrefix;
+    certPrefix = subjectDescription;
+    subjectDescription = notAfter;
+    notAfter = notBefore;
+    notBefore = signingIdentity;
+    signingIdentity = publicKey;
+    publicKey = null;
+  }
+
+  // certPrefix may be omitted or null, so check for it and the following args.
+  var arg7 = certPrefix;
+  var arg8 = onComplete;
+  var arg9 = onError;
+  if (arg7 instanceof Name)
+    certPrefix = arg7;
+  else
+    certPrefix = null;
+
+  if (typeof arg7 === 'function') {
+    onComplete = arg7;
+    onError = arg8;
+  }
+  else if (typeof arg8 === 'function') {
+    onComplete = arg8;
+    onError = arg9;
+  }
+  else {
+    onComplete = null;
+    onError = null;
+  }
+
+  var promise;
+  if (publicKey == null)
+    promise =  this.prepareUnsignedIdentityCertificatePromise
+      (keyName, signingIdentity, notBefore, notAfter, subjectDescription,
+       certPrefix, !onComplete);
+  else
+    promise =  this.prepareUnsignedIdentityCertificatePromise
+      (keyName, publicKey, signingIdentity, notBefore, notAfter,
+       subjectDescription, certPrefix, !onComplete);
+  return SyncPromise.complete(onComplete, onError, promise);
+};
+
+/**
+ * Prepare an unsigned identity certificate.
+ * @param {Name} keyName The key name, e.g., `/{identity_name}/ksk-123456`.
+ * @param {PublicKey} publicKey (optional) The public key to sign. If ommited,
+ * use the keyName to get the public key from the identity storage.
+ * @param {Name} signingIdentity The signing identity.
+ * @param {number} notBefore See IdentityCertificate.
+ * @param {number} notAfter See IdentityCertificate.
+ * @param {Array<CertificateSubjectDescription>} subjectDescription A list of
+ * CertificateSubjectDescription. See IdentityCertificate. If null or empty,
+ * this adds a an ATTRIBUTE_NAME based on the keyName.
+ * @param {Name} certPrefix (optional) The prefix before the `KEY` component. If
+ * null or omitted, this infers the certificate name according to the relation
+ * between the signingIdentity and the subject identity. If the signingIdentity
+ * is a prefix of the subject identity, `KEY` will be inserted after the
+ * signingIdentity, otherwise `KEY` is inserted after subject identity (i.e.,
+ * before `ksk-...`).
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the unsigned
+ * IdentityCertificate, or that returns null if the inputs are invalid.
+ */
+IdentityManager.prototype.prepareUnsignedIdentityCertificatePromise = function
+  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
+   certPrefix, useSync)
+{
+  if (!(publicKey instanceof PublicKey)) {
+    // The publicKey was omitted. Shift arguments.
+    useSync = certPrefix;
+    certPrefix = subjectDescription;
+    subjectDescription = notAfter;
+    notAfter = notBefore;
+    notBefore = signingIdentity;
+    signingIdentity = publicKey;
+    publicKey = null;
+  }
+
+  // certPrefix may be omitted or null, so check for it and the following arg.
+  var arg7 = certPrefix;
+  var arg8 = useSync;
+  if (arg7 instanceof Name)
+    certPrefix = arg7;
+  else
+    certPrefix = null;
+
+  if (typeof arg7 === 'boolean')
+    useSync = arg7;
+  else if (typeof arg8 === 'boolean')
+    useSync = arg8;
+  else
+    useSync = false;
+
+  var promise;
+  if (publicKey == null) {
+    promise = this.identityStorage.getKeyPromise(keyName, useSync)
+    .then(function(keyDer) {
+      publicKey = new PublicKey(keyDer);
+      return SyncPromise.resolve();
+    });
+  }
+  else
+    promise = SyncPromise.resolve();
+
+  return promise
+  .then(function() {
+    return SyncPromise.resolve
+      (IdentityManager.prepareUnsignedIdentityCertificateHelper_
+       (keyName, publicKey, signingIdentity, notBefore, notAfter,
+        subjectDescription, certPrefix));
+  });
+};
+
+/**
+ * A helper for prepareUnsignedIdentityCertificatePromise where the publicKey
+ * is known.
+ */
+IdentityManager.prepareUnsignedIdentityCertificateHelper_ = function
+  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
+   certPrefix)
+{
+  if (keyName.size() < 1)
+    return null;
+
+  var tempKeyIdPrefix = keyName.get(-1).toEscapedString();
+  if (tempKeyIdPrefix.length < 4)
+    return null;
+  keyIdPrefix = tempKeyIdPrefix.substr(0, 4);
+  if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
+    return null;
+
+  var certificate = new IdentityCertificate();
+  var certName = new Name();
+
+  if (certPrefix == null) {
+    // No certificate prefix hint, so infer the prefix.
+    if (signingIdentity.match(keyName))
+      certName.append(signingIdentity)
+        .append("KEY")
+        .append(keyName.getSubName(signingIdentity.size()))
+        .append("ID-CERT")
+        .appendVersion(new Date().getTime());
+    else
+      certName.append(keyName.getPrefix(-1))
+        .append("KEY")
+        .append(keyName.get(-1))
+        .append("ID-CERT")
+        .appendVersion(new Date().getTime());
+  }
+  else {
+    // A cert prefix hint is supplied, so determine the cert name.
+    if (certPrefix.match(keyName) && !certPrefix.equals(keyName))
+      certName.append(certPrefix)
+        .append("KEY")
+        .append(keyName.getSubName(certPrefix.size()))
+        .append("ID-CERT")
+        .appendVersion(new Date().getTime());
+    else
+      return null;
+  }
+
+  certificate.setName(certName);
+  certificate.setNotBefore(notBefore);
+  certificate.setNotAfter(notAfter);
+  certificate.setPublicKeyInfo(publicKey);
+
+  if (subjectDescription == null || subjectDescription.length === 0)
+    certificate.addSubjectDescription(new CertificateSubjectDescription
+      ("2.5.4.41", keyName.getPrefix(-1).toUri()));
+  else {
+    for (var i = 0; i < subjectDescription.length; ++i)
+      certificate.addSubjectDescription(subjectDescription[i]);
+  }
+
+  try {
+    certificate.encode();
+  } catch (ex) {
+    throw SecurityException(new Error("DerEncodingException: " + ex));
+  }
+
+  return certificate;
+};
+
+/**
+ * Add a certificate into the public key identity storage.
+ * @param {IdentityCertificate} certificate The certificate to to added. This
+ * makes a copy of the certificate.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.addCertificate = function
+  (certificate, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.addCertificatePromise(certificate, !onComplete));
+};
+
+/**
+ * Set the certificate as the default for its corresponding key.
+ * @param {IdentityCertificate} certificate The certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the default
+ * certificate is set.
+ */
+IdentityManager.prototype.setDefaultCertificateForKeyPromise = function
+  (certificate, useSync)
+{
+  var thisManager = this;
+
+  var keyName = certificate.getPublicKeyName();
+  return this.identityStorage.doesKeyExistPromise(keyName, useSync)
+  .then(function(exists) {
+    if (!exists)
+      throw new SecurityException(new Error
+        ("No corresponding Key record for certificate!"));
+
+    return thisManager.identityStorage.setDefaultCertificateNameForKeyPromise
+      (keyName, certificate.getName(), useSync);
+  });
+};
+
+/**
+ * Set the certificate as the default for its corresponding key.
+ * @param {IdentityCertificate} certificate The certificate.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.setDefaultCertificateForKey = function
+  (certificate, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.setDefaultCertificateForKeyPromise(certificate, !onComplete));
+};
+
+/**
+ * Add a certificate into the public key identity storage and set the
+ * certificate as the default for its corresponding identity.
+ * @param {IdentityCertificate} certificate The certificate to be added. This
+ * makes a copy of the certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the certificate
+ * is added.
+ */
+IdentityManager.prototype.addCertificateAsIdentityDefaultPromise = function
+  (certificate, useSync)
+{
+  var thisManager = this;
+  return this.identityStorage.addCertificatePromise(certificate, useSync)
+  .then(function() {
+    var keyName = certificate.getPublicKeyName();
+    return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
+      (keyName, useSync);
+  })
+  .then(function() {
+    return thisManager.setDefaultCertificateForKeyPromise(certificate, useSync);
+  });
+};
+
+/**
+ * Add a certificate into the public key identity storage and set the
+ * certificate as the default of its corresponding key.
+ * @param {IdentityCertificate} certificate The certificate to be added. This
+ * makes a copy of the certificate.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to use
+ * these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.addCertificateAsDefault = function
+  (certificate, onComplete, onError)
+{
+  var useSync = !onComplete;
+  var thisManager = this;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.addCertificatePromise(certificate, useSync)
+    .then(function() {
+      return thisManager.setDefaultCertificateForKeyPromise(certificate, useSync);
+    }));
+};
+
+/**
+ * Get a certificate which is still valid with the specified name.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @param {function} onComplete (optional) This calls onComplete(certificate)
+ * with the requested IdentityCertificate. If omitted, the return value is 
+ * described below. (Some database libraries only use a callback, so onComplete
+ * is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {IdentityCertificate} If onComplete is omitted, return the requested
+ * certificate. Otherwise, if onComplete is supplied then return undefined and
+ * use onComplete as described above.
+ */
+IdentityManager.prototype.getCertificate = function
+  (certificateName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getCertificatePromise
+      (certificateName, false, !onComplete));
+};
+
+/**
+ * Get the default certificate name for the specified identity.
+ * @param {Name} identityName The identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the default certificate
+ * Name, or a promise rejected with SecurityException if the default key name
+ * for the identity is not set or the default certificate name for the key name
+ * is not set.
+ */
+IdentityManager.prototype.getDefaultCertificateNameForIdentityPromise = function
+  (identityName, useSync)
+{
+  return this.identityStorage.getDefaultCertificateNameForIdentityPromise
+    (identityName, useSync);
+}
+
+/**
+ * Get the default certificate name for the specified identity, which will be
+ * used when signing is performed based on identity.
+ * @param {Name} identityName The name of the specified identity.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with name of the default certificate. If omitted, the return value is described
+ * below. (Some database libraries only use a callback, so onComplete is required
+ * to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the default certificate name.
+ * Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * @throws SecurityException if the default key name for the identity is not
+ * set or the default certificate name for the key name is not set. However, if
+ * onComplete and onError are defined, then if there is an exception return
+ * undefined and call onError(exception).
+ */
+IdentityManager.prototype.getDefaultCertificateNameForIdentity = function
+  (identityName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getDefaultCertificateNameForIdentityPromise
+      (identityName, !onComplete));
+};
+
+/**
+ * Get the default certificate name of the default identity, which will be used
+ * when signing is based on identity and the identity is not specified.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with name of the default certificate. If omitted, the return value is described
+ * below. (Some database libraries only use a callback, so onComplete is required
+ * to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the default certificate name.
+ * Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * @throws SecurityException if the default identity is not set or the default
+ * key name for the identity is not set or the default certificate name for
+ * the key name is not set. However, if onComplete and onError are defined, then
+ * if there is an exception return undefined and call onError(exception).
+ */
+IdentityManager.prototype.getDefaultCertificateName = function
+  (onComplete, onError)
+{
+  var useSync = !onComplete;
+  var thisManager = this;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getDefaultIdentityPromise(useSync)
+    .then(function(identityName) {
+      return thisManager.identityStorage.getDefaultCertificateNameForIdentityPromise
+        (identityName, useSync);
+    }));
+};
+
+/**
+ * Append all the identity names to the nameList.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default identity name. If
+ * false, add only the non-default identity names.
+ * @param {function} onComplete (optional) This calls onComplete() when finished
+ * adding to nameList. If omitted, this returns when complete. (Some database
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {void} If onComplete is omitted, return when complete. Otherwise, if
+ * onComplete is supplied then return undefined and use onComplete as described
+ * above.
+ */
+IdentityManager.prototype.getAllIdentities = function
+  (nameList, isDefault, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getAllIdentitiesPromise
+      (nameList, isDefault, !onComplete));
+};
+
+/**
+ * Append all the key names of a particular identity to the nameList.
+ * @param {Name} identityName The identity name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default key name. If false,
+ * add only the non-default key names.
+ * @param {function} onComplete (optional) This calls onComplete() when finished
+ * adding to nameList. If omitted, this returns when complete. (Some database
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {void} If onComplete is omitted, return when complete. Otherwise, if
+ * onComplete is supplied then return undefined and use onComplete as described
+ * above.
+ */
+IdentityManager.prototype.getAllKeyNamesOfIdentity = function
+  (identityName, nameList, isDefault, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getAllKeyNamesOfIdentityPromise
+      (identityName, nameList, isDefault, !onComplete));
+};
+
+/**
+ * Append all the certificate names of a particular key name to the nameList.
+ * @param {Name} keyName The key name to search for.
+ * @param {Array<Name>} nameList Append result names to nameList.
+ * @param {boolean} isDefault If true, add only the default certificate name. If
+ * false, add only the non-default certificate names.
+ * @param {function} onComplete (optional) This calls onComplete() when finished
+ * adding to nameList. If omitted, this returns when complete. (Some database
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {void} If onComplete is omitted, return when complete. Otherwise, if
+ * onComplete is supplied then return undefined and use onComplete as described
+ * above.
+ */
+IdentityManager.prototype.getAllCertificateNamesOfKey = function
+  (keyName, nameList, isDefault, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.identityStorage.getAllCertificateNamesOfKeyPromise
+      (keyName, nameList, isDefault, !onComplete));
+};
+
+/**
+ * Sign the Data packet or byte array data based on the certificate name.
+ * @param {Data|Buffer} target If this is a Data object, wire encode for signing,
+ * update its signature and key locator field and wireEncoding. If it is a
+ * Buffer, sign it to produce a Signature object.
+ * @param {Name} certificateName The Name identifying the certificate which
+ * identifies the signing key.
+ * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
+ * WireFormat.getDefaultWireFormat() if omitted.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the generated Signature
+ * object (if target is a Buffer) or the target (if target is Data).
+ */
+IdentityManager.prototype.signByCertificatePromise = function
+  (target, certificateName, wireFormat, useSync)
+{
+  useSync = (typeof wireFormat === "boolean") ? wireFormat : useSync;
+  wireFormat = (typeof wireFormat === "boolean" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  var keyName = IdentityManager.certificateNameToPublicKeyName(certificateName);
+
+  var thisManager = this;
+  if (target instanceof Data) {
+    var data = target;
+    var digestAlgorithm = [0];
+
+    return this.makeSignatureByCertificatePromise
+      (certificateName, digestAlgorithm, useSync)
+    .then(function(signature) {
+      data.setSignature(signature);
+      // Encode once to get the signed portion.
+      var encoding = data.wireEncode(wireFormat);
+
+      return thisManager.privateKeyStorage.signPromise
+        (encoding.signedBuf(), keyName, digestAlgorithm[0], useSync);
+    })
+    .then(function(signatureValue) {
+      data.getSignature().setSignature(signatureValue);
+      // Encode again to include the signature.
+      data.wireEncode(wireFormat);
+
+      return SyncPromise.resolve(data);
+    });
+  }
+  else {
+    var digestAlgorithm = [0];
+    return this.makeSignatureByCertificatePromise
+      (certificateName, digestAlgorithm, useSync)
+    .then(function(signature) {
+      return thisManager.privateKeyStorage.signPromise
+        (target, keyName, digestAlgorithm[0], useSync);
+    })
+    .then(function (signatureValue) {
+      signature.setSignature(signatureValue);
+      return SyncPromise.resolve(signature);
+    });
+  }
+};
+
+/**
+ * Sign the Data packet or byte array data based on the certificate name.
+ * @param {Data|Buffer} target If this is a Data object, wire encode for signing,
+ * update its signature and key locator field and wireEncoding. If it is a
+ * Buffer, sign it to produce a Signature object.
+ * @param {Name} certificateName The Name identifying the certificate which
+ * identifies the signing key.
+ * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
+ * WireFormat.getDefaultWireFormat() if omitted.
+ * @param {function} onComplete (optional) If target is a Data object, this calls
+ * onComplete(data) with the supplied Data object which has been modified to set
+ * its signature. If target is a Buffer, this calls onComplete(signature) where
+ * signature is the produced Signature object. If omitted, the return value is
+ * described below. (Some crypto libraries only use a callback, so onComplete is
+ * required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some crypto libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Signature} If onComplete is omitted, return the generated Signature
+ * object (if target is a Buffer) or the target (if target is Data). Otherwise,
+ * if onComplete is supplied then return undefined and use onComplete as described
+ * above.
+ */
+IdentityManager.prototype.signByCertificate = function
+  (target, certificateName, wireFormat, onComplete, onError)
+{
+  onError = (typeof wireFormat === "function") ? onComplete : onError;
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.signByCertificatePromise
+      (target, certificateName, wireFormat, !onComplete));
+};
+
+/**
+ * Append a SignatureInfo to the Interest name, sign the name components and
+ * append a final name component with the signature bits.
+ * @param {Interest} interest The Interest object to be signed. This appends
+ * name components of SignatureInfo and the signature bits.
+ * @param {Name} certificateName The certificate name of the key to use for
+ * signing.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the supplied Interest.
+ */
+IdentityManager.prototype.signInterestByCertificatePromise = function
+  (interest, certificateName, wireFormat, useSync)
+{
+  useSync = (typeof wireFormat === "boolean") ? wireFormat : useSync;
+  wireFormat = (typeof wireFormat === "boolean" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  var thisManager = this;
+  var signature;
+  var digestAlgorithm = [0];
+  return this.makeSignatureByCertificatePromise
+      (certificateName, digestAlgorithm, useSync)
+  .then(function(localSignature) {
+    signature = localSignature;
+    // Append the encoded SignatureInfo.
+    interest.getName().append(wireFormat.encodeSignatureInfo(signature));
+
+    // Append an empty signature so that the "signedPortion" is correct.
+    interest.getName().append(new Name.Component());
+    // Encode once to get the signed portion.
+    var encoding = interest.wireEncode(wireFormat);
+    var keyName = IdentityManager.certificateNameToPublicKeyName
+      (certificateName);
+
+    return thisManager.privateKeyStorage.signPromise
+      (encoding.signedBuf(), keyName, digestAlgorithm[0], useSync);
+  })
+  .then(function(signatureValue) {
+    signature.setSignature(signatureValue);
+
+    // Remove the empty signature and append the real one.
+    interest.setName(interest.getName().getPrefix(-1).append
+      (wireFormat.encodeSignatureValue(signature)));
+    return SyncPromise.resolve(interest);
+  });
+};
+
+/**
+ * Append a SignatureInfo to the Interest name, sign the name components and
+ * append a final name component with the signature bits.
+ * @param {Interest} interest The Interest object to be signed. This appends
+ * name components of SignatureInfo and the signature bits.
+ * @param {Name} certificateName The certificate name of the key to use for
+ * signing.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {function} onComplete (optional) This calls onComplete(interest) with
+ * the supplied Interest object which has been modified to set its signature. If
+ * omitted, then return when the interest has been signed. (Some crypto
+ * libraries only use a callback, so onComplete is required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some crypto libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Signature} If onComplete is omitted, return the interest. Otherwise,
+ * if onComplete is supplied then return undefined and use onComplete as
+ * described above.
+ */
+IdentityManager.prototype.signInterestByCertificate = function
+  (interest, certificateName, wireFormat, onComplete, onError)
+{
+  onError = (typeof wireFormat === "function") ? onComplete : onError;
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  return SyncPromise.complete(onComplete, onError,
+    this.signInterestByCertificatePromise
+      (interest, certificateName, wireFormat, !onComplete));
+};
+
+/**
+ * Wire encode the Data object, digest it and set its SignatureInfo to a
+ * DigestSha256.
+ * @param {Data} data The Data object to be signed. This updates its signature
+ * and wireEncoding.
+ * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
+ * WireFormat.getDefaultWireFormat() if omitted.
+ */
+IdentityManager.prototype.signWithSha256 = function(data, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  data.setSignature(new DigestSha256Signature());
+  // Encode once to get the signed portion.
+  var encoding = data.wireEncode(wireFormat);
+
+  // Digest and set the signature.
+  var hash = Crypto.createHash('sha256');
+  hash.update(encoding.signedBuf());
+  data.getSignature().setSignature(new Blob(hash.digest(), false));
+
+  // Encode again to include the signature.
+  data.wireEncode(wireFormat);
+};
+
+/**
+ * Append a SignatureInfo for DigestSha256 to the Interest name, digest the
+   * name components and append a final name component with the signature bits
+   * (which is the digest).
+ * @param {Interest} interest The Interest object to be signed. This appends
+ * name components of SignatureInfo and the signature bits.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ */
+IdentityManager.prototype.signInterestWithSha256 = function(interest, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var signature = new DigestSha256Signature();
+
+  // Append the encoded SignatureInfo.
+  interest.getName().append(wireFormat.encodeSignatureInfo(signature));
+
+  // Append an empty signature so that the "signedPortion" is correct.
+  interest.getName().append(new Name.Component());
+  // Encode once to get the signed portion.
+  var encoding = interest.wireEncode(wireFormat);
+
+  // Digest and set the signature.
+  var hash = Crypto.createHash('sha256');
+  hash.update(encoding.signedBuf());
+  signature.setSignature(new Blob(hash.digest(), false));
+
+  // Remove the empty signature and append the real one.
+  interest.setName(interest.getName().getPrefix(-1).append
+    (wireFormat.encodeSignatureValue(signature)));
+};
+
+/**
+ * Generate a self-signed certificate for a public key.
+ * @param {Name} keyName The name of the public key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which returns the generated
+ * IdentityCertificate.
+ */
+IdentityManager.prototype.selfSignPromise = function(keyName, useSync)
+{
+  var certificate = new IdentityCertificate();
+
+  var thisManager = this;
+  return this.identityStorage.getKeyPromise(keyName, useSync)
+  .then(function(keyBlob) {
+    var publicKey = new PublicKey(keyBlob);
+
+    var notBefore = new Date().getTime();
+    var notAfter = notBefore + 2 * 365 * 24 * 3600 * 1000; // about 2 years
+
+    certificate.setNotBefore(notBefore);
+    certificate.setNotAfter(notAfter);
+
+    var certificateName = keyName.getPrefix(-1).append("KEY").append
+      (keyName.get(-1)).append("ID-CERT").appendVersion(certificate.getNotBefore());
+    certificate.setName(certificateName);
+
+    certificate.setPublicKeyInfo(publicKey);
+    certificate.addSubjectDescription(new CertificateSubjectDescription
+      ("2.5.4.41", keyName.toUri()));
+    certificate.encode();
+
+    return thisManager.signByCertificatePromise
+      (certificate, certificate.getName(), useSync);
+  })
+};
+
+/**
+ * Generate a self-signed certificate for a public key.
+ * @param {Name} keyName The name of the public key.
+ * @param {function} onComplete (optional) This calls onComplete(certificate)
+ * with the the generated IdentityCertificate. If omitted, the return value is
+ * described below. (Some crypto libraries only use a callback, so onComplete is
+ * required to use these.)
+ * @return {IdentityCertificate} If onComplete is omitted, return the
+ * generated certificate. Otherwise, if onComplete is supplied then return
+ * undefined and use onComplete as described above.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some crypto libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+IdentityManager.prototype.selfSign = function(keyName, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.selfSignPromise(keyName, !onComplete));
+};
+
+/**
+ * Get the public key name from the full certificate name.
+ *
+ * @param {Name} certificateName The full certificate name.
+ * @return {Name} The related public key name.
+ * TODO: Move this to IdentityCertificate
+ */
+IdentityManager.certificateNameToPublicKeyName = function(certificateName)
+{
+  var i = certificateName.size() - 1;
+  var idString = "ID-CERT";
+  while (i >= 0) {
+    if (certificateName.get(i).toEscapedString() == idString)
+      break;
+    --i;
+  }
+
+  var tmpName = certificateName.getSubName(0, i);
+  var keyString = "KEY";
+  i = 0;
+  while (i < tmpName.size()) {
+    if (tmpName.get(i).toEscapedString() == keyString)
+      break;
+    ++i;
+  }
+
+  return tmpName.getSubName(0, i).append(tmpName.getSubName
+    (i + 1, tmpName.size() - i - 1));
+};
+
+/**
+ * Return a new Signature object based on the signature algorithm of the public
+ * key with keyName (derived from certificateName).
+ * @param {Name} certificateName The certificate name.
+ * @param {Array} digestAlgorithm Set digestAlgorithm[0] to the signature
+ * algorithm's digest algorithm, e.g. DigestAlgorithm.SHA256.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which returns a new object of the
+ * correct subclass of Signature.
+ */
+IdentityManager.prototype.makeSignatureByCertificatePromise = function
+  (certificateName, digestAlgorithm, useSync)
+{
+  var keyName = IdentityManager.certificateNameToPublicKeyName(certificateName);
+  return this.privateKeyStorage.getPublicKeyPromise(keyName, useSync)
+  .then(function(publicKey) {
+    var keyType = publicKey.getKeyType();
+
+    var signature = null;
+    if (keyType == KeyType.RSA) {
+      signature = new Sha256WithRsaSignature();
+      digestAlgorithm[0] = DigestAlgorithm.SHA256;
+
+      signature.getKeyLocator().setType(KeyLocatorType.KEYNAME);
+      signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));
+    }
+    else if (keyType == KeyType.ECDSA) {
+      signature = new Sha256WithEcdsaSignature();
+      digestAlgorithm[0] = DigestAlgorithm.SHA256;
+
+      signature.getKeyLocator().setType(KeyLocatorType.KEYNAME);
+      signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));
+    }
+    else
+      throw new SecurityException(new Error("Key type is not recognized"));
+
+    return SyncPromise.resolve(signature);
+  });
+};
+
+/**
+ * A private method to generate a pair of keys for the specified identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk true for generating a Key-Signing-Key (KSK), false for
+ * a Data-Signing-Key (DSK).
+ * @param {KeyParams} params The parameters of the key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If false, this may return a SyncPromise or an async
+ * Promise.
+ * @return {Promise|SyncPromise} A promise which returns the generated key name.
+ */
+IdentityManager.prototype.generateKeyPairPromise = function
+  (identityName, isKsk, params, useSync)
+{
+  var keyName;
+  var thisManager = this;
+  return this.identityStorage.getNewKeyNamePromise(identityName, isKsk, useSync)
+  .then(function(localKeyName) {
+    keyName = localKeyName;
+    return thisManager.privateKeyStorage.generateKeyPairPromise
+      (keyName, params, useSync);
+  })
+  .then(function() {
+    return thisManager.privateKeyStorage.getPublicKeyPromise
+      (keyName, useSync);
+  })
+  .then(function(publicKey) {
+    return thisManager.identityStorage.addKeyPromise
+      (keyName, params.getKeyType(), publicKey.getKeyDer());
+  })
+  .then(function() {
+    return SyncPromise.resolve(keyName);
+  });
+};
+
+/**
+ * Get the IdentityStorage from the pib value in the configuration file if
+ * supplied. Otherwise, get the default for this platform.
+ * @param {ConfigFile} config The configuration file to check.
+ * @param {function} initialCheckPromise This is passed to the
+ * BasicIdentityStorage constructor. See it for details.
+ * @return {IdentityStorage} A new IdentityStorage.
+ */
+IdentityManager.getDefaultIdentityStorage_ = function(config, initialCheckPromise)
+{
+  // Assume we are in Node.js.
+  var pibLocator = config.get("pib", "");
+
+  if (pibLocator !== "") {
+    // Don't support non-default locations for now.
+    if (pibLocator !== "pib-sqlite3")
+      throw new SecurityException(new Error
+        ("Invalid config file pib value: " + pibLocator));
+  }
+
+  return new BasicIdentityStorage(initialCheckPromise);
+};
+
+/**
+ * Get the PrivateKeyStorage from the tpm value in the configuration file if
+ * supplied. Otherwise, get the default for this platform.
+ * @param {ConfigFile} config The configuration file to check.
+ * @param {Array<string>} canonicalTpmLocator Set canonicalTpmLocator[0] to the
+ * canonical value including the colon, * e.g. "tpm-file:".
+ * @return A new PrivateKeyStorage.
+ */
+IdentityManager.getDefaultPrivateKeyStorage_ = function
+  (config, canonicalTpmLocator)
+{
+  var tpmLocator = config.get("tpm", "");
+
+  if (tpmLocator === "") {
+    // Assume we are in Node.js, so check the system.
+    if (process.platform === "darwin") {
+      canonicalTpmLocator[0] = "tpm-osxkeychain:";
+      throw new SecurityException(new Error
+        ("IdentityManager: OS X key chain storage is not yet implemented. You must supply a privateKeyStorage."));
+    }
+    else {
+      canonicalTpmLocator[0] = "tpm-file:";
+      return new FilePrivateKeyStorage();
+    }
+  }
+  else if (tpmLocator === "tpm-osxkeychain") {
+    canonicalTpmLocator[0] = "tpm-osxkeychain:";
+    throw new SecurityException(new Error
+      ("IdentityManager: tpm-osxkeychain is not yet implemented."));
+  }
+  else if (tpmLocator === "tpm-file") {
+    canonicalTpmLocator[0] = "tpm-file:";
+    return new FilePrivateKeyStorage();
+  }
+  else
+    throw new SecurityException(new Error
+      ("Invalid config file tpm value: " + tpmLocator));
+};
+
+/**
+ * Check that identityStorage.getTpmLocatorPromise() (if defined) matches the
+ * canonicalTpmLocator. This has to be an async Promise because it calls async
+ * getTpmLocatorPromise.
+ * @param canonicalTpmLocator The canonical locator from
+ * getDefaultPrivateKeyStorage().
+ * @return {Promise} A promise which resolves if canonicalTpmLocator is OK, or a
+ * promise rejected with SecurityException if the private key storage does not
+ * match.
+ */
+IdentityManager.prototype.checkTpmPromise_ = function(canonicalTpmLocator)
+{
+  return this.identityStorage.getTpmLocatorPromise()
+  .then(function(tpmLocator) {
+    // Just check. If a PIB reset is required, expect ndn-cxx/NFD to do it.
+    if (tpmLocator !== "" && tpmLocator !== canonicalTpmLocator)
+      return Promise.reject(new SecurityException(new Error
+        ("The TPM locator supplied does not match the TPM locator in the PIB: " +
+         tpmLocator + " != " + canonicalTpmLocator)));
+    else
+      return Promise.resolve();
+  }, function(err) {
+    // The TPM locator is not set in the PIB yet.
+    return Promise.resolve();
+  });
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A ValidationRequest is used to return information from
+ * PolicyManager.checkVerificationPolicy.
+ *
+ * Create a new ValidationRequest with the given values.
+ * @param {Interest} interest An interest for fetching more data.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(data).
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(data, reason).
+ * @param {number} retry The number of retrials when there is an interest timeout.
+ * @param {number} stepCount  The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @constructor
+ */
+var ValidationRequest = function ValidationRequest
+  (interest, onVerified, onValidationFailed, retry, stepCount)
+{
+  this.interest = interest;
+  this.onVerified = onVerified;
+  this.onValidationFailed = onValidationFailed;
+  this.retry = retry;
+  this.stepCount = stepCount;
+};
+
+exports.ValidationRequest = ValidationRequest;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DataUtils = require('../../encoding/data-utils.js').DataUtils; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var DigestSha256Signature = require('../../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
+var Sha256WithRsaSignature = require('../../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var Sha256WithEcdsaSignature = require('../../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
+var UseSubtleCrypto = require("../../use-subtle-crypto-node.js").UseSubtleCrypto;
+
+/**
+ * A PolicyManager is an abstract base class to represent the policy for
+ * verifying data packets. You must create an object of a subclass.
+ * @constructor
+ */
+var PolicyManager = function PolicyManager()
+{
+};
+
+exports.PolicyManager = PolicyManager;
+
+/**
+ * Check if the received data packet or signed interest can escape from
+ * verification and be trusted as valid.
+ * Your derived class should override.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} True if the data or interest does not need to be verified
+ * to be trusted as valid, otherwise false.
+ */
+PolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
+{
+  throw new Error("PolicyManager.skipVerifyAndTrust is not implemented");
+};
+
+/**
+ * Check if this PolicyManager has a verification rule for the received data
+ * packet or signed interest.
+ * Your derived class should override.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} True if the data or interest must be verified, otherwise
+ * false.
+ */
+PolicyManager.prototype.requireVerify = function(dataOrInterest)
+{
+  throw new Error("PolicyManager.requireVerify is not implemented");
+};
+
+/**
+ * Check whether the received data or interest packet complies with the
+ * verification policy, and get the indication of the next verification step.
+ * Your derived class should override.
+ *
+ * @param {Data|Interest} dataOrInterest The Data object or interest with the
+ * signature to check.
+ * @param {number} stepCount The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(dataOrInterest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(dataOrInterest, reason).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {WireFormat} wireFormat
+ * @return {ValidationRequest} The indication of next verification step, or
+ * null if there is no further step.
+ */
+PolicyManager.prototype.checkVerificationPolicy = function
+  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
+{
+  throw new Error("PolicyManager.checkVerificationPolicy is not implemented");
+};
+
+/**
+ * Check if the signing certificate name and data name satisfy the signing
+ * policy.
+ * Your derived class should override.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @param {Name} certificateName The name of signing certificate.
+ * @return {boolean} True if the signing certificate can be used to sign the
+ * data, otherwise false.
+ */
+PolicyManager.prototype.checkSigningPolicy = function(dataName, certificateName)
+{
+  throw new Error("PolicyManager.checkSigningPolicy is not implemented");
+};
+
+/**
+ * Infer the signing identity name according to the policy. If the signing
+ * identity cannot be inferred, return an empty name.
+ * Your derived class should override.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @return {Name} The signing identity or an empty name if cannot infer.
+ */
+PolicyManager.prototype.inferSigningIdentity = function(dataName)
+{
+  throw new Error("PolicyManager.inferSigningIdentity is not implemented");
+};
+
+// The first time verify is called, it sets this to determine if a signature
+// buffer needs to be converted to a string for the crypto verifier.
+PolicyManager.verifyUsesString_ = null;
+PolicyManager.setVerifyUsesString_ = function()
+{
+  var hashResult = Crypto.createHash('sha256').digest();
+  // If the hash result is a string, we assume that this is a version of
+  //   crypto where verify also uses a string signature.
+  PolicyManager.verifyUsesString_ = (typeof hashResult === 'string');
+};
+
+/**
+ * Check the type of signature and use the publicKeyDer to verify the
+ * signedBlob using the appropriate signature algorithm.
+ * @param {Signature} signature An object of a subclass of Signature, e.g.
+ * Sha256WithRsaSignature.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
+ * signature.
+ * @param {function} onComplete This calls onComplete(true) if the signature
+ * verifies, otherwise onComplete(false).
+ * @throws SecurityException if the signature type is not recognized or if
+ * publicKeyDer can't be decoded.
+ */
+PolicyManager.verifySignature = function
+  (signature, signedBlob, publicKeyDer, onComplete)
+{
+  if (signature instanceof Sha256WithRsaSignature) {
+    if (publicKeyDer.isNull()) {
+      onComplete(false);
+      return;
+    }
+    PolicyManager.verifySha256WithRsaSignature
+      (signature.getSignature(), signedBlob, publicKeyDer, onComplete);
+  }
+  else if (signature instanceof Sha256WithEcdsaSignature) {
+    if (publicKeyDer.isNull()) {
+      onComplete(false);
+      return;
+    }
+    PolicyManager.verifySha256WithEcdsaSignature
+      (signature.getSignature(), signedBlob, publicKeyDer, onComplete);
+  }
+  else if (signature instanceof DigestSha256Signature)
+    PolicyManager.verifyDigestSha256Signature
+      (signature.getSignature(), signedBlob, onComplete);
+  else
+    // We don't expect this to happen.
+    throw new SecurityException(new Error
+      ("PolicyManager.verify: Signature type is unknown"));
+};
+
+/**
+ * Verify the RSA signature on the SignedBlob using the given public key.
+ * @param {Blob} signature The signature bits.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
+ * signature.
+ * @param {function} onComplete This calls onComplete(true) if the signature
+ * verifies, otherwise onComplete(false).
+ */
+PolicyManager.verifySha256WithRsaSignature = function
+  (signature, signedBlob, publicKeyDer, onComplete)
+{
+  if (UseSubtleCrypto()){
+    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};
+
+    crypto.subtle.importKey("spki", publicKeyDer.buf().buffer, algo, true, ["verify"]).then(function(publicKey){
+      return crypto.subtle.verify(algo, publicKey, signature.buf(), signedBlob.signedBuf())
+    }).then(function(verified){
+      onComplete(verified);
+    });
+  } else {
+    if (PolicyManager.verifyUsesString_ === null)
+      PolicyManager.setVerifyUsesString_();
+
+    // The crypto verifier requires a PEM-encoded public key.
+    var keyBase64 = publicKeyDer.buf().toString('base64');
+    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END PUBLIC KEY-----";
+
+    var verifier = Crypto.createVerify('RSA-SHA256');
+    verifier.update(signedBlob.signedBuf());
+    var signatureBytes = PolicyManager.verifyUsesString_ ?
+      DataUtils.toString(signature.buf()) : signature.buf();
+    onComplete(verifier.verify(keyPem, signatureBytes));
+  }
+};
+
+/**
+ * Verify the ECDSA signature on the SignedBlob using the given public key.
+ * @param {Blob} signature The signature bits.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
+ * signature.
+ * @param {function} onComplete This calls onComplete(true) if the signature
+ * verifies, otherwise onComplete(false).
+ */
+PolicyManager.verifySha256WithEcdsaSignature = function
+  (signature, signedBlob, publicKeyDer, onComplete)
+{
+  if (UseSubtleCrypto()) {
 /*
+    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};
+
+    crypto.subtle.importKey("spki", publicKeyDer.buf().buffer, algo, true, ["verify"]).then(function(publicKey){
+      return crypto.subtle.verify(algo, publicKey, signature.buf(), signedBlob.signedBuf())
+    }).then(function(verified){
+      onComplete(verified);
+    });
+*/  onComplete(false);
+  } else {
+    if (PolicyManager.verifyUsesString_ === null)
+      PolicyManager.setVerifyUsesString_();
+
+    // The crypto verifier requires a PEM-encoded public key.
+    var keyBase64 = publicKeyDer.buf().toString("base64");
+    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END PUBLIC KEY-----";
+
+    // Just create a "sha256". The Crypto library will infer ECDSA from the key.
+    var verifier = Crypto.createVerify("sha256");
+    verifier.update(signedBlob.signedBuf());
+    var signatureBytes = PolicyManager.verifyUsesString_ ?
+      DataUtils.toString(signature.buf()) : signature.buf();
+    onComplete(verifier.verify(keyPem, signatureBytes));
+  }
+};
+
+/**
+ * Verify the DigestSha256 signature on the SignedBlob by verifying that the
+ * digest of SignedBlob equals the signature.
+ * @param {Blob} signature The signature bits.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {function} onComplete This calls onComplete(true) if the signature
+ * verifies, otherwise onComplete(false).
+ */
+PolicyManager.verifyDigestSha256Signature = function
+  (signature, signedBlob, onComplete)
+{
+  // Set signedPortionDigest to the digest of the signed portion of the signedBlob.
+  var hash = Crypto.createHash('sha256');
+  hash.update(signedBlob.signedBuf());
+  var signedPortionDigest = new Blob(hash.digest(), false);
+
+  onComplete(signedPortionDigest.equals(signature));
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From PyNDN certificate_cache.py by Adeola Bannis.
+ * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate;
+
+/**
+ * A CertificateCache is used to save other users' certificate during
+ * verification.
+ * @constructor
+ */
+var CertificateCache = function CertificateCache()
+{
+  // The key is the certificate name URI. The value is the wire encoding Blob.
+  this.cache = {};
+};
+
+exports.CertificateCache = CertificateCache;
+
+/**
+ * Insert the certificate into the cache. Assumes the timestamp is not yet
+ * removed from the name.
+ * @param {IdentityCertificate} certificate The certificate to insert.
+ */
+CertificateCache.prototype.insertCertificate = function(certificate)
+{
+  var certName = certificate.getName().getPrefix(-1);
+  this.cache[certName.toUri()] = certificate.wireEncode();
+};
+
+/**
+ * Remove a certificate from the cache. This does nothing if it is not present.
+ * @param {Name} certificateName The name of the certificate to remove. This
+ * assumes there is no timestamp in the name.
+ */
+CertificateCache.prototype.deleteCertificate = function(certificateName)
+{
+  delete this.cache[certificateName.toUri()];
+};
+
+/**
+ * Fetch a certificate from the cache.
+ * @param {Name} certificateName The name of the certificate to remove. This
+ * assumes there is no timestamp in the name.
+ * @return {IdentityCertificate} A new copy of the IdentityCertificate, or null
+ * if not found.
+ */
+CertificateCache.prototype.getCertificate = function(certificateName)
+{
+  var certData = this.cache[certificateName.toUri()];
+  if (certData === undefined)
+    return null;
+
+  var cert = new IdentityCertificate();
+  cert.wireDecode(certData);
+  return cert;
+};
+
+/**
+ * Clear all certificates from the store.
+ */
+CertificateCache.prototype.reset = function()
+{
+  this.cache = {};
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From PyNDN config_policy_manager.py by Adeola Bannis.
+ * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var fs = require('fs'); /** @ignore */
+var path = require('path'); /** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var Interest = require('../../interest.js').Interest; /** @ignore */
+var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
+var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var BoostInfoParser = require('../../util/boost-info-parser.js').BoostInfoParser; /** @ignore */
+var NdnRegexMatcher = require('../../util/ndn-regex-matcher.js').NdnRegexMatcher; /** @ignore */
+var CertificateCache = require('./certificate-cache.js').CertificateCache; /** @ignore */
+var ValidationRequest = require('./validation-request.js').ValidationRequest; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
+var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
+var NdnCommon = require('../../util/ndn-common.js').NdnCommon;
+
+/**
+ * ConfigPolicyManager manages trust according to a configuration file in the
+ * Validator Configuration File Format
+ * (http://redmine.named-data.net/projects/ndn-cxx/wiki/CommandValidatorConf)
+ *
+ * Once a rule is matched, the ConfigPolicyManager looks in the
+ * CertificateCache for the IdentityCertificate matching the name in the KeyLocator
+ * and uses its public key to verify the data packet or signed interest. If the
+ * certificate can't be found, it is downloaded, verified and installed. A chain
+ * of certificates will be followed to a maximum depth.
+ * If the new certificate is accepted, it is used to complete the verification.
+ *
+ * The KeyLocators of data packets and signed interests MUST contain a name for
+ * verification to succeed.
+ *
+ * Create a new ConfigPolicyManager which will act on the rules specified in the
+ * configuration and download unknown certificates when necessary.
+ *
+ * @param {string} configFileName (optional) If not null or empty, the path to
+ * the configuration file containing verification rules. (This only works in
+ * Node.js since it reads files using the "fs" module.) Otherwise, you should
+ * separately call load().
+ * @param {CertificateCache} certificateCache (optional) A CertificateCache to
+ * hold known certificates. If this is null or omitted, then create an internal
+ * CertificateCache.
+ * @param {number} searchDepth (optional) The maximum number of links to follow
+ * when verifying a certificate chain. If omitted, use a default.
+ * @param {number} graceInterval (optional) The window of time difference
+ * (in milliseconds) allowed between the timestamp of the first interest signed with
+ * a new public key and the validation time. If omitted, use a default value.
+ * @param {number} keyTimestampTtl (optional) How long a public key's last-used
+ * timestamp is kept in the store (milliseconds). If omitted, use a default value.
+ * @param {number} maxTrackedKeys The maximum number of public key use
+ * timestamps to track. If omitted, use a default.
+ * @constructor
+ */
+var ConfigPolicyManager = function ConfigPolicyManager
+  (configFileName, certificateCache, searchDepth, graceInterval,
+   keyTimestampTtl, maxTrackedKeys)
+{
+  // Call the base constructor.
+  PolicyManager.call(this);
+
+  if (certificateCache == undefined)
+    certificateCache = null;
+  if (searchDepth == undefined)
+    searchDepth = 5;
+  if (graceInterval == undefined)
+    graceInterval = 3000;
+  if (keyTimestampTtl == undefined)
+    keyTimestampTtl = 3600000;
+  if (maxTrackedKeys == undefined)
+    maxTrackedKeys = 1000;
+
+  if (certificateCache == null)
+    this.certificateCache = new CertificateCache();
+  else
+    this.certificateCache = certificateCache;
+  this.maxDepth = searchDepth;
+  this.keyGraceInterval = graceInterval;
+  this.keyTimestampTtl = keyTimestampTtl;
+  this.maxTrackedKeys = maxTrackedKeys;
+
+  this.reset();
+
+  if (configFileName != null && configFileName != "")
+    this.load(configFileName);
+};
+
+ConfigPolicyManager.prototype = new PolicyManager();
+ConfigPolicyManager.prototype.name = "ConfigPolicyManager";
+
+exports.ConfigPolicyManager = ConfigPolicyManager;
+
+/**
+ * Reset the certificate cache and other fields to the constructor state.
+ */
+ConfigPolicyManager.prototype.reset = function()
+{
+  this.certificateCache.reset();
+
+  // Stores the fixed-signer certificate name associated with validation rules
+  // so we don't keep loading from files.
+  this.fixedCertificateCache = {};
+
+  // Stores the timestamps for each public key used in command interests to
+  // avoid replay attacks.
+  // Key is public key name, value is last timestamp.
+  this.keyTimestamps = {};
+
+  this.requiresVerification = true;
+
+  this.config = new BoostInfoParser();
+  this.refreshManager = new ConfigPolicyManager.TrustAnchorRefreshManager();
+};
+
+/**
+ * Call reset() and load the configuration rules from the file name or the input
+ * string. There are two forms:
+ * load(configFileName) reads configFileName from the file system. (This only
+ * works in Node.js since it reads files using the "fs" module.)
+ * load(input, inputName) reads from the input, in which case inputName is used
+ * only for log messages, etc.
+ * @param {string} configFileName The path to the file containing configuration
+ * rules.
+ * @param {string} input The contents of the configuration rules, with lines
+ * separated by "\n" or "\r\n".
+ * @param {string} inputName Use with input for log messages, etc.
+ */
+ConfigPolicyManager.prototype.load = function(configFileNameOrInput, inputName)
+{
+  this.reset();
+  this.config.read(configFileNameOrInput, inputName);
+  this.loadTrustAnchorCertificates();
+}
+
+/**
+ * Check if this PolicyManager has a verification rule for the received data.
+ * If the configuration file contains the trust anchor 'any', nothing is
+ * verified.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} true if the data must be verified, otherwise false.
+ */
+ConfigPolicyManager.prototype.requireVerify = function(dataOrInterest)
+{
+  return this.requiresVerification;
+};
+
+/**
+ * Override to always indicate that the signing certificate name and data name
+ * satisfy the signing policy.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @param {Name} certificateName The name of signing certificate.
+ * @return {boolean} True to indicate that the signing certificate can be used
+ * to sign the data.
+ */
+ConfigPolicyManager.prototype.checkSigningPolicy = function
+  (dataName, certificateName)
+{
+  return true;
+};
+
+/**
+ * Check if the received signed interest can escape from verification and be
+ * trusted as valid. If the configuration file contains the trust anchor
+ * 'any', nothing is verified.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} true if the data or interest does not need to be verified
+ * to be trusted as valid, otherwise false.
+ */
+ConfigPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
+{
+  return !this.requiresVerification;
+};
+
+/**
+ * Check whether the received data packet or interest complies with the
+ * verification policy, and get the indication of the next verification step.
+ *
+ * @param {Data|Interest} dataOrInterest The Data object or interest with the
+ * signature to check.
+ * @param {number} stepCount The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(dataOrInterest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(dataOrInterest, reason).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {WireFormat} wireFormat
+ * @return {ValidationRequest} The indication of next verification step, or
+ * null if there is no further step.
+ */
+ConfigPolicyManager.prototype.checkVerificationPolicy = function
+  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
+{
+  if (stepCount > this.maxDepth) {
+    try {
+      onValidationFailed
+        (dataOrInterest, "The verification stepCount " + stepCount +
+           " exceeded the maxDepth " + this.maxDepth);
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var signature = ConfigPolicyManager.extractSignature(dataOrInterest, wireFormat);
+  // No signature -> fail.
+  if (signature == null) {
+    try {
+      onValidationFailed
+        (dataOrInterest, "Cannot extract the signature from " +
+         dataOrInterest.getName().toUri());
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  if (!KeyLocator.canGetFromSignature(signature)) {
+    // We only support signature types with key locators.
+    try {
+      onValidationFailed
+        (dataOrInterest, "The signature type does not support a KeyLocator");
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var keyLocator = null;
+  try {
+    keyLocator = KeyLocator.getFromSignature(signature);
+  }
+  catch (ex) {
+    // No key locator -> fail.
+    try {
+      onValidationFailed
+        (dataOrInterest, "Error in KeyLocator.getFromSignature: " + ex);
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var signatureName = keyLocator.getKeyName();
+  // No key name in KeyLocator -> fail.
+  if (signatureName.size() == 0) {
+    try {
+      onValidationFailed
+        (dataOrInterest, "The signature KeyLocator doesn't have a key name");
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var objectName = dataOrInterest.getName();
+  var matchType = "data";
+
+  // For command interests, we need to ignore the last 4 components when
+  // matching the name.
+  if (dataOrInterest instanceof Interest) {
+    objectName = objectName.getPrefix(-4);
+    matchType = "interest";
+  }
+
+  // First see if we can find a rule to match this packet.
+  var matchedRule = this.findMatchingRule(objectName, matchType);
+
+  // No matching rule -> fail.
+  if (matchedRule == null) {
+    try {
+      onValidationFailed
+        (dataOrInterest, "No matching rule found for " + objectName.toUri());
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  var failureReason = ["unknown"];
+  var signatureMatches = this.checkSignatureMatch
+    (signatureName, objectName, matchedRule, failureReason);
+  if (!signatureMatches) {
+    try {
+      onValidationFailed(dataOrInterest, failureReason[0]);
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return null;
+  }
+
+  // Before we look up keys, refresh any certificate directories.
+  this.refreshManager.refreshAnchors();
+
+  // Now finally check that the data or interest was signed correctly.
+  // If we don't actually have the certificate yet, create a
+  // ValidationRequest for it.
+  var foundCert = this.refreshManager.getCertificate(signatureName);
+  if (foundCert == null)
+    foundCert = this.certificateCache.getCertificate(signatureName);
+  var thisManager = this;
+  if (foundCert == null) {
+    var certificateInterest = new Interest(signatureName);
+    var onCertificateDownloadComplete = function(data) {
+      var certificate;
+      try {
+        certificate = new IdentityCertificate(data);
+      } catch (ex) {
+        try {
+          onValidationFailed
+            (dataOrInterest, "Cannot decode certificate " + data.getName().toUri());
+        } catch (ex) {
+          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+        return null;
+      }
+      thisManager.certificateCache.insertCertificate(certificate);
+      thisManager.checkVerificationPolicy
+        (dataOrInterest, stepCount + 1, onVerified, onValidationFailed);
+    };
+
+    var nextStep = new ValidationRequest
+      (certificateInterest, onCertificateDownloadComplete, onValidationFailed,
+       2, stepCount + 1);
+
+    return nextStep;
+  }
+
+  // For interests, we must check that the timestamp is fresh enough.
+  // We do this after (possibly) downloading the certificate to avoid
+  // filling the cache with bad keys.
+  if (dataOrInterest instanceof Interest) {
+    var keyName = foundCert.getPublicKeyName();
+    var timestamp = dataOrInterest.getName().get(-4).toNumber();
+
+    if (!this.interestTimestampIsFresh(keyName, timestamp, failureReason)) {
+      try {
+        onValidationFailed(dataOrInterest, failureReason[0]);
+      } catch (ex) {
+        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return null;
+    }
+  }
+
+  // Certificate is known, so verify the signature.
+  this.verify(signature, dataOrInterest.wireEncode(), function (verified, reason) {
+    if (verified) {
+      try {
+        onVerified(dataOrInterest);
+      } catch (ex) {
+        console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      if (dataOrInterest instanceof Interest)
+        thisManager.updateTimestampForKey(keyName, timestamp);
+    }
+    else {
+      try {
+        onValidationFailed(dataOrInterest, reason);
+      } catch (ex) {
+        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+  });
+};
+
+/**
+ * The configuration file allows 'trust anchor' certificates to be preloaded.
+ * The certificates may also be loaded from a directory, and if the 'refresh'
+ * option is set to an interval, the certificates are reloaded at the specified
+ * interval.
+ */
+ConfigPolicyManager.prototype.loadTrustAnchorCertificates = function()
+{
+  var anchors = this.config.getRoot().get("validator/trust-anchor");
+
+  for (var i = 0; i < anchors.length; ++i) {
+    var anchor = anchors[i];
+
+    var typeName = anchor.get("type")[0].getValue();
+    var isPath = false;
+    var certID;
+    if (typeName == 'file') {
+      certID = anchor.get("file-name")[0].getValue();
+      isPath = true;
+    }
+    else if (typeName == 'base64') {
+      certID = anchor.get("base64-string")[0].getValue();
+      isPath = false;
+    }
+    else if (typeName == "dir") {
+      var dirName = anchor.get("dir")[0].getValue();
+
+      var refreshPeriod = 0;
+      var refreshTrees = anchor.get("refresh");
+      if (refreshTrees.length >= 1) {
+        var refreshPeriodStr = refreshTrees[0].getValue();
+
+        var refreshMatch = refreshPeriodStr.match(/(\d+)([hms])/);
+        if (refreshMatch == null)
+          refreshPeriod = 0;
+        else {
+          refreshPeriod = parseInt(refreshMatch[1]);
+          if (refreshMatch[2] != 's') {
+            refreshPeriod *= 60;
+            if (refreshMatch[2] != 'm')
+              refreshPeriod *= 60;
+          }
+        }
+      }
+
+      // Convert refreshPeriod from seconds to milliseconds.
+      this.refreshManager.addDirectory(dirName, refreshPeriod * 1000);
+      continue;
+    }
+    else if (typeName == "any") {
+      // This disables all security!
+      this.requiresVerification = false;
+      break;
+    }
+
+    this.lookupCertificate(certID, isPath);
+  }
+};
+
+/**
+ * Once a rule is found to match data or a signed interest, the name in the
+ * KeyLocator must satisfy the condition in the 'checker' section of the rule,
+ * else the data or interest is rejected.
+ * @param {Name} signatureName The certificate name from the KeyLocator.
+ * @param {Name} objectName The name of the data packet or interest. In the case
+ * of signed interests, this excludes the timestamp, nonce and signature
+ * components.
+ * @param {BoostInfoTree} rule The rule from the configuration file that matches
+ * the data or interest.
+ * @param {Array<string>} failureReason If matching fails, set failureReason[0]
+ * to the failure reason.
+ * @return {boolean} True if matches.
+ */
+ConfigPolicyManager.prototype.checkSignatureMatch = function
+  (signatureName, objectName, rule, failureReason)
+{
+  var checker = rule.get("checker")[0];
+  var checkerType = checker.get("type")[0].getValue();
+  if (checkerType == "fixed-signer") {
+    var signerInfo = checker.get("signer")[0];
+    var signerType = signerInfo.get("type")[0].getValue();
+
+    var cert;
+    if (signerType == "file") {
+      cert = this.lookupCertificate
+        (signerInfo.get("file-name")[0].getValue(), true);
+      if (cert == null) {
+        failureReason[0] = "Can't find fixed-signer certificate file: " +
+          signerInfo.get("file-name")[0].getValue();
+        return false;
+      }
+    }
+    else if (signerType == "base64") {
+      cert = this.lookupCertificate
+        (signerInfo.get("base64-string")[0].getValue(), false);
+      if (cert == null) {
+        failureReason[0] = "Can't find fixed-signer certificate base64: " +
+          signerInfo.get("base64-string")[0].getValue();
+        return false;
+      }
+    }
+    else {
+      failureReason[0] = "Unrecognized fixed-signer signerType: " + signerType;
+      return false;
+    }
+
+    if (cert.getName().equals(signatureName))
+      return true;
+    else {
+      failureReason[0] = "fixed-signer cert name \"" + cert.getName().toUri() +
+        "\" does not equal signatureName \"" + signatureName.toUri() + "\"";
+      return false;
+    }
+  }
+  else if (checkerType == "hierarchical") {
+    // This just means the data/interest name has the signing identity as a prefix.
+    // That means everything before "ksk-?" in the key name.
+    var identityRegex = "^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>";
+    var identityMatch = NdnRegexMatcher.match(identityRegex, signatureName);
+    if (identityMatch != null) {
+      var identityPrefix = new Name(identityMatch[1]).append
+        (new Name(identityMatch[2]));
+      if (ConfigPolicyManager.matchesRelation
+          (objectName, identityPrefix, "is-prefix-of"))
+        return true;
+      else {
+        failureReason[0] = "The hierarchical objectName \"" + objectName.toUri() +
+          "\" is not a prefix of \"" + identityPrefix.toUri() + "\"";
+        return false;
+      }
+    }
+    else {
+      failureReason[0] = "The hierarchical identityRegex \"" + identityRegex +
+        "\" does not match signatureName \"" + signatureName.toUri() + "\"";
+      return false;
+    }
+  }
+  else if (checkerType == "customized") {
+    var keyLocatorInfo = checker.get("key-locator")[0];
+    // Not checking type - only name is supported.
+
+    // Is this a simple relation?
+    var relationType = keyLocatorInfo.getFirstValue("relation");
+    if (relationType != null) {
+      var matchName = new Name(keyLocatorInfo.get("name")[0].getValue());
+      if (ConfigPolicyManager.matchesRelation
+          (signatureName, matchName, relationType))
+        return true;
+      else {
+        failureReason[0] = "The custom signatureName \"" + signatureName.toUri() +
+          "\" does not match matchName \"" + matchName.toUri() +
+          "\" using relation " + relationType;
+        return false;
+      }
+    }
+
+    // Is this a simple regex?
+    var keyRegex = keyLocatorInfo.getFirstValue("regex");
+    if (keyRegex != null) {
+      if (NdnRegexMatcher.match(keyRegex, signatureName) != null)
+        return true;
+      else {
+        failureReason[0] = "The custom signatureName \"" + signatureName.toUri() +
+          "\" does not regex match simpleKeyRegex \"" + keyRegex + "\"";
+        return false;
+      }
+    }
+
+    // Is this a hyper-relation?
+    var hyperRelationList = keyLocatorInfo.get("hyper-relation");
+    if (hyperRelationList.length >= 1) {
+      var hyperRelation = hyperRelationList[0];
+
+      var keyRegex = hyperRelation.getFirstValue("k-regex");
+      var keyExpansion = hyperRelation.getFirstValue("k-expand");
+      var nameRegex = hyperRelation.getFirstValue("p-regex");
+      var nameExpansion = hyperRelation.getFirstValue("p-expand");
+      var relationType = hyperRelation.getFirstValue("h-relation");
+      if (keyRegex != null && keyExpansion != null && nameRegex != null &&
+          nameExpansion != null && relationType != null) {
+        var keyMatch = NdnRegexMatcher.match(keyRegex, signatureName);
+        if (keyMatch == null || keyMatch[1] === undefined) {
+          failureReason[0] = "The custom hyper-relation signatureName \"" +
+            signatureName.toUri() + "\" does not match the keyRegex \"" +
+            keyRegex + "\"";
+          return false;
+        }
+        var keyMatchPrefix = ConfigPolicyManager.expand(keyMatch, keyExpansion);
+
+        var nameMatch = NdnRegexMatcher.match(nameRegex, objectName);
+        if (nameMatch == null || nameMatch[1] === undefined) {
+          failureReason[0] = "The custom hyper-relation objectName \"" +
+            objectName.toUri() + "\" does not match the nameRegex \"" +
+            nameRegex + "\"";
+          return false;
+        }
+        var nameMatchStr = ConfigPolicyManager.expand(nameMatch, nameExpansion);
+
+        if (ConfigPolicyManager.matchesRelation
+            (new Name(nameMatchStr), new Name(keyMatchPrefix), relationType))
+          return true;
+        else {
+          failureReason[0] = "The custom hyper-relation nameMatch \"" +
+            nameMatchStr + "\" does not match the keyMatchPrefix \"" +
+            keyMatchPrefix + "\" using relation " + relationType;
+          return false;
+        }
+      }
+    }
+  }
+
+  failureReason[0] = "Unrecognized checkerType: " + checkerType;
+  return false;
+};
+
+/**
+ * Similar to Python expand, return expansion where every \1, \2, etc. is
+ * replaced by match[1], match[2], etc.  Note: Even though this is a general
+ * utility function, we define it locally because it is only tested to work in
+ * the cases used by this class.
+ * @param {Object} match The match object from String.match.
+ * @param {string} expansion The string with \1, \2, etc. to replace from match.
+ * @return {string} The expanded string.
+ */
+ConfigPolicyManager.expand = function(match, expansion)
+{
+  return expansion.replace
+    (/\\(\d)/g,
+     function(fullMatch, n) { return match[parseInt(n)];})
+};
+
+/**
+ * This looks up certificates specified as base64-encoded data or file names.
+ * These are cached by filename or encoding to avoid repeated reading of files
+ * or decoding.
+ * @param {string} certID
+ * @param {boolean} isPath
+ * @return {IdentityCertificate} The certificate object, or null if not found.
+ */
+ConfigPolicyManager.prototype.lookupCertificate = function(certID, isPath)
+{
+  var cert;
+
+  var cachedCertUri = this.fixedCertificateCache[certID];
+  if (cachedCertUri === undefined) {
+    if (isPath)
+      // load the certificate data (base64 encoded IdentityCertificate)
+      cert = ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile
+        (certID);
+    else {
+      var certData = new Buffer(certID, 'base64');
+      cert = new IdentityCertificate();
+      cert.wireDecode(certData);
+    }
+
+    var certUri = cert.getName().getPrefix(-1).toUri();
+    this.fixedCertificateCache[certID] = certUri;
+    this.certificateCache.insertCertificate(cert);
+  }
+  else
+    cert = this.certificateCache.getCertificate(new Name(cachedCertUri));
+
+  return cert;
+};
+
+/**
+ * Search the configuration file for the first rule that matches the data or
+ * signed interest name. In the case of interests, the name to match should
+ * exclude the timestamp, nonce, and signature components.
+ * @param {Name} objName The name to be matched.
+ * @param {string} matchType The rule type to match, "data" or "interest".
+ * @return {BoostInfoTree} The matching rule, or null if not found.
+ */
+ConfigPolicyManager.prototype.findMatchingRule = function(objName, matchType)
+{
+  var rules = this.config.getRoot().get("validator/rule");
+  for (var iRule = 0; iRule < rules.length; ++iRule) {
+    var r = rules[iRule];
+
+    if (r.get('for')[0].getValue() == matchType) {
+      var passed = true;
+      var filters = r.get('filter');
+      if (filters.length == 0)
+        // No filters means we pass!
+        return r;
+      else {
+        for (var iFilter = 0; iFilter < filters.length; ++iFilter) {
+          var f = filters[iFilter];
+
+          // Don't check the type - it can only be name for now.
+          // We need to see if this is a regex or a relation.
+          var regexPattern = f.getFirstValue("regex");
+          if (regexPattern === null) {
+            var matchRelation = f.get('relation')[0].getValue();
+            var matchUri = f.get('name')[0].getValue();
+            var matchName = new Name(matchUri);
+            passed = ConfigPolicyManager.matchesRelation(objName, matchName, matchRelation);
+          }
+          else
+            passed = (NdnRegexMatcher.match(regexPattern, objName) !== null);
+
+          if (!passed)
+            break;
+        }
+
+        if (passed)
+          return r;
+      }
+    }
+  }
+
+  return null;
+};
+
+/**
+ * Determines if a name satisfies the relation to matchName.
+ * @param {Name} name
+ * @param {Name} matchName
+ * @param {string} matchRelation Can be one of:
+ *   'is-prefix-of' - passes if the name is equal to or has the other
+ *      name as a prefix
+ *   'is-strict-prefix-of' - passes if the name has the other name as a
+ *      prefix, and is not equal
+ *   'equal' - passes if the two names are equal
+ * @return {boolean}
+ */
+ConfigPolicyManager.matchesRelation = function(name, matchName, matchRelation)
+{
+  var passed = false;
+  if (matchRelation == 'is-strict-prefix-of') {
+    if (matchName.size() == name.size())
+      passed = false;
+    else if (matchName.match(name))
+      passed = true;
+  }
+  else if (matchRelation == 'is-prefix-of') {
+    if (matchName.match(name))
+      passed = true;
+  }
+  else if (matchRelation == 'equal') {
+    if (matchName.equals(name))
+      passed = true;
+  }
+  return passed;
+};
+
+/**
+ * Extract the signature information from the interest name or from the data
+ * packet or interest.
+ * @param {Data|Interest} dataOrInterest The object whose signature is needed.
+ * @param {WireFormat} wireFormat (optional) The wire format used to decode
+ * signature information from the interest name.
+ * @return {Signature} The object of a sublcass of Signature or null if can't
+ * decode.
+ */
+ConfigPolicyManager.extractSignature = function(dataOrInterest, wireFormat)
+{
+  if (dataOrInterest instanceof Data)
+    return dataOrInterest.getSignature();
+  else if (dataOrInterest instanceof Interest) {
+    wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+    try {
+      var signature = wireFormat.decodeSignatureInfoAndValue
+        (dataOrInterest.getName().get(-2).getValue().buf(),
+         dataOrInterest.getName().get(-1).getValue().buf(), false);
+    }
+    catch (e) {
+      return null;
+    }
+
+    return signature;
+  }
+
+  return null;
+};
+
+/**
+ * Determine whether the timestamp from the interest is newer than the last use
+ * of this key, or within the grace interval on first use.
+ * @param {Name} keyName The name of the public key used to sign the interest.
+ * @param {number} timestamp The timestamp extracted from the interest name.
+ * @param {Array<string>} failureReason If matching fails, set failureReason[0]
+ * to the failure reason.
+ * @return {boolean} True if timestamp is fresh as described above.
+ */
+ConfigPolicyManager.prototype.interestTimestampIsFresh = function
+  (keyName, timestamp, failureReason)
+{
+  var lastTimestamp = this.keyTimestamps[keyName.toUri()];
+  if (lastTimestamp == undefined) {
+    var now = new Date().getTime();
+    var notBefore = now - this.keyGraceInterval;
+    var notAfter = now + this.keyGraceInterval;
+    if (!(timestamp > notBefore && timestamp < notAfter)) {
+      failureReason[0] =
+        "The command interest timestamp is not within the first use grace period of " +
+        this.keyGraceInterval + " milliseconds.";
+      return false;
+    }
+    else
+      return true;
+  }
+  else {
+    if (timestamp <= lastTimestamp) {
+      failureReason[0] =
+        "The command interest timestamp is not newer than the previous timestamp";
+      return false;
+    }
+    else
+      return true;
+  }
+};
+
+/**
+ * Trim the table size down if necessary, and insert/update the latest interest
+ * signing timestamp for the key. Any key which has not been used within the TTL
+ * period is purged. If the table is still too large, the oldest key is purged.
+ * @param {Name} keyName The name of the public key used to sign the interest.
+ * @param {number} timestamp The timestamp extracted from the interest name.
+ */
+ConfigPolicyManager.prototype.updateTimestampForKey = function
+  (keyName, timestamp)
+{
+  this.keyTimestamps[keyName.toUri()] = timestamp;
+
+  // JavaScript does have a direct way to get the number of entries, so first
+  //   get the keysToErase while counting.
+  var keyTimestampsSize = 0;
+  var keysToErase = [];
+
+  var now = new Date().getTime();
+  var oldestTimestamp = now;
+  var oldestKey = null;
+  for (var keyUri in this.keyTimestamps) {
+    ++keyTimestampsSize;
+    var ts = this.keyTimestamps[keyUri];
+    if (now - ts > this.keyTimestampTtl)
+      keysToErase.push(keyUri);
+    else if (ts < oldestTimestamp) {
+      oldestTimestamp = ts;
+      oldestKey = keyUri;
+    }
+  }
+
+  if (keyTimestampsSize >= this.maxTrackedKeys) {
+    // Now delete the expired keys.
+    for (var i = 0; i < keysToErase.length; ++i) {
+      delete this.keyTimestamps[keysToErase[i]];
+      --keyTimestampsSize;
+    }
+
+    if (keyTimestampsSize > this.maxTrackedKeys)
+      // We have not removed enough.
+      delete this.keyTimestamps[oldestKey];
+  }
+};
+
+/**
+ * Check the type of signatureInfo to get the KeyLocator. Look in the
+ * IdentityStorage for the public key with the name in the KeyLocator and use it
+ * to verify the signedBlob. If the public key can't be found, return false.
+ * (This is a generalized method which can verify both a data packet and an
+ * interest.)
+ * @param {Signature} signatureInfo An object of a subclass of Signature, e.g.
+ * Sha256WithRsaSignature.
+ * @param {SignedBlob} signedBlob The SignedBlob with the signed portion to
+ * verify.
+ * @param {function} onComplete This calls onComplete(true, undefined) if the
+ * signature verifies, otherwise onComplete(false, reason).
+ */
+ConfigPolicyManager.prototype.verify = function
+  (signatureInfo, signedBlob, onComplete)
+{
+  // We have already checked once that there is a key locator.
+  var keyLocator = KeyLocator.getFromSignature(signatureInfo);
+
+  if (keyLocator.getType() == KeyLocatorType.KEYNAME) {
+    // Assume the key name is a certificate name.
+    var signatureName = keyLocator.getKeyName();
+    var certificate = this.refreshManager.getCertificate(signatureName);
+    if (certificate == null)
+      certificate = this.certificateCache.getCertificate(signatureName);
+    if (certificate == null) {
+      onComplete(false,  "Cannot find a certificate with name " +
+        signatureName.toUri());
+      return;
+    }
+
+    var publicKeyDer = certificate.getPublicKeyInfo().getKeyDer();
+    if (publicKeyDer.isNull()) {
+      // Can't find the public key with the name.
+      onComplete(false, "There is no public key in the certificate with name " +
+        certificate.getName().toUri());
+      return;
+    }
+
+    PolicyManager.verifySignature
+      (signatureInfo, signedBlob, publicKeyDer, function(verified) {
+        if (verified)
+          onComplete(true);
+        else
+          onComplete
+            (false,
+             "The signature did not verify with the given public key");
+      });
+  }
+  else
+    onComplete(false, "The KeyLocator does not have a key name");
+};
+
+ConfigPolicyManager.TrustAnchorRefreshManager =
+  function ConfigPolicyManagerTrustAnchorRefreshManager()
+{
+  this.certificateCache = new CertificateCache();
+  // Maps the directory name to certificate names so they can be deleted when
+  // necessary. The key is the directory name string. The value is the object
+  //  {certificateNames,  // array of string
+  //   nextRefresh,       // number
+  //   refreshPeriod      // number
+  //  }.
+  this.refreshDirectories = {};
+};
+
+ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile =
+  function(fileName)
+{
+  var encodedData = fs.readFileSync(fileName).toString();
+  var decodedData = new Buffer(encodedData, 'base64');
+  var cert = new IdentityCertificate();
+  cert.wireDecode(new Blob(decodedData, false));
+  return cert;
+};
+
+ConfigPolicyManager.TrustAnchorRefreshManager.prototype.getCertificate = function
+  (certificateName)
+{
+  // This assumes the timestamp is already removed.
+  return this.certificateCache.getCertificate(certificateName);
+};
+
+// refreshPeriod in milliseconds.
+ConfigPolicyManager.TrustAnchorRefreshManager.prototype.addDirectory = function
+  (directoryName, refreshPeriod)
+{
+  var allFiles;
+  try {
+    allFiles = fs.readdirSync(directoryName);
+  }
+  catch (e) {
+    throw new SecurityException(new Error
+      ("Cannot list files in directory " + directoryName));
+  }
+
+  var certificateNames = [];
+  for (var i = 0; i < allFiles.length; ++i) {
+    var cert;
+    try {
+      var fullPath = path.join(directoryName, allFiles[i]);
+      cert = ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile
+        (fullPath);
+    }
+    catch (e) {
+      // Allow files that are not certificates.
+      continue;
+    }
+
+    // Cut off the timestamp so it matches the KeyLocator Name format.
+    var certUri = cert.getName().getPrefix(-1).toUri();
+    this.certificateCache.insertCertificate(cert);
+    certificateNames.push(certUri);
+  }
+
+  this.refreshDirectories[directoryName] = {
+    certificates: certificateNames,
+    nextRefresh: new Date().getTime() + refreshPeriod,
+    refreshPeriod: refreshPeriod };
+};
+
+ConfigPolicyManager.TrustAnchorRefreshManager.prototype.refreshAnchors = function()
+{
+  var refreshTime =  new Date().getTime();
+  for (var directory in this.refreshDirectories) {
+    var info = this.refreshDirectories[directory];
+    var nextRefreshTime = info.nextRefresh;
+    if (nextRefreshTime <= refreshTime) {
+      var certificateList = info.certificates.slice(0);
+      // Delete the certificates associated with this directory if possible
+      //   then re-import.
+      // IdentityStorage subclasses may not support deletion.
+      for (var c in certificateList)
+        this.certificateCache.deleteCertificate(new Name(c));
+
+      this.addDirectory(directory, info.refreshPeriod);
+    }
+  }
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
+var NdnCommon = require('../../util/ndn-common.js').NdnCommon;
+
+/**
+ * @constructor
+ */
+var NoVerifyPolicyManager = function NoVerifyPolicyManager()
+{
+  // Call the base constructor.
+  PolicyManager.call(this);
+};
+
+NoVerifyPolicyManager.prototype = new PolicyManager();
+NoVerifyPolicyManager.prototype.name = "NoVerifyPolicyManager";
+
+exports.NoVerifyPolicyManager = NoVerifyPolicyManager;
+
+/**
+ * Override to always skip verification and trust as valid.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} True.
+ */
+NoVerifyPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
+{
+  return true;
+};
+
+/**
+ * Override to return false for no verification rule for the received data or
+ * signed interest.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} False.
+ */
+NoVerifyPolicyManager.prototype.requireVerify = function(dataOrInterest)
+{
+  return false;
+};
+
+/**
+ * Override to call onVerified(data) and to indicate no further verification
+ * step.
+ *
+ * @param {Data|Interest} dataOrInterest The Data object or interest with the
+ * signature to check.
+ * @param {number} stepCount The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @param {function} onVerified This does override to call
+ * onVerified(dataOrInterest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed Override to ignore this.
+ * @param {WireFormat} wireFormat
+ * @return {ValidationRequest} null for no further step for looking up a
+ * certificate chain.
+ */
+NoVerifyPolicyManager.prototype.checkVerificationPolicy = function
+  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
+{
+  try {
+    onVerified(dataOrInterest);
+  } catch (ex) {
+    console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+  return null;
+};
+
+/**
+ * Override to always indicate that the signing certificate name and data name
+ * satisfy the signing policy.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @param {Name} certificateName The name of signing certificate.
+ * @return {boolean} True to indicate that the signing certificate can be used
+ * to sign the data.
+ */
+NoVerifyPolicyManager.prototype.checkSigningPolicy = function
+  (dataName, certificateName)
+{
+  return true;
+};
+
+/**
+ * Override to indicate that the signing identity cannot be inferred.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @return {Name} An empty name because cannot infer.
+ */
+NoVerifyPolicyManager.prototype.inferSigningIdentity = function(dataName)
+{
+  return new Name();
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var Interest = require('../../interest.js').Interest; /** @ignore */
+var Data = require('../../data.js').Data; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
+var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
+var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
+var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
+var NdnCommon = require('../../util/ndn-common.js').NdnCommon;
+
+/**
+ * A SelfVerifyPolicyManager implements a PolicyManager to look in the
+ * IdentityStorage for the public key with the name in the KeyLocator (if
+ * available) and use it to verify the data packet, without searching a
+ * certificate chain.  If the public key can't be found, the verification fails.
+ *
+ * @param {IdentityStorage} identityStorage (optional) The IdentityStorage for
+ * looking up the public key. This object must remain valid during the life of
+ * this SelfVerifyPolicyManager. If omitted, then don't look for a public key
+ * with the name in the KeyLocator and rely on the KeyLocator having the full
+ * public key DER.
+ * @constructor
+ */
+var SelfVerifyPolicyManager = function SelfVerifyPolicyManager(identityStorage)
+{
+  // Call the base constructor.
+  PolicyManager.call(this);
+
+  this.identityStorage = identityStorage;
+};
+
+SelfVerifyPolicyManager.prototype = new PolicyManager();
+SelfVerifyPolicyManager.prototype.name = "SelfVerifyPolicyManager";
+
+exports.SelfVerifyPolicyManager = SelfVerifyPolicyManager;
+
+/**
+ * Never skip verification.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} False.
+ */
+SelfVerifyPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
+{
+  return false;
+};
+
+/**
+ * Always return true to use the self-verification rule for the received data.
+ *
+ * @param {Data|Interest} dataOrInterest The received data packet or interest.
+ * @return {boolean} True.
+ */
+SelfVerifyPolicyManager.prototype.requireVerify = function(dataOrInterest)
+{
+  return true;
+};
+
+/**
+ * Look in the IdentityStorage for the public key with the name in the
+ * KeyLocator (if available) and use it to verify the data packet.  If the
+ * public key can't be found, call onValidationFailed.
+ *
+ * @param {Data|Interest} dataOrInterest The Data object or interest with the
+ * signature to check.
+ * @param {number} stepCount The number of verification steps that have been
+ * done, used to track the verification progress.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(dataOrInterest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(dataOrInterest, reason).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {WireFormat} wireFormat
+ * @return {ValidationRequest} null for no further step for looking up a
+ * certificate chain.
+ */
+SelfVerifyPolicyManager.prototype.checkVerificationPolicy = function
+  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (dataOrInterest instanceof Data) {
+    var data = dataOrInterest;
+    // wireEncode returns the cached encoding if available.
+    this.verify(data.getSignature(), data.wireEncode(), function(verified, reason) {
+      if (verified) {
+        try {
+          onVerified(data);
+        } catch (ex) {
+          console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+      else {
+        try {
+          onValidationFailed(data, reason);
+        } catch (ex) {
+          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+    });
+  }
+  else if (dataOrInterest instanceof Interest) {
+    var interest = dataOrInterest;
+
+    if (interest.getName().size() < 2) {
+      try {
+        onValidationFailed
+          (interest, "The signed interest has less than 2 components: " +
+             interest.getName().toUri());
+      } catch (ex) {
+        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return;
+    }
+
+    // Decode the last two name components of the signed interest
+    var signature;
+    try {
+      signature = wireFormat.decodeSignatureInfoAndValue
+        (interest.getName().get(-2).getValue().buf(),
+         interest.getName().get(-1).getValue().buf(), false);
+    } catch (ex) {
+      try {
+        onValidationFailed
+          (interest, "Error decoding the signed interest signature: " + ex);
+      } catch (ex) {
+        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+      return;
+    }
+
+    // wireEncode returns the cached encoding if available.
+    this.verify(signature, interest.wireEncode(), function(verified, reason) {
+      if (verified) {
+        try {
+          onVerified(interest);
+        } catch (ex) {
+          console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+      else {
+        try {
+          onValidationFailed(interest, reason);
+        } catch (ex) {
+          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+    });
+  }
+  else
+    throw new SecurityException(new Error
+      ("checkVerificationPolicy: unrecognized type for dataOrInterest"));
+
+  // No more steps, so return null.
+  return null;
+};
+
+/**
+ * Override to always indicate that the signing certificate name and data name
+ * satisfy the signing policy.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @param {Name} certificateName The name of signing certificate.
+ * @return {boolean} True to indicate that the signing certificate can be used
+ * to sign the data.
+ */
+SelfVerifyPolicyManager.prototype.checkSigningPolicy = function
+  (dataName, certificateName)
+{
+  return true;
+};
+
+/**
+ * Override to indicate that the signing identity cannot be inferred.
+ *
+ * @param {Name} dataName The name of data to be signed.
+ * @return {Name} An empty name because cannot infer.
+ */
+SelfVerifyPolicyManager.prototype.inferSigningIdentity = function(dataName)
+{
+  return new Name();
+};
+
+/**
+ * Check the type of signatureInfo to get the KeyLocator. Look in the
+ * IdentityStorage for the public key with the name in the KeyLocator (if
+ * available) and use it to verify the signedBlob. If the public key can't be
+ * found, return false. (This is a generalized method which can verify both a
+ * Data packet and an interest.)
+ * @param {Signature} signatureInfo An object of a subclass of Signature, e.g.
+ * Sha256WithRsaSignature.
+ * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
+ * verify.
+ * @param {function} onComplete This calls onComplete(true, undefined) if the
+ * signature verifies, otherwise onComplete(false, reason).
+ */
+SelfVerifyPolicyManager.prototype.verify = function
+  (signatureInfo, signedBlob, onComplete)
+{
+  if (KeyLocator.canGetFromSignature(signatureInfo)) {
+    this.getPublicKeyDer
+      (KeyLocator.getFromSignature(signatureInfo), function(publicKeyDer, reason) {
+        if (publicKeyDer.isNull())
+          onComplete(false, reason);
+        else {
+          try {
+            PolicyManager.verifySignature
+              (signatureInfo, signedBlob, publicKeyDer, function(verified) {
+                if (verified)
+                  onComplete(true);
+                else
+                  onComplete
+                    (false,
+                     "The signature did not verify with the given public key");
+              });
+          } catch (ex) {
+            onComplete(false, "Error in verifySignature: " + ex);
+          }
+        }
+      });
+  }
+  else {
+    try {
+      // Assume that the signature type does not require a public key.
+      PolicyManager.verifySignature
+        (signatureInfo, signedBlob, null, function(verified) {
+          if (verified)
+            onComplete(true);
+          else
+            onComplete
+              (false, "The signature did not verify with the given public key");
+        });
+    } catch (ex) {
+      onComplete(false, "Error in verifySignature: " + ex);
+    }
+  }
+};
+
+/**
+ * Look in the IdentityStorage for the public key with the name in the
+ * KeyLocator (if available). If the public key can't be found, return and empty
+ * Blob.
+ * @param {KeyLocator} keyLocator The KeyLocator.
+ * @param {function} onComplete This calls 
+ * onComplete(publicKeyDer, reason) where publicKeyDer is the public key
+ * DER Blob or an isNull Blob if not found and reason is the reason
+ * string if not found.
+ */
+SelfVerifyPolicyManager.prototype.getPublicKeyDer = function
+  (keyLocator, onComplete)
+{
+  if (keyLocator.getType() == KeyLocatorType.KEYNAME &&
+      this.identityStorage != null) {
+    var keyName;
+    try {
+      // Assume the key name is a certificate name.
+      keyName = IdentityCertificate.certificateNameToPublicKeyName
+        (keyLocator.getKeyName());
+    } catch (ex) {
+      onComplete
+        (new Blob(), "Cannot get a public key name from the certificate named: " +
+           keyLocator.getKeyName().toUri());
+      return;
+    }
+    SyncPromise.complete
+      (onComplete,
+       function(err) {
+         // The storage doesn't have the key.
+         onComplete
+           (new Blob(), "The identityStorage doesn't have the key named " +
+              keyName.toUri());
+       },
+       this.identityStorage.getKeyPromise(keyName));
+  }
+  else
+    // Can't find a key to verify.
+    onComplete(new Blob(), "The signature KeyLocator doesn't have a key name");
+};
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('../crypto.js'); /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
+var SecurityException = require('./security-exception.js').SecurityException; /** @ignore */
+var RsaKeyParams = require('./key-params.js').RsaKeyParams; /** @ignore */
+var IdentityCertificate = require('./certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
+var IdentityManager = require('./identity/identity-manager.js').IdentityManager; /** @ignore */
+var NoVerifyPolicyManager = require('./policy/no-verify-policy-manager.js').NoVerifyPolicyManager;
+
+/**
+ * A KeyChain provides a set of interfaces to the security library such as
+ * identity management, policy configuration and packet signing and verification.
+ * Note: This class is an experimental feature. See the API docs for more detail at
+ * http://named-data.net/doc/ndn-ccl-api/key-chain.html .
+ *
+ * Create a new KeyChain with the identityManager and policyManager.
+ * @param {IdentityManager} identityManager (optional) The identity manager as a
+ * subclass of IdentityManager. If omitted, use the default IdentityManager
+ * constructor.
+ * @param {PolicyManager} policyManager (optional) The policy manager as a
+ * subclass of PolicyManager. If omitted, use NoVerifyPolicyManager.
+ * @throws SecurityException if this is not in Node.js and this uses the default
+ * IdentityManager constructor. (See IdentityManager for details.)
+ * @constructor
+ */
+var KeyChain = function KeyChain(identityManager, policyManager)
+{
+  if (!identityManager)
+    identityManager = new IdentityManager();
+  if (!policyManager)
+    policyManager = new NoVerifyPolicyManager();
+
+  this.identityManager = identityManager;
+  this.policyManager = policyManager;
+  this.face = null;
+};
+
+exports.KeyChain = KeyChain;
+
+/*****************************************
+ *          Identity Management          *
+ *****************************************/
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @param {Name} identityName The name of the identity.
+ * @param {KeyParams} params (optional) The key parameters if a key needs to be
+ * generated for the identity. If omitted, use KeyChain.DEFAULT_KEY_PARAMS.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with name of the default certificate of the identity. If omitted, the return
+ * value is described below. (Some crypto libraries only use a callback, so
+ * onComplete is required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {Name} If onComplete is omitted, return the name of the default
+ * certificate of the identity. Otherwise, if onComplete is supplied then return
+ * undefined and use onComplete as described above.
+ */
+KeyChain.prototype.createIdentityAndCertificate = function
+  (identityName, params, onComplete, onError)
+{
+  onError = (typeof params === "function") ? onComplete : onError;
+  onComplete = (typeof params === "function") ? params : onComplete;
+  params = (typeof params === "function" || !params) ?
+    KeyChain.DEFAULT_KEY_PARAMS : params;
+
+  return this.identityManager.createIdentityAndCertificate
+    (identityName, params, onComplete, onError);
+};
+
+/**
+ * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
+ * identity and a self-signed certificate of the KSK. If a key pair or
+ * certificate for the identity already exists, use it.
+ * @deprecated Use createIdentityAndCertificate which returns the
+ * certificate name instead of the key name. You can use
+ * IdentityCertificate.certificateNameToPublicKeyName to convert the
+ * certificate name to the key name.
+ * @param {Name} identityName The name of the identity.
+ * @param {KeyParams} params (optional) The key parameters if a key needs to be
+ * generated for the identity. If omitted, use KeyChain.DEFAULT_KEY_PARAMS.
+ * @return {Name} The key name of the auto-generated KSK of the identity.
+ */
+KeyChain.prototype.createIdentity = function(identityName, params)
+{
+  return IdentityCertificate.certificateNameToPublicKeyName
+    (this.createIdentityAndCertificate(identityName, params));
+};
+
+/**
+ * Delete the identity from the public and private key storage. If the
+ * identity to be deleted is the current default system default, this will not
+ * delete the identity and will return immediately.
+ * @param {Name} identityName The name of the identity.
+ * @param {function} onComplete (optional) This calls onComplete() when the
+ * operation is complete. If omitted, do not use it. (Some database libraries
+ * only use a callback, so onComplete is required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.deleteIdentity = function
+  (identityName, onComplete, onError)
+{
+  this.identityManager.deleteIdentity(identityName, onComplete, onError);
+};
+
+/**
+ * Get the default identity.
+ * @param {function} onComplete (optional) This calls onComplete(identityName)
+ * with name of the default identity. If omitted, the return value is described
+ * below. (Some crypto libraries only use a callback, so onComplete is required
+ * to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * @return {Name} If onComplete is omitted, return the name of the default
+ * identity. Otherwise, if onComplete is supplied then return undefined and use
+ * onComplete as described above.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @throws SecurityException if the default identity is not set. However, if
+ * onComplete and onError are defined, then if there is an exception return
+ * undefined and call onError(exception).
+ */
+KeyChain.prototype.getDefaultIdentity = function(onComplete, onError)
+{
+  return this.identityManager.getDefaultIdentity(onComplete, onError);
+};
+
+/**
+ * Get the default certificate name of the default identity, which will be used
+ * when signing is based on identity and the identity is not specified.
+ * @param {function} onComplete (optional) This calls onComplete(certificateName)
+ * with name of the default certificate. If omitted, the return value is described
+ * below. (Some crypto libraries only use a callback, so onComplete is required
+ * to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {Name} If onComplete is omitted, return the default certificate name.
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete
+ * as described above.
+ * @throws SecurityException if the default identity is not set or the default
+ * key name for the identity is not set or the default certificate name for
+ * the key name is not set. However, if onComplete and onError are defined, then
+ * if there is an exception return undefined and call onError(exception).
+ */
+KeyChain.prototype.getDefaultCertificateName = function(onComplete, onError)
+{
+  return this.identityManager.getDefaultCertificateName(onComplete, onError);
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk (optional) true for generating a Key-Signing-Key (KSK),
+ * false for a Data-Signing-Key (DSK). If omitted, generate a Data-Signing-Key.
+ * @param {number} keySize (optional) The size of the key. If omitted, use a
+ * default secure key size.
+ * @return {Name} The generated key name.
+ */
+KeyChain.prototype.generateRSAKeyPair = function(identityName, isKsk, keySize)
+{
+  keySize = (typeof isKsk === "boolean") ? isKsk : keySize;
+  isKsk = (typeof isKsk === "boolean") ? isKsk : false;
+
+  if (!keySize)
+    keySize = 2048;
+
+  return this.identityManager.generateRSAKeyPair(identityName, isKsk, keySize);
+};
+
+/**
+ * Set a key as the default key of an identity. The identity name is inferred
+ * from keyName.
+ * @param {Name} keyName The name of the key.
+ * @param {Name} identityNameCheck (optional) The identity name to check that the
+ * keyName contains the same identity name. If an empty name, it is ignored.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.setDefaultKeyForIdentity = function
+  (keyName, identityNameCheck, onComplete, onError)
+{
+  return this.identityManager.setDefaultKeyForIdentity
+    (keyName, identityNameCheck, onComplete, onError);
+};
+
+/**
+ * Generate a pair of RSA keys for the specified identity and set it as default
+ * key for the identity.
+ * @param {Name} identityName The name of the identity.
+ * @param {boolean} isKsk (optional) true for generating a Key-Signing-Key (KSK),
+ * false for a Data-Signing-Key (DSK). If omitted, generate a Data-Signing-Key.
+ * @param {number} keySize (optional) The size of the key. If omitted, use a
+ * default secure key size.
+ * @return {Name} The generated key name.
+ */
+KeyChain.prototype.generateRSAKeyPairAsDefault = function
+  (identityName, isKsk, keySize)
+{
+  return this.identityManager.generateRSAKeyPairAsDefault
+    (identityName, isKsk, keySize);
+};
+
+/**
+ * Create a public key signing request.
+ * @param {Name} keyName The name of the key.
+ * @return {Blob} The signing request data.
+ */
+KeyChain.prototype.createSigningRequest = function(keyName)
+{
+  return this.identityManager.getPublicKey(keyName).getKeyDer();
+};
+
+/**
+ * Install an identity certificate into the public key identity storage.
+ * @param {IdentityCertificate} certificate The certificate to to added.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.installIdentityCertificate = function
+  (certificate, onComplete, onError)
+{
+  this.identityManager.addCertificate(certificate, onComplete, onError);
+};
+
+/**
+ * Set the certificate as the default for its corresponding key.
+ * @param {IdentityCertificate} certificate The certificate.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some database libraries only use a callback, so onComplete is required to
+ * use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.setDefaultCertificateForKey = function
+  (certificate, onComplete, onError)
+{
+  this.identityManager.setDefaultCertificateForKey
+    (certificate, onComplete, onError);
+};
+
+/**
+ * Get a certificate which is still valid with the specified name.
+ * @param {Name} certificateName The name of the requested certificate.
+ * @param {function} onComplete (optional) This calls onComplete(certificate)
+ * with the requested IdentityCertificate. If omitted, the return value is 
+ * described below. (Some crypto libraries only use a callback, so onComplete is
+ * required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {IdentityCertificate} If onComplete is omitted, return the requested
+ * certificate. Otherwise, if onComplete is supplied then return undefined and
+ * use onComplete as described above.
+ */
+KeyChain.prototype.getCertificate = function
+  (certificateName, onComplete, onError)
+{
+  return this.identityManager.getCertificate
+    (certificateName, onComplete, onError);
+};
+
+/**
+ * @deprecated Use getCertificate.
+ */
+KeyChain.prototype.getIdentityCertificate = function
+  (certificateName, onComplete, onError)
+{
+  return this.identityManager.getCertificate
+    (certificateName, onComplete, onError);
+};
+
+/**
+ * Revoke a key.
+ * @param {Name} keyName The name of the key that will be revoked.
+ */
+KeyChain.prototype.revokeKey = function(keyName)
+{
+  //TODO: Implement
+};
+
+/**
+ * Revoke a certificate.
+ * @param {Name} certificateName The name of the certificate that will be
+ * revoked.
+ */
+KeyChain.prototype.revokeCertificate = function(certificateName)
+{
+  //TODO: Implement
+};
+
+/**
+ * Get the identity manager given to or created by the constructor.
+ * @return {IdentityManager} The identity manager.
+ */
+KeyChain.prototype.getIdentityManager = function()
+{
+  return this.identityManager;
+};
+
+/*****************************************
+ *           Policy Management           *
+ *****************************************/
+
+/**
+ * Get the policy manager given to or created by the constructor.
+ * @return {PolicyManager} The policy manager.
+ */
+KeyChain.prototype.getPolicyManager = function()
+{
+  return this.policyManager;
+};
+
+/*****************************************
+ *              Sign/Verify              *
+ *****************************************/
+
+/**
+ * Sign the target. If it is a Data or Interest object, set its signature. If it
+ * is an array, produce a Signature object. There are two forms of sign:
+ * sign(target, certificateName [, wireFormat] [, onComplete] [, onError]).
+ * sign(target [, wireFormat] [, onComplete] [, onError]).
+ * @param {Data|Interest|Buffer} target If this is a Data object, wire encode for
+ * signing, update its signature and key locator field and wireEncoding. If this
+ * is an Interest object, wire encode for signing, append a SignatureInfo to the
+ * Interest name, sign the name components and append a final name component
+ * with the signature bits. If it is an array, sign it and produce a Signature
+ * object.
+ * @param {Name} certificateName (optional) The certificate name of the key to
+ * use for signing. If omitted, use the default identity in the identity storage.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {function} onComplete (optional) If target is a Data object, this calls
+ * onComplete(data) with the supplied Data object which has been modified to set
+ * its signature. If target is an Interest object, this calls
+ * onComplete(interest) with the supplied Interest object which has been
+ * modified to set its signature. If target is a Buffer, this calls
+ * onComplete(signature) where signature is the produced Signature object. If
+ * omitted, the return value is described below. (Some crypto libraries only use
+ * a callback, so onComplete is required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {Signature} If onComplete is omitted, return the generated Signature
+ * object (if target is a Buffer) or the target (if target is Data or Interest).
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete as
+ * described above.
+ */
+KeyChain.prototype.sign = function
+  (target, certificateName, wireFormat, onComplete, onError)
+{
+  var arg2 = certificateName;
+  var arg3 = wireFormat;
+  var arg4 = onComplete;
+  var arg5 = onError;
+  // arg2,            arg3,       arg4,       arg5
+  // certificateName, wireFormat, onComplete, onError
+  // certificateName, wireFormat, null,       null
+  // certificateName, onComplete, onError,    null
+  // certificateName, null,       null,       null
+  // wireFormat,      onComplete, onError,    null
+  // wireFormat,      null,       null,       null
+  // onComplete,      onError,    null,       null
+  // null,            null,       null,       null
+  if (arg2 instanceof Name)
+    certificateName = arg2;
+  else
+    certificateName = null;
+
+  if (arg2 instanceof WireFormat)
+    wireFormat = arg2;
+  else if (arg3 instanceof WireFormat)
+    wireFormat = arg3;
+  else
+    wireFormat = null;
+
+  if (typeof arg2 === "function") {
+    onComplete = arg2;
+    onError = arg3;
+  }
+  else if (typeof arg3 === "function") {
+    onComplete = arg3;
+    onError = arg4;
+  }
+  else if (typeof arg4 === "function") {
+    onComplete = arg4;
+    onError = arg5;
+  }
+  else {
+    onComplete = null;
+    onError = null;
+  }
+
+  return SyncPromise.complete(onComplete, onError,
+    this.signPromise(target, certificateName, wireFormat, !onComplete));
+};
+
+/**
+ * Sign the target. If it is a Data or Interest object, set its signature. If it
+ * is an array, produce a Signature object. There are two forms of signPromise:
+ * signPromise(target, certificateName [, wireFormat] [, useSync]).
+ * sign(target [, wireFormat] [, useSync]).
+ * @param {Data|Interest|Buffer} target If this is a Data object, wire encode for
+ * signing, update its signature and key locator field and wireEncoding. If this
+ * is an Interest object, wire encode for signing, append a SignatureInfo to the
+ * Interest name, sign the name components and append a final name component
+ * with the signature bits. If it is an array, sign it and produce a Signature
+ * object.
+ * @param {Name} certificateName (optional) The certificate name of the key to
+ * use for signing. If omitted, use the default identity in the identity storage.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the generated Signature
+ * object (if target is a Buffer) or the target (if target is Data or Interest).
+ */
+KeyChain.prototype.signPromise = function
+  (target, certificateName, wireFormat, useSync)
+{
+  var arg2 = certificateName;
+  var arg3 = wireFormat;
+  var arg4 = useSync;
+  // arg2,            arg3,       arg4
+  // certificateName, wireFormat, useSync
+  // certificateName, wireFormat, null
+  // certificateName, useSync,    null
+  // certificateName, null,       null
+  // wireFormat,      useSync,    null
+  // wireFormat,      null,       null
+  // useSync,         null,       null
+  // null,            null,       null
+  if (arg2 instanceof Name)
+    certificateName = arg2;
+  else
+    certificateName = null;
+
+  if (arg2 instanceof WireFormat)
+    wireFormat = arg2;
+  else if (arg3 instanceof WireFormat)
+    wireFormat = arg3;
+  else
+    wireFormat = null;
+
+  if (typeof arg2 === 'boolean')
+    useSync = arg2;
+  else if (typeof arg3 === 'boolean')
+    useSync = arg3;
+  else if (typeof arg4 === 'boolean')
+    useSync = arg4;
+  else
+    useSync = false;
+
+  var thisKeyChain = this;
+  return SyncPromise.resolve()
+  .then(function() {
+    if (certificateName != null)
+      return SyncPromise.resolve();
+
+    // Get the default certificate name.
+    return thisKeyChain.identityManager.getDefaultCertificatePromise(useSync)
+    .then(function(signingCertificate) {
+      if (signingCertificate != null) {
+        certificateName = signingCertificate.getName();
+        return SyncPromise.resolve();
+      }
+
+      // Set the default certificate and default certificate name again.
+      return thisKeyChain.prepareDefaultCertificateNamePromise_(useSync)
+      .then(function(localCertificateName) {
+        certificateName =localCertificateName;
+        return SyncPromise.resolve();
+      });
+    });
+  })
+  .then(function() {
+    // certificateName is now set. Do the actual signing.
+    if (target instanceof Interest)
+      return thisKeyChain.identityManager.signInterestByCertificatePromise
+        (target, certificateName, wireFormat, useSync);
+    else if (target instanceof Data)
+      return thisKeyChain.identityManager.signByCertificatePromise
+        (target, certificateName, wireFormat, useSync);
+    else
+      return thisKeyChain.identityManager.signByCertificatePromise
+        (target, certificateName, useSync);
+  });
+};
+
+/**
+ * Sign the target. If it is a Data object, set its signature. If it is an
+ * array, produce a signature object.
+ * @param {Data|Buffer} target If this is a Data object, wire encode for
+ * signing, update its signature and key locator field and wireEncoding. If it
+ * is an array, sign it and return a Signature object.
+ * @param {Name} identityName (optional) The identity name for the key to use for
+ * signing.  If omitted, infer the signing identity from the data packet name.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ * @param {function} onComplete (optional) If target is a Data object, this calls
+ * onComplete(data) with the supplied Data object which has been modified to set
+ * its signature. If target is a Buffer, this calls
+ * onComplete(signature) where signature is the produced Signature object. If
+ * omitted, the return value is described below. (Some crypto libraries only use
+ * a callback, so onComplete is required to use these.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * with the exception. If onComplete is defined but onError is undefined, then
+ * this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @return {Signature} If onComplete is omitted, return the generated Signature
+ * object (if target is a Buffer) or undefined (if target is Data).
+ * Otherwise, if onComplete is supplied then return undefined and use onComplete
+ * as described above.
+ */
+KeyChain.prototype.signByIdentity = function
+  (target, identityName, wireFormat, onComplete, onError)
+{
+  onError = (typeof wireFormat === "function") ? onComplete : onError;
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
+
+  var useSync = !onComplete;
+  var thisKeyChain = this;
+
+  if (identityName == null)
+    identityName = new Name();
+
+  if (target instanceof Data) {
+    var data = target;
+
+    var mainPromise = SyncPromise.resolve()
+    .then(function() {
+      if (identityName.size() == 0) {
+        var inferredIdentity = thisKeyChain.policyManager.inferSigningIdentity
+          (data.getName());
+        if (inferredIdentity.size() == 0)
+          return thisKeyChain.identityManager.getDefaultCertificateNamePromise
+            (useSync);
+        else
+          return thisKeyChain.identityManager.getDefaultCertificateNameForIdentityPromise
+              (inferredIdentity, useSync);
+      }
+      else
+        return thisKeyChain.identityManager.getDefaultCertificateNameForIdentityPromise
+          (identityName, useSync);
+    })
+    .then(function(signingCertificateName) {
+      if (signingCertificateName.size() == 0)
+        throw new SecurityException(new Error
+          ("No qualified certificate name found!"));
+
+      if (!thisKeyChain.policyManager.checkSigningPolicy
+           (data.getName(), signingCertificateName))
+        throw new SecurityException(new Error
+          ("Signing Cert name does not comply with signing policy"));
+
+      return thisKeyChain.identityManager.signByCertificatePromise
+        (data, signingCertificateName, wireFormat, useSync);
+    });
+
+    return SyncPromise.complete(onComplete, onError, mainPromise);
+  }
+  else {
+    var array = target;
+
+    return SyncPromise.complete(onComplete, onError,
+      this.identityManager.getDefaultCertificateNameForIdentityPromise
+        (identityName, useSync)
+      .then(function(signingCertificateName) {
+        if (signingCertificateName.size() == 0)
+          throw new SecurityException(new Error
+            ("No qualified certificate name found!"));
+
+        return thisKeyChain.identityManager.signByCertificatePromise
+          (array, signingCertificateName, wireFormat, useSync);
+      }));
+  }
+};
+
+/**
+ * Sign the target using DigestSha256.
+ * @param {Data|Interest} target If this is a Data object, wire encode for
+ * signing, digest it and set its SignatureInfo to a DigestSha256, updating its
+ * signature and wireEncoding. If this is an Interest object, wire encode for
+ * signing, append a SignatureInfo for DigestSha256 to the Interest name, digest
+ * the name components and append a final name component with the signature bits.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the input. If omitted, use WireFormat getDefaultWireFormat().
+ */
+KeyChain.prototype.signWithSha256 = function(target, wireFormat)
+{
+  if (target instanceof Interest)
+    this.identityManager.signInterestWithSha256(target, wireFormat);
+  else
+    this.identityManager.signWithSha256(target, wireFormat);
+};
+
+/**
+ * Check the signature on the Data object and call either onVerify or
+ * onValidationFailed. We use callback functions because verify may fetch
+ * information to check the signature.
+ * @param {Data} data The Data object with the signature to check.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(data).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(data, reason) with the Data object and reason string.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {number} stepCount
+ */
+KeyChain.prototype.verifyData = function
+  (data, onVerified, onValidationFailed, stepCount)
+{
+  if (stepCount == null)
+    stepCount = 0;
+
+  if (this.policyManager.requireVerify(data)) {
+    var nextStep = this.policyManager.checkVerificationPolicy
+      (data, stepCount, onVerified, onValidationFailed);
+    if (nextStep != null) {
+      var thisKeyChain = this;
+      this.face.expressInterest
+        (nextStep.interest,
+         function(callbackInterest, callbackData) {
+           thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
+         },
+         function(callbackInterest) {
+           thisKeyChain.onCertificateInterestTimeout
+             (callbackInterest, nextStep.retry, onValidationFailed, data, nextStep);
+         });
+    }
+  }
+  else if (this.policyManager.skipVerifyAndTrust(data)) {
+    try {
+      onVerified(data);
+    } catch (ex) {
+      console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+  else {
+    try {
+      onValidationFailed
+        (data, "The packet has no verify rule but skipVerifyAndTrust is false");
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Check the signature on the signed interest and call either onVerify or
+ * onValidationFailed. We use callback functions because verify may fetch
+ * information to check the signature.
+ * @param {Interest} interest The interest with the signature to check.
+ * @param {function} onVerified If the signature is verified, this calls
+ * onVerified(interest).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onValidationFailed If the signature check fails, this calls
+ * onValidationFailed(interest, reason) with the Interest object and reason
+ * string.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+KeyChain.prototype.verifyInterest = function
+  (interest, onVerified, onValidationFailed, stepCount, wireFormat)
+{
+  if (stepCount == null)
+    stepCount = 0;
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (this.policyManager.requireVerify(interest)) {
+    var nextStep = this.policyManager.checkVerificationPolicy
+      (interest, stepCount, onVerified, onValidationFailed, wireFormat);
+    if (nextStep != null) {
+      var thisKeyChain = this;
+      this.face.expressInterest
+        (nextStep.interest,
+         function(callbackInterest, callbackData) {
+           thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
+         },
+         function(callbackInterest) {
+           thisKeyChain.onCertificateInterestTimeout
+             (callbackInterest, nextStep.retry, onValidationFailed, interest,
+              nextStep);
+         });
+    }
+  }
+  else if (this.policyManager.skipVerifyAndTrust(interest)) {
+    try {
+      onVerified(interest);
+    } catch (ex) {
+      console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+  else {
+    try {
+      onValidationFailed
+        (interest,
+         "The packet has no verify rule but skipVerifyAndTrust is false");
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Set the Face which will be used to fetch required certificates.
+ * @param {Face} face A pointer to the Face object.
+ */
+KeyChain.prototype.setFace = function(face)
+{
+  this.face = face;
+};
+
+/**
+ * Wire encode the target, compute an HmacWithSha256 and update the signature
+ * value.
+ * Note: This method is an experimental feature. The API may change.
+ * @param {Data} target If this is a Data object, update its signature and wire
+ * encoding.
+ * @param {Blob} key The key for the HmacWithSha256.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the target. If omitted, use WireFormat getDefaultWireFormat().
+ */
+KeyChain.signWithHmacWithSha256 = function(target, key, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (target instanceof Data) {
+    var data = target;
+    // Encode once to get the signed portion.
+    var encoding = data.wireEncode(wireFormat);
+
+    var signer = Crypto.createHmac('sha256', key.buf());
+    signer.update(encoding.signedBuf());
+    data.getSignature().setSignature(
+      new Blob(signer.digest(), false));
+  }
+  else
+    throw new SecurityException(new Error
+      ("signWithHmacWithSha256: Unrecognized target type"));
+};
+
+/**
+ * Compute a new HmacWithSha256 for the target and verify it against the
+ * signature value.
+ * Note: This method is an experimental feature. The API may change.
+ * @param {Data} target The Data object to verify.
+ * @param {Blob} key The key for the HmacWithSha256.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the target. If omitted, use WireFormat getDefaultWireFormat().
+ * @return {boolean} True if the signature verifies, otherwise false.
+ */
+KeyChain.verifyDataWithHmacWithSha256 = function(data, key, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  // wireEncode returns the cached encoding if available.
+  var encoding = data.wireEncode(wireFormat);
+
+  var signer = Crypto.createHmac('sha256', key.buf());
+  signer.update(encoding.signedBuf());
+  var newSignatureBits = new Blob(signer.digest(), false);
+
+  // Use the flexible Blob.equals operator.
+  return newSignatureBits.equals(data.getSignature().getSignature());
+};
+
+KeyChain.DEFAULT_KEY_PARAMS = new RsaKeyParams();
+
+KeyChain.prototype.onCertificateData = function(interest, data, nextStep)
+{
+  // Try to verify the certificate (data) according to the parameters in nextStep.
+  this.verifyData
+    (data, nextStep.onVerified, nextStep.onValidationFailed, nextStep.stepCount);
+};
+
+KeyChain.prototype.onCertificateInterestTimeout = function
+  (interest, retry, onValidationFailed, originalDataOrInterest, nextStep)
+{
+  if (retry > 0) {
+    // Issue the same expressInterest as in verifyData except decrement retry.
+    var thisKeyChain = this;
+    this.face.expressInterest
+      (interest,
+       function(callbackInterest, callbackData) {
+         thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
+       },
+       function(callbackInterest) {
+         thisKeyChain.onCertificateInterestTimeout
+           (callbackInterest, retry - 1, onValidationFailed,
+            originalDataOrInterest, nextStep);
+       });
+  }
+  else {
+    try {
+      onValidationFailed
+        (originalDataOrInterest, "The retry count is zero after timeout for fetching " +
+          interest.getName().toUri());
+    } catch (ex) {
+      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Get the default certificate from the identity storage and return its name.
+ * If there is no default identity or default certificate, then create one.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the default certificate
+ * name.
+ */
+KeyChain.prototype.prepareDefaultCertificateNamePromise_ = function(useSync)
+{
+  var signingCertificate;
+  var thisKeyChain = this;
+  return this.identityManager.getDefaultCertificatePromise(useSync)
+  .then(function(localCertificate) {
+    signingCertificate = localCertificate;
+    if (signingCertificate != null)
+      return SyncPromise.resolve();
+
+    // Set the default certificate and get the certificate again.
+    return thisKeyChain.setDefaultCertificatePromise_(useSync)
+    .then(function() {
+      return thisKeyChain.identityManager.getDefaultCertificatePromise(useSync);
+    })
+    .then(function(localCertificate) {
+      signingCertificate = localCertificate;
+      return SyncPromise.resolve();
+    });
+  })
+  .then(function() {
+    return SyncPromise.resolve(signingCertificate.getName());
+  });
+}
+
+/**
+ * Create the default certificate if it is not initialized. If there is no
+ * default identity yet, creating a new tmp-identity.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that resolves when the default
+ * certificate is set.
+ */
+KeyChain.prototype.setDefaultCertificatePromise_ = function(useSync)
+{
+  var thisKeyChain = this;
+
+  return this.identityManager.getDefaultCertificatePromise(useSync)
+  .then(function(certificate) {
+    if (certificate != null)
+      // We already have a default certificate.
+      return SyncPromise.resolve();
+
+    var defaultIdentity;
+    return thisKeyChain.identityManager.getDefaultIdentityPromise(useSync)
+    .then(function(localDefaultIdentity) {
+      defaultIdentity = localDefaultIdentity;
+      return SyncPromise.resolve();
+    }, function(ex) {
+      // Create a default identity name.
+      randomComponent = Crypto.randomBytes(4);
+      defaultIdentity = new Name().append("tmp-identity")
+        .append(new Blob(randomComponent, false));
+
+      return SyncPromise.resolve();
+    })
+    .then(function() {
+      return thisKeyChain.identityManager.createIdentityAndCertificatePromise
+        (defaultIdentity, KeyChain.DEFAULT_KEY_PARAMS, useSync);
+    })
+    .then(function() {
+      return thisKeyChain.identityManager.setDefaultIdentityPromise
+        (defaultIdentity, useSync);
+    });
+  });
+};
+/**
+ * This class represents an Interest Exclude.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * Create a new Exclude.
+ * @constructor
+ * @param {Array<Name.Component|Buffer|Exclude.ANY>} values (optional) An array where each element is either a Name.Component, Buffer component or Exclude.ANY.
+ */
+var Exclude = function Exclude(values)
+{
+  this.values = [];
+
+  if (typeof values === 'object' && values instanceof Exclude)
+    // Copy the exclude.
+    this.values = values.values.slice(0);
+  else if (values) {
+    // Set the changeCount now since append expects it.
+    this.changeCount = 0;
+    for (var i = 0; i < values.length; ++i) {
+      if (values[i] == Exclude.ANY)
+        this.appendAny();
+      else
+        this.appendComponent(values[i]);
+    }
+  }
+
+  this.changeCount = 0;
+};
+
+exports.Exclude = Exclude;
+
+Exclude.ANY = "*";
+
+/**
+ * Get the number of entries.
+ * @return {number} The number of entries.
+ */
+Exclude.prototype.size = function() { return this.values.length; };
+
+/**
+ * Get the entry at the given index.
+ * @param {number} i The index of the entry, starting from 0.
+ * @return {Exclude.ANY|Name.Component} Exclude.ANY or a Name.Component.
+ */
+Exclude.prototype.get = function(i) { return this.values[i]; };
+
+/**
+ * Append an Exclude.ANY element.
+ * @return This Exclude so that you can chain calls to append.
+ */
+Exclude.prototype.appendAny = function()
+{
+  this.values.push(Exclude.ANY);
+  ++this.changeCount;
+  return this;
+};
+
+/**
+ * Append a component entry, copying from component.
+ * @param {Name.Component|Buffer} component
+ * @return This Exclude so that you can chain calls to append.
+ */
+Exclude.prototype.appendComponent = function(component)
+{
+  this.values.push(new Name.Component(component));
+  ++this.changeCount;
+  return this;
+};
+
+/**
+ * Clear all the entries.
+ */
+Exclude.prototype.clear = function()
+{
+  ++this.changeCount;
+  this.values = [];
+};
+
+/**
+ * Return a string with elements separated by "," and Exclude.ANY shown as "*".
+ */
+Exclude.prototype.toUri = function()
+{
+  if (this.values == null || this.values.length == 0)
+    return "";
+
+  var result = "";
+  for (var i = 0; i < this.values.length; ++i) {
+    if (i > 0)
+      result += ",";
+
+    if (this.values[i] == Exclude.ANY)
+      result += "*";
+    else
+      result += this.values[i].toEscapedString();
+  }
+  return result;
+};
+
+/**
+ * Return true if the component matches any of the exclude criteria.
+ */
+Exclude.prototype.matches = function(component)
+{
+  if (!(typeof component == 'object' && component instanceof Name.Component))
+    component = new Name.Component(component);
+
+  for (var i = 0; i < this.values.length; ++i) {
+    if (this.values[i] == Exclude.ANY) {
+      var lowerBound = null;
+      if (i > 0)
+        lowerBound = this.values[i - 1];
+
+      // Find the upper bound, possibly skipping over multiple ANY in a row.
+      var iUpperBound;
+      var upperBound = null;
+      for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
+        if (this.values[iUpperBound] != Exclude.ANY) {
+          upperBound = this.values[iUpperBound];
+          break;
+        }
+      }
+
+      // If lowerBound != null, we already checked component equals lowerBound on the last pass.
+      // If upperBound != null, we will check component equals upperBound on the next pass.
+      if (upperBound != null) {
+        if (lowerBound != null) {
+          if (component.compare(lowerBound) > 0 &&
+              component.compare(upperBound) < 0)
+            return true;
+        }
+        else {
+          if (component.compare(upperBound) < 0)
+            return true;
+        }
+
+        // Make i equal iUpperBound on the next pass.
+        i = iUpperBound - 1;
+      }
+      else {
+        if (lowerBound != null) {
+            if (component.compare(lowerBound) > 0)
+              return true;
+        }
+        else
+          // this.values has only ANY.
+          return true;
+      }
+    }
+    else {
+      if (component.equals(this.values[i]))
+        return true;
+    }
+  }
+
+  return false;
+};
+
+/**
+ * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
+ * A component is less if it is shorter, otherwise if equal length do a byte comparison.
+ */
+Exclude.compareComponents = function(component1, component2)
+{
+  if (typeof component1 == 'object' && component1 instanceof Name.Component)
+    component1 = component1.getValue().buf();
+  if (typeof component2 == 'object' && component2 instanceof Name.Component)
+    component2 = component2.getValue().buf();
+
+  return Name.Component.compareBuffers(component1, component2);
+};
+
+/**
+ * Get the change count, which is incremented each time this object is changed.
+ * @return {number} The change count.
+ */
+Exclude.prototype.getChangeCount = function()
+{
+  return this.changeCount;
+};
+/**
+ * This class represents Interest Objects
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cheraoui
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('./crypto.js'); /** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var SignedBlob = require('./util/signed-blob.js').SignedBlob; /** @ignore */
+var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var Exclude = require('./exclude.js').Exclude; /** @ignore */
+var Link = require('./link.js').Link; /** @ignore */
+var KeyLocator = require('./key-locator.js').KeyLocator; /** @ignore */
+var IncomingFaceId = require('./lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat;
+
+/**
+ * Create a new Interest with the optional values.
+ *
+ * @constructor
+ * @param {Name|Interest} nameOrInterest If this is an Interest, copy values from the interest and ignore the
+ * other arguments.  Otherwise this is the optional name for the new Interest.
+ * @param {number} minSuffixComponents
+ * @param {number} maxSuffixComponents
+ */
+var Interest = function Interest
+   (nameOrInterest, minSuffixComponents, maxSuffixComponents,
+    publisherPublicKeyDigest, exclude, childSelector, answerOriginKind, scope,
+    interestLifetimeMilliseconds, nonce)
+{
+  if (publisherPublicKeyDigest)
+    throw new Error
+      ("Interest constructor: PublisherPublicKeyDigest support has been removed.");
+  if (answerOriginKind)
+    throw new Error
+      ("Interest constructor: answerOriginKind support has been removed. Use setMustBeFresh().");
+  if (scope)
+    throw new Error("Interest constructor: scope support has been removed.");
+
+  if (typeof nameOrInterest === 'object' && nameOrInterest instanceof Interest) {
+    // Special case: this is a copy constructor.  Ignore all but the first argument.
+    var interest = nameOrInterest;
+    // Copy the name.
+    this.name_ = new ChangeCounter(new Name(interest.getName()));
+    this.maxSuffixComponents_ = interest.maxSuffixComponents_;
+    this.minSuffixComponents_ = interest.minSuffixComponents_;
+
+    this.keyLocator_ = new ChangeCounter(new KeyLocator(interest.getKeyLocator()));
+    this.exclude_ = new ChangeCounter(new Exclude(interest.getExclude()));
+    this.childSelector_ = interest.childSelector_;
+    this.mustBeFresh_ = interest.mustBeFresh_;
+    this.interestLifetimeMilliseconds_ = interest.interestLifetimeMilliseconds_;
+    this.nonce_ = interest.nonce_;
+    this.linkWireEncoding_ = interest.linkWireEncoding_;
+    this.linkWireEncodingFormat_ = interest.linkWireEncodingFormat_;
+    this.link_ = new ChangeCounter(null);
+    if (interest.link_.get() != null)
+      this.link_.set(new Link(interest.link_.get()));
+    this.selectedDelegationIndex_ = interest.selectedDelegationIndex_;
+    this.defaultWireEncoding_ = interest.getDefaultWireEncoding();
+    this.defaultWireEncodingFormat_ = interest.defaultWireEncodingFormat_;
+  }
+  else {
+    this.name_ = new ChangeCounter(typeof nameOrInterest === 'object' &&
+                                   nameOrInterest instanceof Name ?
+      new Name(nameOrInterest) : new Name());
+    this.maxSuffixComponents_ = maxSuffixComponents;
+    this.minSuffixComponents_ = minSuffixComponents;
+
+    this.keyLocator_ = new ChangeCounter(new KeyLocator());
+    this.exclude_ = new ChangeCounter(typeof exclude === 'object' && exclude instanceof Exclude ?
+      new Exclude(exclude) : new Exclude());
+    this.childSelector_ = childSelector;
+    this.mustBeFresh_ = true;
+    this.interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
+    this.nonce_ = typeof nonce === 'object' && nonce instanceof Blob ?
+      nonce : new Blob(nonce, true);
+    this.linkWireEncoding_ = new Blob();
+    this.linkWireEncodingFormat_ = null;
+    this.link_ = new ChangeCounter(null);
+    this.selectedDelegationIndex_ = null;
+    this.defaultWireEncoding_ = new SignedBlob();
+    this.defaultWireEncodingFormat_ = null;
+  }
+
+  this.getNonceChangeCount_ = 0;
+  this.getDefaultWireEncodingChangeCount_ = 0;
+  this.changeCount_ = 0;
+  this.lpPacket_ = null;
+};
+
+exports.Interest = Interest;
+
+Interest.RECURSIVE_POSTFIX = "*";
+
+Interest.CHILD_SELECTOR_LEFT = 0;
+Interest.CHILD_SELECTOR_RIGHT = 1;
+
+/**
+ * Check if this interest's name matches the given name (using Name.match) and
+ * the given name also conforms to the interest selectors.
+ * @param {Name} name The name to check.
+ * @return {boolean} True if the name and interest selectors match, False otherwise.
+ */
+Interest.prototype.matchesName = function(name)
+{
+  if (!this.getName().match(name))
+    return false;
+
+  if (this.minSuffixComponents_ != null &&
+      // Add 1 for the implicit digest.
+      !(name.size() + 1 - this.getName().size() >= this.minSuffixComponents_))
+    return false;
+  if (this.maxSuffixComponents_ != null &&
+      // Add 1 for the implicit digest.
+      !(name.size() + 1 - this.getName().size() <= this.maxSuffixComponents_))
+    return false;
+  if (this.getExclude() != null && name.size() > this.getName().size() &&
+      this.getExclude().matches(name.get(this.getName().size())))
+    return false;
+
+  return true;
+};
+
+/**
+ * @deprecated Use matchesName.
+ */
+Interest.prototype.matches_name = function(/*Name*/ name)
+{
+  return this.matchesName(name);
+};
+
+/**
+ * Check if the given Data packet can satisfy this Interest. This method
+ * considers the Name, MinSuffixComponents, MaxSuffixComponents,
+ * PublisherPublicKeyLocator, and Exclude. It does not consider the
+ * ChildSelector or MustBeFresh. This uses the given wireFormat to get the
+ * Data packet encoding for the full Name.
+ * @param {Data} data The Data packet to check.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the Data packet to get its full Name. If omitted, use
+ * WireFormat.getDefaultWireFormat().
+ * @return {boolean} True if the given Data packet can satisfy this Interest.
+ */
+Interest.prototype.matchesData = function(data, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  // Imitate ndn-cxx Interest::matchesData.
+  var interestNameLength = this.getName().size();
+  var dataName = data.getName();
+  var fullNameLength = dataName.size() + 1;
+
+  // Check MinSuffixComponents.
+  var hasMinSuffixComponents = (this.getMinSuffixComponents() != null);
+  var minSuffixComponents =
+    hasMinSuffixComponents ? this.getMinSuffixComponents() : 0;
+  if (!(interestNameLength + minSuffixComponents <= fullNameLength))
+    return false;
+
+  // Check MaxSuffixComponents.
+  var hasMaxSuffixComponents = (this.getMaxSuffixComponents() != null);
+  if (hasMaxSuffixComponents &&
+      !(interestNameLength + this.getMaxSuffixComponents() >= fullNameLength))
+    return false;
+
+  // Check the prefix.
+  if (interestNameLength === fullNameLength) {
+    if (this.getName().get(-1).isImplicitSha256Digest()) {
+      if (!this.getName().equals(data.getFullName(wireFormat)))
+        return false;
+    }
+    else
+      // The Interest Name is the same length as the Data full Name, but the
+      //   last component isn't a digest so there's no possibility of matching.
+      return false;
+  }
+  else {
+    // The Interest Name should be a strict prefix of the Data full Name.
+    if (!this.getName().isPrefixOf(dataName))
+      return false;
+  }
+
+  // Check the Exclude.
+  // The Exclude won't be violated if the Interest Name is the same as the
+  //   Data full Name.
+  if (this.getExclude().size() > 0 && fullNameLength > interestNameLength) {
+    if (interestNameLength == fullNameLength - 1) {
+      // The component to exclude is the digest.
+      if (this.getExclude().matches
+          (data.getFullName(wireFormat).get(interestNameLength)))
+        return false;
+    }
+    else {
+      // The component to exclude is not the digest.
+      if (this.getExclude().matches(dataName.get(interestNameLength)))
+        return false;
+    }
+  }
+
+  // Check the KeyLocator.
+  var publisherPublicKeyLocator = this.getKeyLocator();
+  if (publisherPublicKeyLocator.getType()) {
+    var signature = data.getSignature();
+    if (!KeyLocator.canGetFromSignature(signature))
+      // No KeyLocator in the Data packet.
+      return false;
+    if (!publisherPublicKeyLocator.equals
+        (KeyLocator.getFromSignature(signature)))
+      return false;
+  }
+
+  return true;
+};
+
+/**
+ * Return a new Interest with the same fields as this Interest.
+ */
+Interest.prototype.clone = function()
+{
+  return new Interest(this);
+};
+
+/**
+ * Get the interest Name.
+ * @return {Name} The name.  The name size() may be 0 if not specified.
+ */
+Interest.prototype.getName = function() { return this.name_.get(); };
+
+/**
+ * Get the min suffix components.
+ * @return {number} The min suffix components, or null if not specified.
+ */
+Interest.prototype.getMinSuffixComponents = function()
+{
+  return this.minSuffixComponents_;
+};
+
+/**
+ * Get the max suffix components.
+ * @return {number} The max suffix components, or null if not specified.
+ */
+Interest.prototype.getMaxSuffixComponents = function()
+{
+  return this.maxSuffixComponents_;
+};
+
+/**
+ * Get the interest key locator.
+ * @return {KeyLocator} The key locator. If its getType() is null,
+ * then the key locator is not specified.
+ */
+Interest.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_.get();
+};
+
+/**
+ * Get the exclude object.
+ * @return {Exclude} The exclude object. If the exclude size() is zero, then
+ * the exclude is not specified.
+ */
+Interest.prototype.getExclude = function() { return this.exclude_.get(); };
+
+/**
+ * Get the child selector.
+ * @return {number} The child selector, or null if not specified.
+ */
+Interest.prototype.getChildSelector = function()
+{
+  return this.childSelector_;
+};
+
+/**
+ * Get the must be fresh flag. If not specified, the default is true.
+ * @return {boolean} The must be fresh flag.
+ */
+Interest.prototype.getMustBeFresh = function()
+{
+  return this.mustBeFresh_;
+};
+
+/**
+ * Return the nonce value from the incoming interest.  If you change any of the
+ * fields in this Interest object, then the nonce value is cleared.
+ * @return {Blob} The nonce. If not specified, the value isNull().
+ */
+Interest.prototype.getNonce = function()
+{
+  if (this.getNonceChangeCount_ != this.getChangeCount()) {
+    // The values have changed, so the existing nonce is invalidated.
+    this.nonce_ = new Blob();
+    this.getNonceChangeCount_ = this.getChangeCount();
+  }
+
+  return this.nonce_;
+};
+
+/**
+ * @deprecated Use getNonce. This method returns a Buffer which is the former
+ * behavior of getNonce, and should only be used while updating your code.
+ */
+Interest.prototype.getNonceAsBuffer = function()
+{
+  return this.getNonce().buf();
+};
+
+/**
+ * Check if this interest has a link object (or a link wire encoding which
+ * can be decoded to make the link object).
+ * @return {boolean} True if this interest has a link object, false if not.
+ */
+Interest.prototype.hasLink = function()
+{
+  return this.link_.get() != null || !this.linkWireEncoding_.isNull();
+};
+
+/**
+ * Get the link object. If necessary, decode it from the link wire encoding.
+ * @return {Link} The link object, or null if not specified.
+ * @throws DecodingException For error decoding the link wire encoding (if
+ * necessary).
+ */
+Interest.prototype.getLink = function()
+{
+  if (this.link_.get() != null)
+    return this.link_.get();
+  else if (!this.linkWireEncoding_.isNull()) {
+    // Decode the link object from linkWireEncoding_.
+    var link = new Link();
+    link.wireDecode(this.linkWireEncoding_, this.linkWireEncodingFormat_);
+    this.link_.set(link);
+
+    // Clear linkWireEncoding_ since it is now managed by the link object.
+    this.linkWireEncoding_ = new Blob();
+    this.linkWireEncodingFormat_ = null;
+
+    return link;
+  }
+  else
+    return null;
+};
+
+/**
+ * Get the wire encoding of the link object. If there is already a wire
+ * encoding then return it. Otherwise encode from the link object (if
+ * available).
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * the Link. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The wire encoding, or an isNull Blob if the link is not
+ * specified.
+ */
+Interest.prototype.getLinkWireEncoding = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (!this.linkWireEncoding_.isNull() && this.linkWireEncodingFormat_ == wireFormat)
+    return this.linkWireEncoding_;
+
+  var link = this.getLink();
+  if (link != null)
+    return link.wireEncode(wireFormat);
+  else
+    return new Blob();
+};
+
+/**
+ * Get the selected delegation index.
+ * @return {number} The selected delegation index. If not specified, return null.
+ */
+Interest.prototype.getSelectedDelegationIndex = function()
+{
+  return this.selectedDelegationIndex_;
+};
+
+/**
+ * Get the interest lifetime.
+ * @return {number} The interest lifetime in milliseconds, or null if not
+ * specified.
+ */
+Interest.prototype.getInterestLifetimeMilliseconds = function()
+{
+  return this.interestLifetimeMilliseconds_;
+};
+
+/**
+ * Return the default wire encoding, which was encoded with
+ * getDefaultWireEncodingFormat().
+ * @return {SignedBlob} The default wire encoding, whose isNull() may be true
+ * if there is no default wire encoding.
+ */
+Interest.prototype.getDefaultWireEncoding = function()
+{
+  if (this.getDefaultWireEncodingChangeCount_ != this.getChangeCount()) {
+    // The values have changed, so the default wire encoding is invalidated.
+    this.defaultWireEncoding_ = new SignedBlob();
+    this.defaultWireEncodingFormat_ = null;
+    this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
+  }
+
+  return this.defaultWireEncoding_;
+};
+
+/**
+ * Get the WireFormat which is used by getDefaultWireEncoding().
+ * @return {WireFormat} The WireFormat, which is only meaningful if the
+ * getDefaultWireEncoding() is not isNull().
+ */
+Interest.prototype.getDefaultWireEncodingFormat = function()
+{
+  return this.defaultWireEncodingFormat_;
+};
+
+/**
+ * Get the incoming face ID according to the incoming packet header.
+ * @return {number} The incoming face ID. If not specified, return null.
+ */
+Interest.prototype.getIncomingFaceId = function()
+{
+  var field =
+    this.lpPacket_ === null ? null : IncomingFaceId.getFirstHeader(this.lpPacket_);
+  return field === null ? null : field.getFaceId();
+};
+
+/**
+ * Set the interest name.
+ * Note: You can also call getName and change the name values directly.
+ * @param {Name} name The interest name. This makes a copy of the name.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setName = function(name)
+{
+  this.name_.set(typeof name === 'object' && name instanceof Name ?
+    new Name(name) : new Name());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the min suffix components count.
+ * @param {number} minSuffixComponents The min suffix components count. If not
+ * specified, set to undefined.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setMinSuffixComponents = function(minSuffixComponents)
+{
+  this.minSuffixComponents_ = minSuffixComponents;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the max suffix components count.
+ * @param {number} maxSuffixComponents The max suffix components count. If not
+ * specified, set to undefined.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setMaxSuffixComponents = function(maxSuffixComponents)
+{
+  this.maxSuffixComponents_ = maxSuffixComponents;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set this interest to use a copy of the given KeyLocator object.
+ * Note: You can also call getKeyLocator and change the key locator directly.
+ * @param {KeyLocator} keyLocator The KeyLocator object. This makes a copy of the object.
+ * If no key locator is specified, set to a new default KeyLocator(), or to a
+ * KeyLocator with an unspecified type.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_.set
+    (typeof keyLocator === 'object' && keyLocator instanceof KeyLocator ?
+     new KeyLocator(keyLocator) : new KeyLocator());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set this interest to use a copy of the given exclude object. Note: You can
+ * also call getExclude and change the exclude entries directly.
+ * @param {Exclude} exclude The Exclude object. This makes a copy of the object.
+ * If no exclude is specified, set to a new default Exclude(), or to an Exclude
+ * with size() 0.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setExclude = function(exclude)
+{
+  this.exclude_.set(typeof exclude === 'object' && exclude instanceof Exclude ?
+    new Exclude(exclude) : new Exclude());
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the link wire encoding bytes, without decoding them. If there is
+ * a link object, set it to null. If you later call getLink(), it will
+ * decode the wireEncoding to create the link object.
+ * @param {Blob} encoding The Blob with the bytes of the link wire encoding.
+ * If no link is specified, set to an empty Blob() or call unsetLink().
+ * @param {WireFormat} wireFormat The wire format of the encoding, to be used
+ * later if necessary to decode. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setLinkWireEncoding = function(encoding, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  this.linkWireEncoding_ = encoding;
+  this.linkWireEncodingFormat_ = wireFormat;
+
+  // Clear the link object, assuming that it has a different encoding.
+  this.link_.set(null);
+
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Clear the link wire encoding and link object so that getLink() returns null.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.unsetLink = function()
+{
+  return this.setLinkWireEncoding(new Blob(), null);
+};
+
+/**
+ * Set the selected delegation index.
+ * @param {number} selectedDelegationIndex The selected delegation index. If not
+ * specified, set to null.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setSelectedDelegationIndex = function(selectedDelegationIndex)
+{
+  this.selectedDelegationIndex_ = selectedDelegationIndex;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the child selector.
+ * @param {number} childSelector The child selector. If not specified, set to
+ * undefined.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setChildSelector = function(childSelector)
+{
+  this.childSelector_ = childSelector;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the MustBeFresh flag.
+ * @param {boolean} mustBeFresh True if the content must be fresh, otherwise
+ * false. If you do not set this flag, the default value is true.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setMustBeFresh = function(mustBeFresh)
+{
+  this.mustBeFresh_ = (mustBeFresh ? true : false);
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * Set the interest lifetime.
+ * @param {number} interestLifetimeMilliseconds The interest lifetime in
+ * milliseconds. If not specified, set to undefined.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ */
+Interest.prototype.setInterestLifetimeMilliseconds = function(interestLifetimeMilliseconds)
+{
+  this.interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
+  ++this.changeCount_;
+  return this;
+};
+
+/**
+ * @deprecated You should let the wire encoder generate a random nonce
+ * internally before sending the interest.
+ */
+Interest.prototype.setNonce = function(nonce)
+{
+  this.nonce_ = typeof nonce === 'object' && nonce instanceof Blob ?
+    nonce : new Blob(nonce, true);
+  // Set getNonceChangeCount_ so that the next call to getNonce() won't clear
+  // this.nonce_.
+  ++this.changeCount_;
+  this.getNonceChangeCount_ = this.getChangeCount();
+  return this;
+};
+
+/**
+ * Encode the name according to the "NDN URI Scheme".  If there are interest selectors, append "?" and
+ * added the selectors as a query string.  For example "/test/name?ndn.ChildSelector=1".
+ * Note: This is an experimental feature.  See the API docs for more detail at
+ * http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .
+ * @return {string} The URI string.
+ */
+Interest.prototype.toUri = function()
+{
+  var selectors = "";
+
+  if (this.minSuffixComponents_ != null)
+    selectors += "&ndn.MinSuffixComponents=" + this.minSuffixComponents_;
+  if (this.maxSuffixComponents_ != null)
+    selectors += "&ndn.MaxSuffixComponents=" + this.maxSuffixComponents_;
+  if (this.childSelector_ != null)
+    selectors += "&ndn.ChildSelector=" + this.childSelector_;
+  selectors += "&ndn.MustBeFresh=" + (this.mustBeFresh_ ? 1 : 0);
+  if (this.interestLifetimeMilliseconds_ != null)
+    selectors += "&ndn.InterestLifetime=" + this.interestLifetimeMilliseconds_;
+  if (this.getNonce().size() > 0)
+    selectors += "&ndn.Nonce=" + Name.toEscapedString(this.getNonce().buf());
+  if (this.getExclude() != null && this.getExclude().size() > 0)
+    selectors += "&ndn.Exclude=" + this.getExclude().toUri();
+
+  var result = this.getName().toUri();
+  if (selectors != "")
+    // Replace the first & with ?.
+    result += "?" + selectors.substr(1);
+
+  return result;
+};
+
+/**
+ * Encode this Interest for a particular wire format. If wireFormat is the
+ * default wire format, also set the defaultWireEncoding field to the encoded
+ * result.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {SignedBlob} The encoded buffer in a SignedBlob object.
+ */
+Interest.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  if (!this.getDefaultWireEncoding().isNull() &&
+      this.getDefaultWireEncodingFormat() == wireFormat)
+    // We already have an encoding in the desired format.
+    return this.getDefaultWireEncoding();
+
+  var result = wireFormat.encodeInterest(this);
+  var wireEncoding = new SignedBlob
+    (result.encoding, result.signedPortionBeginOffset,
+     result.signedPortionEndOffset);
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // This is the default wire encoding.
+    this.setDefaultWireEncoding
+      (wireEncoding, WireFormat.getDefaultWireFormat());
+  return wireEncoding;
+};
+
+/**
+ * Decode the input using a particular wire format and update this Interest. If
+ * wireFormat is the default wire format, also set the defaultWireEncoding to
+ * another pointer to the input.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Interest.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var result;
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    result = wireFormat.decodeInterest(this, input.buf(), false);
+  else
+    result = wireFormat.decodeInterest(this, input, true);
+
+  if (wireFormat == WireFormat.getDefaultWireFormat())
+    // This is the default wire encoding.  In the Blob constructor, set copy
+    // true, but if input is already a Blob, it won't copy.
+    this.setDefaultWireEncoding(new SignedBlob
+      (new Blob(input, true), result.signedPortionBeginOffset,
+       result.signedPortionEndOffset),
+      WireFormat.getDefaultWireFormat());
+  else
+    this.setDefaultWireEncoding(new SignedBlob(), null);
+};
+
+/**
+ * Update the bytes of the nonce with new random values. This ensures that the
+ * new nonce value is different than the current one. If the current nonce is
+ * not specified, this does nothing.
+ */
+Interest.prototype.refreshNonce = function()
+{
+  var currentNonce = this.getNonce();
+  if (currentNonce.size() === 0)
+    return;
+
+  var newNonce;
+  while (true) {
+    newNonce = new Blob(Crypto.randomBytes(currentNonce.size()), false);
+    if (!newNonce.equals(currentNonce))
+      break;
+  }
+
+  this.nonce_ = newNonce;
+  // Set getNonceChangeCount_ so that the next call to getNonce() won't clear
+  // this.nonce_.
+  ++this.changeCount_;
+  this.getNonceChangeCount_ = this.getChangeCount();
+};
+
+/**
+ * An internal library method to set the LpPacket for an incoming packet. The
+ * application should not call this.
+ * @param {LpPacket} lpPacket The LpPacket. This does not make a copy.
+ * @return {Interest} This Interest so that you can chain calls to update values.
+ * @note This is an experimental feature. This API may change in the future.
+ */
+Interest.prototype.setLpPacket = function(lpPacket)
+{
+  this.lpPacket_ = lpPacket;
+  // Don't update changeCount_ since this doesn't affect the wire encoding.
+  return this;
+}
+
+/**
+ * Get the change count, which is incremented each time this object (or a child
+ * object) is changed.
+ * @return {number} The change count.
+ */
+Interest.prototype.getChangeCount = function()
+{
+  // Make sure each of the checkChanged is called.
+  var changed = this.name_.checkChanged();
+  changed = this.keyLocator_.checkChanged() || changed;
+  changed = this.exclude_.checkChanged() || changed;
+  if (changed)
+    // A child object has changed, so update the change count.
+    ++this.changeCount_;
+
+  return this.changeCount_;
+};
+
+Interest.prototype.setDefaultWireEncoding = function
+  (defaultWireEncoding, defaultWireEncodingFormat)
+{
+  this.defaultWireEncoding_ = defaultWireEncoding;
+  this.defaultWireEncodingFormat_ = defaultWireEncodingFormat;
+  // Set getDefaultWireEncodingChangeCount_ so that the next call to
+  // getDefaultWireEncoding() won't clear _defaultWireEncoding.
+  this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
+};
+
+// Define properties so we can change member variable types and implement changeCount_.
+Object.defineProperty(Interest.prototype, "name",
+  { get: function() { return this.getName(); },
+    set: function(val) { this.setName(val); } });
+Object.defineProperty(Interest.prototype, "minSuffixComponents",
+  { get: function() { return this.getMinSuffixComponents(); },
+    set: function(val) { this.setMinSuffixComponents(val); } });
+Object.defineProperty(Interest.prototype, "maxSuffixComponents",
+  { get: function() { return this.getMaxSuffixComponents(); },
+    set: function(val) { this.setMaxSuffixComponents(val); } });
+Object.defineProperty(Interest.prototype, "keyLocator",
+  { get: function() { return this.getKeyLocator(); },
+    set: function(val) { this.setKeyLocator(val); } });
+Object.defineProperty(Interest.prototype, "exclude",
+  { get: function() { return this.getExclude(); },
+    set: function(val) { this.setExclude(val); } });
+Object.defineProperty(Interest.prototype, "childSelector",
+  { get: function() { return this.getChildSelector(); },
+    set: function(val) { this.setChildSelector(val); } });
+/**
+ * @deprecated Use getInterestLifetimeMilliseconds and setInterestLifetimeMilliseconds.
+ */
+Object.defineProperty(Interest.prototype, "interestLifetime",
+  { get: function() { return this.getInterestLifetimeMilliseconds(); },
+    set: function(val) { this.setInterestLifetimeMilliseconds(val); } });
+/**
+ * @deprecated Use getNonce and setNonce.
+ */
+Object.defineProperty(Interest.prototype, "nonce",
+  { get: function() { return this.getNonceAsBuffer(); },
+    set: function(val) { this.setNonce(val); } });
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * A ForwardingFlags object holds the flags which specify how the forwarding daemon should forward an interest for
+ * a registered prefix.  We use a separate ForwardingFlags object to retain future compatibility if the daemon forwarding
+ * bits are changed, amended or deprecated.
+ * Create a new ForwardingFlags with "childInherit" set and all other flags cleared.
+ * @constructor
+ */
+var ForwardingFlags = function ForwardingFlags(value)
+{
+  if (typeof value === 'object' && value instanceof ForwardingFlags) {
+    // Make a copy.
+    this.childInherit = value.childInherit;
+    this.capture = value.capture;
+  }
+  else {
+    this.childInherit = true;
+    this.capture = false;
+  }
+};
+
+exports.ForwardingFlags = ForwardingFlags;
+
+ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT = 1;
+ForwardingFlags.NfdForwardingFlags_CAPTURE       = 2;
+
+/**
+ * Get an integer with the bits set according to the NFD forwarding flags as
+ * used in the ControlParameters of the command interest.
+ * @return {number} An integer with the bits set.
+ */
+ForwardingFlags.prototype.getNfdForwardingFlags = function()
+{
+  var result = 0;
+
+  if (this.childInherit)
+    result |= ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT;
+  if (this.capture)
+    result |= ForwardingFlags.NfdForwardingFlags_CAPTURE;
+
+  return result;
+};
+
+/**
+ * Set the flags according to the NFD forwarding flags as used in the
+ * ControlParameters of the command interest.
+ * @param {number} nfdForwardingFlags An integer with the bits set.
+ */
+ForwardingFlags.prototype.setNfdForwardingFlags = function(nfdForwardingFlags)
+{
+  this.childInherit =
+    ((nfdForwardingFlags & ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT) != 0);
+  this.capture =
+    ((nfdForwardingFlags & ForwardingFlags.NfdForwardingFlags_CAPTURE) != 0);
+};
+
+/**
+ * Get the value of the "childInherit" flag.
+ * @return {Boolean} true if the flag is set, false if it is cleared.
+ */
+ForwardingFlags.prototype.getChildInherit = function() { return this.childInherit; };
+
+/**
+ * Get the value of the "capture" flag.
+ * @return {Boolean} true if the flag is set, false if it is cleared.
+ */
+ForwardingFlags.prototype.getCapture = function() { return this.capture; };
+
+/**
+ * Set the value of the "childInherit" flag
+ * @param {number} value true to set the flag, false to clear it.
+ */
+ForwardingFlags.prototype.setChildInherit = function(value) { this.childInherit = value; };
+
+/**
+ * Set the value of the "capture" flag
+ * @param {number} value true to set the flag, false to clear it.
+ */
+ForwardingFlags.prototype.setCapture = function(value) { this.capture = value; };
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var ForwardingFlags = require('./forwarding-flags.js').ForwardingFlags; /** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * A ControlParameters which holds a Name and other fields for a
+ * ControlParameters which is used, for example, in the command interest to
+ * register a prefix with a forwarder. See
+ * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand#ControlParameters
+ * @constructor
+ */
+var ControlParameters = function ControlParameters(value)
+{
+  if (typeof value === 'object' && value instanceof ControlParameters) {
+    // Make a deep copy.
+    this.name = value.name == null ? null : new Name(value.name);
+    this.faceId = value.faceId;
+    this.uri = value.uri;
+    this.localControlFeature = value.localControlFeature;
+    this.origin = value.origin;
+    this.cost = value.cost;
+    this.forwardingFlags = new ForwardingFlags(value.forwardingFlags);
+    this.strategy = new Name(value.strategy);
+    this.expirationPeriod = value.expirationPeriod;
+  }
+  else {
+    this.name = null;
+    this.faceId = null;
+    this.uri = '';
+    this.localControlFeature = null;
+    this.origin = null;
+    this.cost = null;
+    this.forwardingFlags = new ForwardingFlags();
+    this.strategy = new Name();
+    this.expirationPeriod = null;
+  }
+};
+
+exports.ControlParameters = ControlParameters;
+
+ControlParameters.prototype.clear = function()
+{
+  this.name = null;
+  this.faceId = null;
+  this.uri = '';
+  this.localControlFeature = null;
+  this.origin = null;
+  this.cost = null;
+  this.forwardingFlags = new ForwardingFlags();
+  this.strategy = new Name();
+  this.expirationPeriod = null;
+};
+
+/**
+ * Encode this ControlParameters for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+ControlParameters.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeControlParameters(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this
+ * ControlParameters.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+ControlParameters.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeControlParameters(this, input.buf(), false);
+  else
+    wireFormat.decodeControlParameters(this, input, true);
+};
+
+/**
+ * Get the name.
+ * @return {Name} The name. If not specified, return null.
+ */
+ControlParameters.prototype.getName = function()
+{
+  return this.name;
+};
+
+/**
+ * Get the face ID.
+ * @return {number} The face ID, or null if not specified.
+ */
+ControlParameters.prototype.getFaceId = function()
+{
+  return this.faceId;
+};
+
+/**
+ * Get the URI.
+ * @return {string} The face URI, or an empty string if not specified.
+ */
+ControlParameters.prototype.getUri = function()
+{
+  return this.uri;
+};
+
+/**
+ * Get the local control feature value.
+ * @return {number} The local control feature value, or null if not specified.
+ */
+ControlParameters.prototype.getLocalControlFeature = function()
+{
+  return this.localControlFeature;
+};
+
+/**
+ * Get the origin value.
+ * @return {number} The origin value, or null if not specified.
+ */
+ControlParameters.prototype.getOrigin = function()
+{
+  return this.origin;
+};
+
+/**
+ * Get the cost value.
+ * @return {number} The cost value, or null if not specified.
+ */
+ControlParameters.prototype.getCost = function()
+{
+  return this.cost;
+};
+
+/**
+ * Get the ForwardingFlags object.
+ * @return {ForwardingFlags} The ForwardingFlags object.
+ */
+ControlParameters.prototype.getForwardingFlags = function()
+{
+  return this.forwardingFlags;
+};
+
+/**
+ * Get the strategy.
+ * @return {Name} The strategy or an empty Name
+ */
+ControlParameters.prototype.getStrategy = function()
+{
+  return this.strategy;
+};
+
+/**
+ * Get the expiration period.
+ * @return {number} The expiration period in milliseconds, or null if not specified.
+ */
+ControlParameters.prototype.getExpirationPeriod = function()
+{
+  return this.expirationPeriod;
+};
+
+/**
+ * Set the name.
+ * @param {Name} name The name. If not specified, set to null. If specified, this
+ * makes a copy of the name.
+ */
+ControlParameters.prototype.setName = function(name)
+{
+  this.name = typeof name === 'object' && name instanceof Name ?
+              new Name(name) : null;
+};
+
+/**
+ * Set the Face ID.
+ * @param {number} faceId The new face ID, or null for not specified.
+ */
+ControlParameters.prototype.setFaceId = function(faceId)
+{
+  this.faceId = faceId;
+};
+
+/**
+ * Set the URI.
+ * @param {string} uri The new uri, or an empty string for not specified.
+ */
+ControlParameters.prototype.setUri = function(uri)
+{
+  this.uri = uri || '';
+};
+
+/**
+ * Set the local control feature value.
+ * @param {number} localControlFeature The new local control feature value, or
+ * null for not specified.
+ */
+ControlParameters.prototype.setLocalControlFeature = function(localControlFeature)
+{
+  this.localControlFeature = localControlFeature;
+};
+
+/**
+ * Set the origin value.
+ * @param {number} origin The new origin value, or null for not specified.
+ */
+ControlParameters.prototype.setOrigin = function(origin)
+{
+  this.origin = origin;
+};
+
+/**
+ * Set the cost value.
+ * @param {number} cost The new cost value, or null for not specified.
+ */
+ControlParameters.prototype.setCost = function(cost)
+{
+  this.cost = cost;
+};
+
+/**
+ * Set the ForwardingFlags object to a copy of forwardingFlags. You can use
+ * getForwardingFlags() and change the existing ForwardingFlags object.
+ * @param {ForwardingFlags} forwardingFlags The new cost value, or null for not specified.
+ */
+ControlParameters.prototype.setForwardingFlags = function(forwardingFlags)
+{
+  this.forwardingFlags =
+    typeof forwardingFlags === 'object' && forwardingFlags instanceof ForwardingFlags ?
+      new ForwardingFlags(forwardingFlags) : new ForwardingFlags();
+};
+
+/**
+ * Set the strategy to a copy of the given Name.
+ * @param {Name} strategy The Name to copy, or an empty Name if not specified.
+ */
+ControlParameters.prototype.setStrategy = function(strategy)
+{
+  this.strategy = typeof strategy === 'object' && strategy instanceof Name ?
+              new Name(strategy) : new Name();
+};
+
+/**
+ * Set the expiration period.
+ * @param {number} expirationPeriod The expiration period in milliseconds, or
+ * null for not specified.
+ */
+ControlParameters.prototype.setExpirationPeriod = function(expirationPeriod)
+{
+  this.expirationPeriod = expirationPeriod;
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var ControlParameters = require('./control-parameters.js').ControlParameters; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var Blob = require('./util/blob.js').Blob;
+
+/**
+ * A ControlResponse holds a status code, status text and other fields for a
+ * ControlResponse which is used, for example, in the response from sending a
+ * register prefix control command to a forwarder.
+ * @see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ * @constructor
+ */
+var ControlResponse = function ControlResponse(value)
+{
+  if (typeof value === 'object' && value instanceof ControlResponse) {
+    // Make a deep copy.
+    this.statusCode_ = value.statusCode_;
+    this.statusText_ = value.statusText_;
+    this.bodyAsControlParameters_ = value.bodyAsControlParameters_ == null ? null
+      : new ControlParameters(value.bodyAsControlParameters_);
+  }
+  else {
+    this.statusCode_ = null;
+    this.statusText_ = "";
+    this.bodyAsControlParameters_ = null;
+  }
+};
+
+exports.ControlResponse = ControlResponse;
+
+ControlResponse.prototype.clear = function()
+{
+  this.statusCode_ = null;
+  this.statusText_ = "";
+  this.bodyAsControlParameters_ = null;
+};
+
+/**
+ * Encode this ControlResponse for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+ControlResponse.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeControlResponse(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this
+ * ControlResponse.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+ControlResponse.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeControlResponse(this, input.buf(), false);
+  else
+    wireFormat.decodeControlResponse(this, input, true);
+};
+
+/**
+ * Get the status code.
+ * @return {number} The status code. If not specified, return null.
+ */
+ControlResponse.prototype.getStatusCode = function()
+{
+  return this.statusCode_;
+};
+
+/**
+ * Get the status text.
+ * @return {string} The status text. If not specified, return "".
+ */
+ControlResponse.prototype.getStatusText = function()
+{
+  return this.statusText_;
+};
+
+/**
+ * Get the control response body as a ControlParameters.
+ * @return {ControlParameters} The ControlParameters, or null if the body is not
+ * specified or if it is not a ControlParameters.
+ */
+ControlResponse.prototype.getBodyAsControlParameters = function()
+{
+  return this.bodyAsControlParameters_;
+};
+
+/**
+ * Set the status code.
+ * @param statusCode {number} The status code. If not specified, set to null.
+ * @return {ControlResponse} This ControlResponse so that you can chain calls to
+ * update values.
+ */
+ControlResponse.prototype.setStatusCode = function(statusCode)
+{
+  this.statusCode_ = statusCode;
+  return this;
+};
+
+/**
+ * Set the status text.
+ * @param statusText {string} The status text. If not specified, set to "".
+ * @return {ControlResponse} This ControlResponse so that you can chain calls to
+ * update values.
+ */
+ControlResponse.prototype.setStatusText = function(statusText)
+{
+  this.statusText_ = statusText || "";
+  return this;
+};
+
+/**
+ * Set the control response body as a ControlParameters.
+ * @param {ControlParameters} controlParameters The ControlParameters for the
+ * body. This makes a copy of the ControlParameters. If not specified or if the
+ * body is not a ControlParameters, set to null.
+ * @return {ControlResponse} This ControlResponse so that you can chain calls to
+ * update values.
+ */
+ControlResponse.prototype.setBodyAsControlParameters = function(controlParameters)
+{
+  this.bodyAsControlParameters_ =
+    typeof controlParameters === 'object' && controlParameters instanceof ControlParameters ?
+      new ControlParameters(controlParameters) : null;
+  return this;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var NdnRegexMatcher = require('./util/ndn-regex-matcher.js').NdnRegexMatcher;
+
+/**
+ * An InterestFilter holds a Name prefix and optional regex match expression for
+ * use in Face.setInterestFilter.
+ *
+ * Create an InterestFilter to match any Interest whose name starts with the
+ * given prefix. If the optional regexFilter is provided then the remaining
+ * components match the regexFilter regular expression as described in doesMatch.
+ * @param {InterestFilter|Name|string} prefix If prefix is another
+ * InterestFilter copy its values. If prefix is a Name then this makes a copy of
+ * the Name. Otherwise this creates a Name from the URI string.
+ * @param {string} regexFilter (optional) The regular expression for matching
+ * the remaining name components.
+ * @constructor
+ */
+var InterestFilter = function InterestFilter(prefix, regexFilter)
+{
+  if (typeof prefix === 'object' && prefix instanceof InterestFilter) {
+    // The copy constructor.
+    var interestFilter = prefix;
+    this.prefix = new Name(interestFilter.prefix);
+    this.regexFilter = interestFilter.regexFilter;
+    this.regexFilterPattern = interestFilter.regexFilterPattern;
+  }
+  else {
+    this.prefix = new Name(prefix);
+    if (regexFilter) {
+      this.regexFilter = regexFilter;
+      this.regexFilterPattern = InterestFilter.makePattern(regexFilter);
+    }
+    else {
+      this.regexFilter = null;
+      this.regexFilterPattern = null;
+    }
+  }
+};
+
+exports.InterestFilter = InterestFilter;
+
+/**
+ * Check if the given name matches this filter. Match if name starts with this
+ * filter's prefix. If this filter has the optional regexFilter then the
+ * remaining components match the regexFilter regular expression.
+ * For example, the following InterestFilter:
+ *
+ *    InterestFilter("/hello", "<world><>+")
+ *
+ * will match all Interests, whose name has the prefix `/hello` which is
+ * followed by a component `world` and has at least one more component after it.
+ * Examples:
+ *
+ *    /hello/world/!
+ *    /hello/world/x/y/z
+ *
+ * Note that the regular expression will need to match all remaining components
+ * (e.g., there are implicit heading `^` and trailing `$` symbols in the
+ * regular expression).
+ * @param {Name} name The name to check against this filter.
+ * @return {boolean} True if name matches this filter, otherwise false.
+ */
+InterestFilter.prototype.doesMatch = function(name)
+{
+  if (name.size() < this.prefix.size())
+    return false;
+
+  if (this.hasRegexFilter()) {
+    // Perform a prefix match and regular expression match for the remaining
+    // components.
+    if (!this.prefix.match(name))
+      return false;
+
+    return null != NdnRegexMatcher.match
+      (this.regexFilterPattern, name.getSubName(this.prefix.size()));
+  }
+  else
+    // Just perform a prefix match.
+    return this.prefix.match(name);
+};
+
+/**
+ * Get the prefix given to the constructor.
+ * @return {Name} The prefix Name which you should not modify.
+ */
+InterestFilter.prototype.getPrefix = function() { return this.prefix; };
+
+/**
+ * Check if a regexFilter was supplied to the constructor.
+ * @return {boolean} True if a regexFilter was supplied to the constructor.
+ */
+InterestFilter.prototype.hasRegexFilter = function()
+{
+  return this.regexFilter != null;
+};
+
+/**
+ * Get the regex filter. This is only valid if hasRegexFilter() is true.
+ * @return {string} The regular expression for matching the remaining name
+ * components.
+ */
+InterestFilter.prototype.getRegexFilter = function() { return this.regexFilter; };
+
+/**
+ * If regexFilter doesn't already have them, add ^ to the beginning and $ to
+ * the end since these are required by NdnRegexMatcher.match.
+ * @param {string} regexFilter The regex filter.
+ * @return {string} The regex pattern with ^ and $.
+ */
+InterestFilter.makePattern = function(regexFilter)
+{
+  if (regexFilter.length == 0)
+    // We don't expect this.
+    return "^$";
+
+  var pattern = regexFilter;
+  if (pattern[0] != '^')
+    pattern = "^" + pattern;
+  if (pattern[pattern.length - 1] != '$')
+    pattern = pattern + "$";
+
+  return pattern;
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat;
+
+/**
+ * A DelegationSet holds a list of DelegationSet.Delegation entries which is
+ * used as the content of a Link instance. If you add elements with add(), then
+ * the list is a set sorted by preference number then by name. But wireDecode
+ * will add the elements from the wire encoding, preserving the given order and
+ * possible duplicates (in which case a DelegationSet really holds a "list" and
+ * not necessarily a "set").
+ *
+ * Create a new DelegationSet object, possibly copying values from another
+ * object.
+ *
+ * @param {DelegationSet} value (optional) If value is a DelegationSet, copy its
+ * values.
+ * @constructor
+ */
+var DelegationSet = function DelegationSet(value)
+{
+  if (typeof value === 'object' && value instanceof DelegationSet)
+    // Copy the list.
+    this.delegations_ = value.delegations_.slice(0);
+  else
+    this.delegations_ = []; // of DelegationSet.Delegation.
+};
+
+exports.DelegationSet = DelegationSet;
+
+/**
+ * A DelegationSet.Delegation holds a preference number and delegation name.
+ * Create a new DelegationSet.Delegation with the given values.
+ * @param {number} preference The preference number.
+ * @param {Name} name The delegation name. This makes a copy of the name.
+ * @constructor
+ */
+DelegationSet.Delegation = function DelegationSetDelegation(preference, name)
+{
+  this.preference_ = preference;
+  this.name_ = new Name(name);
+};
+
+/**
+ * Get the preference number.
+ * @return {number} The preference number.
+ */
+DelegationSet.Delegation.prototype.getPreference = function()
+{
+  return this.preference_;
+};
+
+/**
+ * Get the delegation name.
+ * @return {Name} The delegation name. NOTE: You must not change the name object -
+ * if you need to change it then make a copy.
+ */
+DelegationSet.Delegation.prototype.getName = function()
+{
+  return this.name_;
+};
+
+/**
+ * Compare this Delegation with other according to the ordering, based first
+ * on the preference number, then on the delegation name.
+ * @param {DelegationSet.Delegation} other The other Delegation to compare with.
+ * @return {number} 0 If they compare equal, -1 if this Delegation comes before
+ * other in the ordering, or 1 if this Delegation comes after.
+ */
+DelegationSet.Delegation.prototype.compare = function(other)
+{
+  if (this.preference_ < other.preference_)
+    return -1;
+  if (this.preference_ > other.preference_)
+    return 1;
+
+  return this.name_.compare(other.name_);
+};
+
+/**
+ * Add a new DelegationSet.Delegation to the list of delegations, sorted by
+ * preference number then by name. If there is already a delegation with the
+ * same name, update its preference, and remove any extra delegations with the
+ * same name.
+ * @param {number} preference The preference number.
+ * @param {Name} name The delegation name. This makes a copy of the name.
+ */
+DelegationSet.prototype.add = function(preference, name)
+{
+  this.remove(name);
+
+  var newDelegation = new DelegationSet.Delegation(preference, name);
+  // Find the index of the first entry where it is not less than newDelegation.
+  var i = 0;
+  while (i < this.delegations_.length) {
+    if (this.delegations_[i].compare(newDelegation) >= 0)
+      break;
+
+    ++i;
+  }
+
+  this.delegations_.splice(i, 0, newDelegation);
+};
+
+/**
+ * Add a new DelegationSet.Delegation to the end of the list of delegations,
+ * without sorting or updating any existing entries. This is useful for adding
+ * preferences from a wire encoding, preserving the supplied ordering and
+ * possible duplicates.
+ * @param {number} preference The preference number.
+ * @param {Name} name The delegation name. This makes a copy of the name.
+ */
+DelegationSet.prototype.addUnsorted = function(preference, name)
+{
+  this.delegations_.push(new DelegationSet.Delegation(preference, name));
+};
+
+/**
+ * Remove every DelegationSet.Delegation with the given name.
+ * @param {Name} name The name to match the name of the delegation(s) to be
+ * removed.
+ * @return {boolean} True if a DelegationSet.Delegation was removed, otherwise
+ * false.
+ */
+DelegationSet.prototype.remove = function(name)
+{
+  var wasRemoved = false;
+  // Go backwards through the list so we can remove entries.
+  for (var i = this.delegations_.length - 1; i >= 0; --i) {
+    if (this.delegations_[i].getName().equals(name)) {
+      wasRemoved = true;
+      this.delegations_.splice(i, 1);
+    }
+  }
+
+  return wasRemoved;
+};
+
+/**
+ * Clear the list of delegations.
+ */
+DelegationSet.prototype.clear = function() { this.delegations_ = []; };
+
+/**
+ * Get the number of delegation entries.
+ * @return {number} The number of delegation entries.
+ */
+DelegationSet.prototype.size = function() { return this.delegations_.length; };
+
+/**
+ * Get the delegation at the given index, according to the ordering described
+ * in add().
+ * @param {number} i The index of the component, starting from 0.
+ * @return {DelegationSet.Delegation} The delegation at the index.
+ */
+DelegationSet.prototype.get = function(i) { return this.delegations_[i]; };
+
+/**
+ * Find the first delegation with the given name and return its index.
+ * @param {Name} name Then name of the delegation to find.
+ * @return {number} The index of the delegation, or -1 if not found.
+ */
+DelegationSet.prototype.find = function(name)
+{
+  for (var i = 0; i < this.delegations_.length; ++i) {
+    if (this.delegations_[i].getName().equals(name))
+      return i;
+  }
+
+  return -1;
+};
+
+/**
+ * Encode this DelegationSet for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+DelegationSet.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeDelegationSet(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this DelegationSet.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+DelegationSet.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeDelegationSet(this, input.buf(), false);
+  else
+    wireFormat.decodeDelegationSet(this, input, true);
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DelegationSet = require('./delegation-set.js').DelegationSet; /** @ignore */
+var ContentType = require('./meta-info.js').ContentType; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var Data = require('./data.js').Data;
+
+/**
+ * The Link class extends Data and represents a Link instance where the Data
+ * content is an encoded delegation set. The format is defined in "link.pdf"
+ * attached to Redmine issue http://redmine.named-data.net/issues/2587 .
+ *
+ * Create a new Link with the optional values. There are 3 forms of the constructor:
+ * Link(name);
+ * Link(data);
+ * Link();
+ * @param {Name} name The name for constructing the base Data.
+ * @param {Data} data The Data object to copy values from. If the content can be
+ * decoded using the default wire encoding, then update the list of delegations.
+ * @constructor
+ */
+var Link = function Link(value)
+{
+  this.delegations_ = new DelegationSet();
+
+  if (value instanceof Data) {
+    // Call the base constructor.
+    Data.call(this, value);
+
+    if (!this.getContent().isNull()) {
+      try {
+        this.delegations_.wireDecode(this.getContent());
+        this.getMetaInfo().setType(ContentType.LINK);
+      }
+      catch (ex) {
+        this.delegations_.clear();
+      }
+    }
+  }
+  else {
+    if (value != undefined)
+      // value is a Name.
+      Data.call(this, value);
+    else
+      Data.call(this);
+
+    this.getMetaInfo().setType(ContentType.LINK);
+  }
+};
+
+Link.prototype = new Data();
+Link.prototype.name = "Link";
+
+exports.Link = Link;
+
+/**
+ * Override to call the base class wireDecode then populate the list of
+ * delegations from the content.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+Link.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  Data.prototype.wireDecode.call(this, input, wireFormat);
+  if (this.getMetaInfo().getType() != ContentType.LINK)
+    throw new Error
+      ("Link.wireDecode: MetaInfo ContentType is not LINK.");
+
+  this.delegations_.wireDecode(this.getContent());
+};
+
+/**
+ * Add a new delegation to the list of delegations, sorted by preference number
+ * then by name. Re-encode this object's content using the optional wireFormat.
+ * @param {number} preference The preference number.
+ * @param {Name} name The delegation name. This makes a copy of the name. If
+ * there is already a delegation with the same name, this updates its preference.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the DelegationSet. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Link} This Link so that you can chain calls to update values.
+ */
+Link.prototype.addDelegation = function(preference, name, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  this.delegations_.add(preference, name);
+  this.encodeContent(wireFormat);
+
+  return this;
+};
+
+/**
+ * Remove every delegation with the given name. Re-encode this object's content
+ * using the optional wireFormat.
+ * @param {Name} name Then name to match the name of the delegation(s) to be
+ * removed.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the DelegationSet. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {boolean} True if a delegation was removed, otherwise false.
+ */
+Link.prototype.removeDelegation = function(name, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var wasRemoved = this.delegations_.remove(name);
+  if (wasRemoved)
+    this.encodeContent(wireFormat);
+
+  return wasRemoved;
+};
+
+/**
+ * Get the list of delegation for read only.
+ * @return {DelegationSet} The list of delegation, which you should treat as
+ * read-only. To modify it, call Link.addDelegation, etc.
+ */
+Link.prototype.getDelegations = function() { return this.delegations_; };
+
+/**
+ * A private method to encode the delegations_ and set this object's content.
+ * Also set the meta info content type to LINK.
+ * @param {WireFormat} wireFormat A WireFormat object used to encode the
+ * DelegationSet.
+ */
+Link.prototype.encodeContent = function(wireFormat)
+{
+  this.setContent(this.delegations_.wireEncode(wireFormat));
+  this.getMetaInfo().setType(ContentType.LINK);
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-cxx nack.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/nack.hpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * NetworkNack represents a network Nack packet and includes a Nack reason.
+ * @constructor
+ */
+var NetworkNack = function NetworkNack()
+{
+  this.reason_ = NetworkNack.Reason.NONE;
+  this.otherReasonCode_ = -1;
+};
+
+exports.NetworkNack = NetworkNack;
+
+/**
+ * A NetworkNack.Reason specifies the reason in a NetworkNack packet. If the
+ * reason code in the packet is not a recognized enum value, then we use
+ * Reason.OTHER_CODE and you can call getOtherReasonCode(). We do this to keep
+ * the recognized reason values independent of packet encoding formats.
+ */
+NetworkNack.Reason = {
+  NONE:         0,
+  CONGESTION:  50,
+  DUPLICATE:  100,
+  NO_ROUTE:   150,
+  OTHER_CODE: 0x7fff
+};
+
+/**
+ * Get the network Nack reason.
+ * @return {number} The reason enum value from NetworkNack.Reason. If this is
+ * Reason.OTHER_CODE, then call getOtherReasonCode() to get the unrecognized
+ * reason code.
+ */
+NetworkNack.prototype.getReason = function() { return this.reason_; };
+
+/**
+ * Get the reason code from the packet which is other than a recognized
+ * Reason enum value. This is only meaningful if getReason() is
+ * Reason.OTHER_CODE.
+ * @return {number} The reason code.
+ */
+NetworkNack.prototype.getOtherReasonCode = function()
+{ 
+  return this.otherReasonCode_;
+};
+
+/**
+ * Set the network Nack reason.
+ * @param {number} reason The network Nack reason enum value from 
+ * NetworkNack.Reason. If the packet's reason code is not a recognized Reason
+ * enum value, use Reason.OTHER_CODE and call setOtherReasonCode().
+ */
+NetworkNack.prototype.setReason = function(reason) { this.reason_ = reason; };
+
+/**
+ * Set the packet's reason code to use when the reason enum is
+ * Reason.OTHER_CODE. If the packet's reason code is a recognized enum value,
+ * just call setReason().
+ * @param {number} otherReasonCode The packet's unrecognized reason code, which
+ * must be non-negative.
+ */
+NetworkNack.prototype.setOtherReasonCode = function(otherReasonCode)
+{
+  if (otherReasonCode < 0)
+    throw new Error("NetworkNack other reason code must be non-negative");
+  this.otherReasonCode_ = otherReasonCode;
+};
+
+/**
+ * Get the first header field in lpPacket which is a NetworkNack. This is
+ * an internal method which the application normally would not use.
+ * @param {LpPacket} lpPacket The LpPacket with the header fields to search.
+ * @return {NetworkNack} The first NetworkNack header field, or null if not
+ * found.
+ */
+NetworkNack.getFirstHeader = function(lpPacket)
+{
+  for (var i = 0; i < lpPacket.countHeaderFields(); ++i) {
+    var field = lpPacket.getHeaderField(i);
+    if (field instanceof NetworkNack)
+      return field;
+  }
+
+  return null;
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('../crypto.js'); /** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var ForwardingFlags = require('../forwarding-flags').ForwardingFlags; /** @ignore */
+var Tlv = require('./tlv/tlv.js').Tlv; /** @ignore */
+var TlvEncoder = require('./tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
+var TlvDecoder = require('./tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
+var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
+var Exclude = require('../exclude.js').Exclude; /** @ignore */
+var ContentType = require('../meta-info.js').ContentType; /** @ignore */
+var KeyLocatorType = require('../key-locator.js').KeyLocatorType; /** @ignore */
+var Sha256WithRsaSignature = require('../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var Sha256WithEcdsaSignature = require('../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
+var GenericSignature = require('../generic-signature.js').GenericSignature; /** @ignore */
+var HmacWithSha256Signature = require('../hmac-with-sha256-signature.js').HmacWithSha256Signature; /** @ignore */
+var DigestSha256Signature = require('../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
+var ControlParameters = require('../control-parameters.js').ControlParameters; /** @ignore */
+var ForwardingFlags = require('../forwarding-flags.js').ForwardingFlags; /** @ignore */
+var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
+var IncomingFaceId = require('../lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
+var DecodingException = require('./decoding-exception.js').DecodingException;
+
+/**
+ * A Tlv0_2WireFormat implements the WireFormat interface for encoding and
+ * decoding with the NDN-TLV wire format, version 0.2.
+ * @constructor
+ */
+var Tlv0_2WireFormat = function Tlv0_2WireFormat()
+{
+  // Inherit from WireFormat.
+  WireFormat.call(this);
+};
+
+Tlv0_2WireFormat.prototype = new WireFormat();
+Tlv0_2WireFormat.prototype.name = "Tlv0_2WireFormat";
+
+exports.Tlv0_2WireFormat = Tlv0_2WireFormat;
+
+// Default object.
+Tlv0_2WireFormat.instance = null;
+
+/**
+ * Encode name as an NDN-TLV Name and return the encoding.
+ * @param {Name} name The Name to encode.
+ * @return {Blobl} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeName = function(name)
+{
+  var encoder = new TlvEncoder();
+  Tlv0_2WireFormat.encodeName(name, encoder);
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode input as a NDN-TLV name and set the fields of the Name object.
+ * @param {Name} name The Name object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ */
+Tlv0_2WireFormat.prototype.decodeName = function(name, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  Tlv0_2WireFormat.decodeName(name, decoder, copy);
+};
+
+/**
+ * Encode the interest using NDN-TLV and return a Buffer.
+ * @param {Interest} interest The Interest object to encode.
+ * @return {object} An associative array with fields
+ * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
+ * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
+ * the encoding of the beginning of the signed portion, and
+ * signedPortionEndOffset is the offset in the encoding of the end of the signed
+ * portion. The signed portion starts from the first name component and ends
+ * just before the final name component (which is assumed to be a signature for
+ * a signed interest).
+ */
+Tlv0_2WireFormat.prototype.encodeInterest = function(interest)
+{
+  var encoder = new TlvEncoder(256);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.SelectedDelegation, interest.getSelectedDelegationIndex());
+  var linkWireEncoding = interest.getLinkWireEncoding(this);
+  if (!linkWireEncoding.isNull())
+    // Encode the entire link as is.
+    encoder.writeBuffer(linkWireEncoding.buf());
+
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.InterestLifetime, interest.getInterestLifetimeMilliseconds());
+
+  // Encode the Nonce as 4 bytes.
+  if (interest.getNonce().isNull() || interest.getNonce().size() == 0)
+    // This is the most common case. Generate a nonce.
+    encoder.writeBlobTlv(Tlv.Nonce, Crypto.randomBytes(4));
+  else if (interest.getNonce().size() < 4) {
+    var nonce = Buffer(4);
+    // Copy existing nonce bytes.
+    interest.getNonce().buf().copy(nonce);
+
+    // Generate random bytes for remaining bytes in the nonce.
+    for (var i = interest.getNonce().size(); i < 4; ++i)
+      nonce[i] = Crypto.randomBytes(1)[0];
+
+    encoder.writeBlobTlv(Tlv.Nonce, nonce);
+  }
+  else if (interest.getNonce().size() == 4)
+    // Use the nonce as-is.
+    encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().buf());
+  else
+    // Truncate.
+    encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().buf().slice(0, 4));
+
+  Tlv0_2WireFormat.encodeSelectors(interest, encoder);
+  var tempOffsets = Tlv0_2WireFormat.encodeName(interest.getName(), encoder);
+  var signedPortionBeginOffsetFromBack =
+    encoder.getLength() - tempOffsets.signedPortionBeginOffset;
+  var signedPortionEndOffsetFromBack =
+    encoder.getLength() - tempOffsets.signedPortionEndOffset;
+
+  encoder.writeTypeAndLength(Tlv.Interest, encoder.getLength() - saveLength);
+  var signedPortionBeginOffset =
+    encoder.getLength() - signedPortionBeginOffsetFromBack;
+  var signedPortionEndOffset =
+    encoder.getLength() - signedPortionEndOffsetFromBack;
+
+  return { encoding: new Blob(encoder.getOutput(), false),
+           signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Decode input as an NDN-TLV interest and set the fields of the interest
+ * object.
+ * @param {Interest} interest The Interest object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion. The signed portion starts from the first
+ * name component and ends just before the final name component (which is
+ * assumed to be a signature for a signed interest).
+ */
+Tlv0_2WireFormat.prototype.decodeInterest = function(interest, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Interest);
+  var offsets = Tlv0_2WireFormat.decodeName(interest.getName(), decoder, copy);
+  if (decoder.peekType(Tlv.Selectors, endOffset))
+    Tlv0_2WireFormat.decodeSelectors(interest, decoder, copy);
+  // Require a Nonce, but don't force it to be 4 bytes.
+  var nonce = decoder.readBlobTlv(Tlv.Nonce);
+  interest.setInterestLifetimeMilliseconds
+    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime, endOffset));
+
+  if (decoder.peekType(Tlv.Data, endOffset)) {
+    // Get the bytes of the Link TLV.
+    var linkBeginOffset = decoder.getOffset();
+    var linkEndOffset = decoder.readNestedTlvsStart(Tlv.Data);
+    decoder.seek(linkEndOffset);
+
+    interest.setLinkWireEncoding
+      (new Blob(decoder.getSlice(linkBeginOffset, linkEndOffset), copy), this);
+  }
+  else
+    interest.unsetLink();
+  interest.setSelectedDelegationIndex
+    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.SelectedDelegation, endOffset));
+  if (interest.getSelectedDelegationIndex() != null &&
+      interest.getSelectedDelegationIndex() >= 0 && !interest.hasLink())
+    throw new Error("Interest has a selected delegation, but no link object");
+
+  // Set the nonce last because setting other interest fields clears it.
+  interest.setNonce(new Blob(nonce, copy));
+
+  decoder.finishNestedTlvs(endOffset);
+  return offsets;
+};
+
+/**
+ * Encode data as NDN-TLV and return the encoding and signed offsets.
+ * @param {Data} data The Data object to encode.
+ * @return {object} An associative array with fields
+ * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
+ * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
+ * the encoding of the beginning of the signed portion, and
+ * signedPortionEndOffset is the offset in the encoding of the end of the
+ * signed portion.
+ */
+Tlv0_2WireFormat.prototype.encodeData = function(data)
+{
+  var encoder = new TlvEncoder(1500);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  encoder.writeBlobTlv(Tlv.SignatureValue, data.getSignature().getSignature().buf());
+  var signedPortionEndOffsetFromBack = encoder.getLength();
+
+  Tlv0_2WireFormat.encodeSignatureInfo_(data.getSignature(), encoder);
+  encoder.writeBlobTlv(Tlv.Content, data.getContent().buf());
+  Tlv0_2WireFormat.encodeMetaInfo(data.getMetaInfo(), encoder);
+  Tlv0_2WireFormat.encodeName(data.getName(), encoder);
+  var signedPortionBeginOffsetFromBack = encoder.getLength();
+
+  encoder.writeTypeAndLength(Tlv.Data, encoder.getLength() - saveLength);
+  var signedPortionBeginOffset =
+    encoder.getLength() - signedPortionBeginOffsetFromBack;
+  var signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;
+
+  return { encoding: new Blob(encoder.getOutput(), false),
+           signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Decode input as an NDN-TLV data packet, set the fields in the data object,
+ * and return the signed offsets.
+ * @param {Data} data The Data object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion.
+ */
+Tlv0_2WireFormat.prototype.decodeData = function(data, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Data);
+  var signedPortionBeginOffset = decoder.getOffset();
+
+  Tlv0_2WireFormat.decodeName(data.getName(), decoder, copy);
+  Tlv0_2WireFormat.decodeMetaInfo(data.getMetaInfo(), decoder, copy);
+  data.setContent(new Blob(decoder.readBlobTlv(Tlv.Content), copy));
+  Tlv0_2WireFormat.decodeSignatureInfo(data, decoder, copy);
+
+  var signedPortionEndOffset = decoder.getOffset();
+  data.getSignature().setSignature
+    (new Blob(decoder.readBlobTlv(Tlv.SignatureValue), copy));
+
+  decoder.finishNestedTlvs(endOffset);
+  return { signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Encode controlParameters as NDN-TLV and return the encoding.
+ * @param {ControlParameters} controlParameters The ControlParameters object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeControlParameters = function(controlParameters)
+{
+  var encoder = new TlvEncoder(256);
+  Tlv0_2WireFormat.encodeControlParameters(controlParameters, encoder);
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+  * Decode controlParameters in NDN-TLV and return the encoding.
+  * @param {ControlParameters} controlParameters The ControlParameters object to
+  * encode.
+  * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+  * @throws DecodingException For invalid encoding
+  */
+Tlv0_2WireFormat.prototype.decodeControlParameters = function
+  (controlParameters, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  Tlv0_2WireFormat.decodeControlParameters(controlParameters, decoder, copy);
+};
+
+/**
+ * Encode controlResponse as NDN-TLV and return the encoding.
+ * @param {ControlResponse} controlResponse The ControlResponse object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeControlResponse = function(controlResponse)
+{
+  var encoder = new TlvEncoder(256);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+
+  // Encode the body.
+  if (controlResponse.getBodyAsControlParameters() != null)
+    Tlv0_2WireFormat.encodeControlParameters
+      (controlResponse.getBodyAsControlParameters(), encoder);
+
+  encoder.writeBlobTlv
+    (Tlv.NfdCommand_StatusText, new Blob(controlResponse.getStatusText()).buf());
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.NfdCommand_StatusCode, controlResponse.getStatusCode());
+
+  encoder.writeTypeAndLength
+    (Tlv.NfdCommand_ControlResponse, encoder.getLength() - saveLength);
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode controlResponse in NDN-TLV and return the encoding.
+ * @param {ControlResponse} controlResponse The ControlResponse object to
+ * encode.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @throws DecodingException For invalid encoding
+ */
+Tlv0_2WireFormat.prototype.decodeControlResponse = function
+  (controlResponse, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  var endOffset = decoder.readNestedTlvsStart(Tlv.NfdCommand_ControlResponse);
+
+  controlResponse.setStatusCode(decoder.readNonNegativeIntegerTlv
+    (Tlv.NfdCommand_StatusCode));
+  // Set copy false since we just immediately get a string.
+  var statusText = new Blob
+    (decoder.readBlobTlv(Tlv.NfdCommand_StatusText), false);
+  controlResponse.setStatusText(statusText.toString());
+
+  // Decode the body.
+  if (decoder.peekType(Tlv.ControlParameters_ControlParameters, endOffset)) {
+    controlResponse.setBodyAsControlParameters(new ControlParameters());
+    // Decode into the existing ControlParameters to avoid copying.
+    Tlv0_2WireFormat.decodeControlParameters
+      (controlResponse.getBodyAsControlParameters(), decoder, copy);
+  }
+  else
+    controlResponse.setBodyAsControlParameters(null);
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * Encode signature as an NDN-TLV SignatureInfo and return the encoding.
+ * @param {Signature} signature An object of a subclass of Signature to encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeSignatureInfo = function(signature)
+{
+  var encoder = new TlvEncoder(256);
+  Tlv0_2WireFormat.encodeSignatureInfo_(signature, encoder);
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+// SignatureHolder is used by decodeSignatureInfoAndValue.
+Tlv0_2WireFormat.SignatureHolder = function Tlv0_2WireFormatSignatureHolder()
+{
+};
+
+Tlv0_2WireFormat.SignatureHolder.prototype.setSignature = function(signature)
+{
+  this.signature = signature;
+};
+
+Tlv0_2WireFormat.SignatureHolder.prototype.getSignature = function()
+{
+  return this.signature;
+};
+
+/**
+ * Decode signatureInfo as an NDN-TLV SignatureInfo and signatureValue as the
+ * related SignatureValue, and return a new object which is a subclass of Signature.
+ * @param {Buffer} signatureInfo The buffer with the signature info bytes to
+ * decode.
+ * @param {Buffer} signatureValue The buffer with the signature value to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {Signature} A new object which is a subclass of Signature.
+ */
+Tlv0_2WireFormat.prototype.decodeSignatureInfoAndValue = function
+  (signatureInfo, signatureValue, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  // Use a SignatureHolder to imitate a Data object for decodeSignatureInfo.
+  var signatureHolder = new Tlv0_2WireFormat.SignatureHolder();
+  var decoder = new TlvDecoder(signatureInfo);
+  Tlv0_2WireFormat.decodeSignatureInfo(signatureHolder, decoder, copy);
+
+  decoder = new TlvDecoder(signatureValue);
+  signatureHolder.getSignature().setSignature
+    (new Blob(decoder.readBlobTlv(Tlv.SignatureValue), copy));
+
+  return signatureHolder.getSignature();
+};
+
+/**
+ * Encode the signatureValue in the Signature object as an NDN-TLV
+ * SignatureValue (the signature bits) and return the encoding.
+ * @param {Signature} signature An object of a subclass of Signature with the
+ * signature value to encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeSignatureValue = function(signature)
+{
+  var encoder = new TlvEncoder(256);
+  encoder.writeBlobTlv(Tlv.SignatureValue, signature.getSignature().buf());
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object.
+ * @param {LpPacket} lpPacket The LpPacket object whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ */
+Tlv0_2WireFormat.prototype.decodeLpPacket = function(lpPacket, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  lpPacket.clear();
+
+  var decoder = new TlvDecoder(input);
+  var endOffset = decoder.readNestedTlvsStart(Tlv.LpPacket_LpPacket);
+
+  while (decoder.getOffset() < endOffset) {
+    // Imitate TlvDecoder.readTypeAndLength.
+    var fieldType = decoder.readVarNumber();
+    var fieldLength = decoder.readVarNumber();
+    var fieldEndOffset = decoder.getOffset() + fieldLength;
+    if (fieldEndOffset > input.length)
+      throw new DecodingException(new Error("TLV length exceeds the buffer length"));
+
+    if (fieldType == Tlv.LpPacket_Fragment) {
+      // Set the fragment to the bytes of the TLV value.
+      lpPacket.setFragmentWireEncoding
+        (new Blob(decoder.getSlice(decoder.getOffset(), fieldEndOffset), copy));
+      decoder.seek(fieldEndOffset);
+
+      // The fragment is supposed to be the last field.
+      break;
+    }
+    else if (fieldType == Tlv.LpPacket_Nack) {
+      var networkNack = new NetworkNack();
+      var code = decoder.readOptionalNonNegativeIntegerTlv
+        (Tlv.LpPacket_NackReason, fieldEndOffset);
+      var reason;
+      // The enum numeric values are the same as this wire format, so use as is.
+      if (code < 0 || code == NetworkNack.Reason.NONE)
+        // This includes an omitted NackReason.
+        networkNack.setReason(NetworkNack.Reason.NONE);
+      else if (code == NetworkNack.Reason.CONGESTION ||
+               code == NetworkNack.Reason.DUPLICATE ||
+               code == NetworkNack.Reason.NO_ROUTE)
+        networkNack.setReason(code);
+      else {
+        // Unrecognized reason.
+        networkNack.setReason(NetworkNack.Reason.OTHER_CODE);
+        networkNack.setOtherReasonCode(code);
+      }
+
+      lpPacket.addHeaderField(networkNack);
+    }
+    else if (fieldType == Tlv.LpPacket_IncomingFaceId) {
+      var incomingFaceId = new IncomingFaceId();
+      incomingFaceId.setFaceId(decoder.readNonNegativeInteger(fieldLength));
+      lpPacket.addHeaderField(incomingFaceId);
+    }
+    else {
+      // Unrecognized field type. The conditions for ignoring are here:
+      // http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
+      var canIgnore =
+        (fieldType >= Tlv.LpPacket_IGNORE_MIN &&
+         fieldType <= Tlv.LpPacket_IGNORE_MAX &&
+         (fieldType & 0x01) === 1);
+      if  (!canIgnore)
+        throw new DecodingException(new Error("Did not get the expected TLV type"));
+
+      // Ignore.
+      decoder.seek(fieldEndOffset);
+    }
+
+    decoder.finishNestedTlvs(fieldEndOffset);
+  }
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * Encode delegationSet as a sequence of NDN-TLV Delegation, and return the
+ * encoding. Note that the sequence of Delegation does not have an outer TLV
+ * type and length because it is intended to use the type and length of a Data
+ * packet's Content.
+ * @param {DelegationSet} delegationSet The DelegationSet object to encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeDelegationSet = function(delegationSet)
+{
+  var encoder = new TlvEncoder(256);
+
+  // Encode backwards.
+  for (var i = delegationSet.size() - 1; i >= 0; --i) {
+    var saveLength = encoder.getLength();
+
+    Tlv0_2WireFormat.encodeName(delegationSet.get(i).getName(), encoder);
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.Link_Preference, delegationSet.get(i).getPreference());
+
+    encoder.writeTypeAndLength
+      (Tlv.Link_Delegation, encoder.getLength() - saveLength);
+  }
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode input as a sequence of NDN-TLV Delegation and set the fields of the
+ * delegationSet object. Note that the sequence of Delegation does not have an
+ * outer TLV type and length because it is intended to use the type and length
+ * of a Data packet's Content. This ignores any elements after the sequence
+ * of Delegation.
+ * @param {DelegationSet} delegationSet The DelegationSet object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ */
+Tlv0_2WireFormat.prototype.decodeDelegationSet = function
+  (delegationSet, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  var endOffset = input.length;
+
+  delegationSet.clear();
+  while (decoder.getOffset() < endOffset) {
+    decoder.readTypeAndLength(Tlv.Link_Delegation);
+    var preference = decoder.readNonNegativeIntegerTlv(Tlv.Link_Preference);
+    var name = new Name();
+    Tlv0_2WireFormat.decodeName(name, decoder, copy);
+
+    // Add unsorted to preserve the order so that Interest selected delegation
+    // index will work.
+    delegationSet.addUnsorted(preference, name);
+  }
+};
+
+/**
+ * Encode the EncryptedContent in NDN-TLV and return the encoding.
+ * @param {EncryptedContent} encryptedContent The EncryptedContent object to
+ * encode.
+ * @return {Blob} A Blob containing the encoding.
+ */
+Tlv0_2WireFormat.prototype.encodeEncryptedContent = function(encryptedContent)
+{
+  var encoder = new TlvEncoder(256);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  encoder.writeBlobTlv
+    (Tlv.Encrypt_EncryptedPayload, encryptedContent.getPayload().buf());
+  encoder.writeOptionalBlobTlv
+    (Tlv.Encrypt_InitialVector, encryptedContent.getInitialVector().buf());
+  // Assume the algorithmType value is the same as the TLV type.
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_EncryptionAlgorithm, encryptedContent.getAlgorithmType());
+  Tlv0_2WireFormat.encodeKeyLocator
+    (Tlv.KeyLocator, encryptedContent.getKeyLocator(), encoder);
+
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_EncryptedContent, encoder.getLength() - saveLength);
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode input as an EncryptedContent in NDN-TLV and set the fields of the
+ * encryptedContent object.
+ * @param {EncryptedContent} encryptedContent The EncryptedContent object
+ * whose fields are updated.
+ * @param {Buffer} input The buffer with the bytes to decode.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ */
+Tlv0_2WireFormat.prototype.decodeEncryptedContent = function
+  (encryptedContent, input, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var decoder = new TlvDecoder(input);
+  var endOffset = decoder.
+    readNestedTlvsStart(Tlv.Encrypt_EncryptedContent);
+
+  Tlv0_2WireFormat.decodeKeyLocator
+    (Tlv.KeyLocator, encryptedContent.getKeyLocator(), decoder, copy);
+  encryptedContent.setAlgorithmType
+    (decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_EncryptionAlgorithm));
+  encryptedContent.setInitialVector
+    (new Blob(decoder.readOptionalBlobTlv
+     (Tlv.Encrypt_InitialVector, endOffset), copy));
+  encryptedContent.setPayload
+    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_EncryptedPayload), copy));
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * Get a singleton instance of a Tlv0_2WireFormat.  To always use the
+ * preferred version NDN-TLV, you should use TlvWireFormat.get().
+ * @return {Tlv0_2WireFormat} The singleton instance.
+ */
+Tlv0_2WireFormat.get = function()
+{
+  if (Tlv0_2WireFormat.instance === null)
+    Tlv0_2WireFormat.instance = new Tlv0_2WireFormat();
+  return Tlv0_2WireFormat.instance;
+};
+
+/**
+ * Encode the name component to the encoder as NDN-TLV. This handles different
+ * component types such as ImplicitSha256DigestComponent.
+ * @param {Name.Component} component The name component to encode.
+ * @param {TlvEncoder} encoder The encoder to receive the encoding.
+ */
+Tlv0_2WireFormat.encodeNameComponent = function(component, encoder)
+{
+  var type = component.isImplicitSha256Digest() ?
+      Tlv.ImplicitSha256DigestComponent : Tlv.NameComponent;
+  encoder.writeBlobTlv(type, component.getValue().buf());
+};
+
+/**
+ * Decode the name component as NDN-TLV and return the component. This handles
+ * different component types such as ImplicitSha256DigestComponent.
+ * @param {TlvDecoder} decoder The decoder with the input.
+ * @param {boolean} copy (optional) If true, copy from the input when making new
+ * Blob values. If false, then Blob values share memory with the input, which
+ * must remain unchanged while the Blob values are used. If omitted, use true.
+ * @return {Name.Component} A new Name.Component.
+ */
+Tlv0_2WireFormat.decodeNameComponent = function(decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var savePosition = decoder.getOffset();
+  var type = decoder.readVarNumber();
+  // Restore the position.
+  decoder.seek(savePosition);
+
+  var value = new Blob(decoder.readBlobTlv(type), copy);
+  if (type === Tlv.ImplicitSha256DigestComponent)
+    return Name.Component.fromImplicitSha256Digest(value);
+  else
+    return new Name.Component(value);
+};
+
+/**
+ * Encode the name to the encoder.
+ * @param {Name} name The name to encode.
+ * @param {TlvEncoder} encoder The encoder to receive the encoding.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion. The signed portion starts from the first
+ * name component and ends just before the final name component (which is
+ * assumed to be a signature for a signed interest).
+ */
+Tlv0_2WireFormat.encodeName = function(name, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode the components backwards.
+  var signedPortionEndOffsetFromBack;
+  for (var i = name.size() - 1; i >= 0; --i) {
+    Tlv0_2WireFormat.encodeNameComponent(name.get(i), encoder);
+    if (i == name.size() - 1)
+      signedPortionEndOffsetFromBack = encoder.getLength();
+  }
+
+  var signedPortionBeginOffsetFromBack = encoder.getLength();
+  encoder.writeTypeAndLength(Tlv.Name, encoder.getLength() - saveLength);
+
+  var signedPortionBeginOffset =
+    encoder.getLength() - signedPortionBeginOffsetFromBack;
+  var signedPortionEndOffset;
+  if (name.size() == 0)
+    // There is no "final component", so set signedPortionEndOffset arbitrarily.
+    signedPortionEndOffset = signedPortionBeginOffset;
+  else
+    signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;
+
+  return { signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Clear the name, decode a Name from the decoder and set the fields of the name
+ * object.
+ * @param {Name} name The name object whose fields are updated.
+ * @param {TlvDecoder} decoder The decoder with the input.
+ * @return {object} An associative array with fields
+ * (signedPortionBeginOffset, signedPortionEndOffset) where
+ * signedPortionBeginOffset is the offset in the encoding of the beginning of
+ * the signed portion, and signedPortionEndOffset is the offset in the encoding
+ * of the end of the signed portion. The signed portion starts from the first
+ * name component and ends just before the final name component (which is
+ * assumed to be a signature for a signed interest).
+ */
+Tlv0_2WireFormat.decodeName = function(name, decoder, copy)
+{
+  name.clear();
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Name);
+  var signedPortionBeginOffset = decoder.getOffset();
+  // In case there are no components, set signedPortionEndOffset arbitrarily.
+  var signedPortionEndOffset = signedPortionBeginOffset;
+
+  while (decoder.getOffset() < endOffset) {
+    signedPortionEndOffset = decoder.getOffset();
+    name.append(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
+  }
+
+  decoder.finishNestedTlvs(endOffset);
+
+  return { signedPortionBeginOffset: signedPortionBeginOffset,
+           signedPortionEndOffset: signedPortionEndOffset };
+};
+
+/**
+ * Encode the interest selectors.  If no selectors are written, do not output a
+ * Selectors TLV.
+ */
+Tlv0_2WireFormat.encodeSelectors = function(interest, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  if (interest.getMustBeFresh())
+    encoder.writeTypeAndLength(Tlv.MustBeFresh, 0);
+  encoder.writeOptionalNonNegativeIntegerTlv(
+    Tlv.ChildSelector, interest.getChildSelector());
+  if (interest.getExclude().size() > 0)
+    Tlv0_2WireFormat.encodeExclude(interest.getExclude(), encoder);
+
+  if (interest.getKeyLocator().getType() != null)
+    Tlv0_2WireFormat.encodeKeyLocator
+      (Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), encoder);
+
+  encoder.writeOptionalNonNegativeIntegerTlv(
+    Tlv.MaxSuffixComponents, interest.getMaxSuffixComponents());
+  encoder.writeOptionalNonNegativeIntegerTlv(
+    Tlv.MinSuffixComponents, interest.getMinSuffixComponents());
+
+  // Only output the type and length if values were written.
+  if (encoder.getLength() != saveLength)
+    encoder.writeTypeAndLength(Tlv.Selectors, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeSelectors = function(interest, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Selectors);
+
+  interest.setMinSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.MinSuffixComponents, endOffset));
+  interest.setMaxSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.MaxSuffixComponents, endOffset));
+
+  if (decoder.peekType(Tlv.PublisherPublicKeyLocator, endOffset))
+    Tlv0_2WireFormat.decodeKeyLocator
+      (Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), decoder, copy);
+  else
+    interest.getKeyLocator().clear();
+
+  if (decoder.peekType(Tlv.Exclude, endOffset))
+    Tlv0_2WireFormat.decodeExclude(interest.getExclude(), decoder, copy);
+  else
+    interest.getExclude().clear();
+
+  interest.setChildSelector(decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.ChildSelector, endOffset));
+  interest.setMustBeFresh(decoder.readBooleanTlv(Tlv.MustBeFresh, endOffset));
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+Tlv0_2WireFormat.encodeExclude = function(exclude, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // TODO: Do we want to order the components (except for ANY)?
+  // Encode the entries backwards.
+  for (var i = exclude.size() - 1; i >= 0; --i) {
+    var entry = exclude.get(i);
+
+    if (entry == Exclude.ANY)
+      encoder.writeTypeAndLength(Tlv.Any, 0);
+    else
+      Tlv0_2WireFormat.encodeNameComponent(entry, encoder);
+  }
+
+  encoder.writeTypeAndLength(Tlv.Exclude, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeExclude = function(exclude, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Exclude);
+
+  exclude.clear();
+  while (decoder.getOffset() < endOffset) {
+    if (decoder.peekType(Tlv.Any, endOffset)) {
+      // Read past the Any TLV.
+      decoder.readBooleanTlv(Tlv.Any, endOffset);
+      exclude.appendAny();
+    }
+    else
+      exclude.appendComponent(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
+  }
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+Tlv0_2WireFormat.encodeKeyLocator = function(type, keyLocator, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  if (keyLocator.getType() != null) {
+    if (keyLocator.getType() == KeyLocatorType.KEYNAME)
+      Tlv0_2WireFormat.encodeName(keyLocator.getKeyName(), encoder);
+    else if (keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST &&
+             keyLocator.getKeyData().size() > 0)
+      encoder.writeBlobTlv(Tlv.KeyLocatorDigest, keyLocator.getKeyData().buf());
+    else
+      throw new Error("Unrecognized KeyLocatorType " + keyLocator.getType());
+  }
+
+  encoder.writeTypeAndLength(type, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeKeyLocator = function
+  (expectedType, keyLocator, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var endOffset = decoder.readNestedTlvsStart(expectedType);
+
+  keyLocator.clear();
+
+  if (decoder.getOffset() == endOffset)
+    // The KeyLocator is omitted, so leave the fields as none.
+    return;
+
+  if (decoder.peekType(Tlv.Name, endOffset)) {
+    // KeyLocator is a Name.
+    keyLocator.setType(KeyLocatorType.KEYNAME);
+    Tlv0_2WireFormat.decodeName(keyLocator.getKeyName(), decoder, copy);
+  }
+  else if (decoder.peekType(Tlv.KeyLocatorDigest, endOffset)) {
+    // KeyLocator is a KeyLocatorDigest.
+    keyLocator.setType(KeyLocatorType.KEY_LOCATOR_DIGEST);
+    keyLocator.setKeyData
+      (new Blob(decoder.readBlobTlv(Tlv.KeyLocatorDigest), copy));
+  }
+  else
+    throw new DecodingException(new Error
+      ("decodeKeyLocator: Unrecognized key locator type"));
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * An internal method to encode signature as the appropriate form of
+ * SignatureInfo in NDN-TLV.
+ * @param {Signature} signature An object of a subclass of Signature to encode.
+ * @param {TlvEncoder} encoder The encoder.
+ */
+Tlv0_2WireFormat.encodeSignatureInfo_ = function(signature, encoder)
+{
+  if (signature instanceof GenericSignature) {
+    // Handle GenericSignature separately since it has the entire encoding.
+    var encoding = signature.getSignatureInfoEncoding();
+
+    // Do a test decoding to sanity check that it is valid TLV.
+    try {
+      var decoder = new TlvDecoder(encoding.buf());
+      var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);
+      decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
+      decoder.finishNestedTlvs(endOffset);
+    } catch (ex) {
+      throw new Error
+        ("The GenericSignature encoding is not a valid NDN-TLV SignatureInfo: " +
+         ex.message);
+    }
+
+    encoder.writeBuffer(encoding.buf());
+    return;
+  }
+
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  if (signature instanceof Sha256WithRsaSignature) {
+    Tlv0_2WireFormat.encodeKeyLocator
+      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithRsa);
+  }
+  else if (signature instanceof Sha256WithEcdsaSignature) {
+    Tlv0_2WireFormat.encodeKeyLocator
+      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithEcdsa);
+  }
+  else if (signature instanceof HmacWithSha256Signature) {
+    Tlv0_2WireFormat.encodeKeyLocator
+      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.SignatureType, Tlv.SignatureType_SignatureHmacWithSha256);
+  }
+  else if (signature instanceof DigestSha256Signature)
+    encoder.writeNonNegativeIntegerTlv
+      (Tlv.SignatureType, Tlv.SignatureType_DigestSha256);
+  else
+    throw new Error("encodeSignatureInfo: Unrecognized Signature object type");
+
+  encoder.writeTypeAndLength(Tlv.SignatureInfo, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeSignatureInfo = function(data, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var beginOffset = decoder.getOffset();
+  var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);
+
+  var signatureType = decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
+  if (signatureType == Tlv.SignatureType_SignatureSha256WithRsa) {
+    data.setSignature(new Sha256WithRsaSignature());
+    // Modify data's signature object because if we create an object
+    //   and set it, then data will have to copy all the fields.
+    var signatureInfo = data.getSignature();
+    Tlv0_2WireFormat.decodeKeyLocator
+      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
+  }
+  else if (signatureType == Tlv.SignatureType_SignatureSha256WithEcdsa) {
+    data.setSignature(new Sha256WithEcdsaSignature());
+    var signatureInfo = data.getSignature();
+    Tlv0_2WireFormat.decodeKeyLocator
+      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
+  }
+  else if (signatureType == Tlv.SignatureType_SignatureHmacWithSha256) {
+    data.setSignature(new HmacWithSha256Signature());
+    var signatureInfo = data.getSignature();
+    Tlv0_2WireFormat.decodeKeyLocator
+      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
+  }
+  else if (signatureType == Tlv.SignatureType_DigestSha256)
+    data.setSignature(new DigestSha256Signature());
+  else {
+    data.setSignature(new GenericSignature());
+    var signatureInfo = data.getSignature();
+
+    // Get the bytes of the SignatureInfo TLV.
+    signatureInfo.setSignatureInfoEncoding
+      (new Blob(decoder.getSlice(beginOffset, endOffset), copy), signatureType);
+  }
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+Tlv0_2WireFormat.encodeMetaInfo = function(metaInfo, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  var finalBlockIdBuf = metaInfo.getFinalBlockId().getValue().buf();
+  if (finalBlockIdBuf != null && finalBlockIdBuf.length > 0) {
+    // FinalBlockId has an inner NameComponent.
+    var finalBlockIdSaveLength = encoder.getLength();
+    Tlv0_2WireFormat.encodeNameComponent(metaInfo.getFinalBlockId(), encoder);
+    encoder.writeTypeAndLength
+      (Tlv.FinalBlockId, encoder.getLength() - finalBlockIdSaveLength);
+  }
+
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.FreshnessPeriod, metaInfo.getFreshnessPeriod());
+  if (metaInfo.getType() != ContentType.BLOB) {
+    // Not the default, so we need to encode the type.
+    if (metaInfo.getType() == ContentType.LINK ||
+        metaInfo.getType() == ContentType.KEY ||
+        metaInfo.getType() == ContentType.NACK)
+      // The ContentType enum is set up with the correct integer for
+      // each NDN-TLV ContentType.
+      encoder.writeNonNegativeIntegerTlv(Tlv.ContentType, metaInfo.getType());
+    else if (metaInfo.getType() == ContentType.OTHER_CODE)
+      encoder.writeNonNegativeIntegerTlv
+        (Tlv.ContentType, metaInfo.getOtherTypeCode());
+    else
+      // We don't expect this to happen.
+      throw new Error("unrecognized TLV ContentType");
+  }
+
+  encoder.writeTypeAndLength(Tlv.MetaInfo, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeMetaInfo = function(metaInfo, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.MetaInfo);
+
+  var type = decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.ContentType, endOffset);
+  if (type == null || type < 0 || type === ContentType.BLOB)
+    metaInfo.setType(ContentType.BLOB);
+  else if (type === ContentType.LINK ||
+           type === ContentType.KEY ||
+           type === ContentType.NACK)
+    // The ContentType enum is set up with the correct integer for each NDN-TLV
+    // ContentType.
+    metaInfo.setType(type);
+  else {
+    // Unrecognized content type.
+    metaInfo.setType(ContentType.OTHER_CODE);
+    metaInfo.setOtherTypeCode(type);
+  }
+
+  metaInfo.setFreshnessPeriod
+    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod, endOffset));
+  if (decoder.peekType(Tlv.FinalBlockId, endOffset)) {
+    var finalBlockIdEndOffset = decoder.readNestedTlvsStart(Tlv.FinalBlockId);
+    metaInfo.setFinalBlockId(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
+    decoder.finishNestedTlvs(finalBlockIdEndOffset);
+  }
+  else
+    metaInfo.setFinalBlockId(null);
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+Tlv0_2WireFormat.encodeControlParameters = function(controlParameters, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_ExpirationPeriod,
+     controlParameters.getExpirationPeriod());
+
+  if (controlParameters.getStrategy().size() > 0){
+    var strategySaveLength = encoder.getLength();
+    Tlv0_2WireFormat.encodeName(controlParameters.getStrategy(), encoder);
+    encoder.writeTypeAndLength(Tlv.ControlParameters_Strategy,
+      encoder.getLength() - strategySaveLength);
+  }
+
+  var flags = controlParameters.getForwardingFlags().getNfdForwardingFlags();
+  if (flags != new ForwardingFlags().getNfdForwardingFlags())
+      // The flags are not the default value.
+      encoder.writeNonNegativeIntegerTlv
+        (Tlv.ControlParameters_Flags, flags);
+
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_Cost, controlParameters.getCost());
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_Origin, controlParameters.getOrigin());
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_LocalControlFeature,
+     controlParameters.getLocalControlFeature());
+
+  if (controlParameters.getUri().length != 0)
+    encoder.writeBlobTlv
+      (Tlv.ControlParameters_Uri, new Blob(controlParameters.getUri()).buf());
+
+  encoder.writeOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_FaceId, controlParameters.getFaceId());
+  if (controlParameters.getName() != null)
+    Tlv0_2WireFormat.encodeName(controlParameters.getName(), encoder);
+
+  encoder.writeTypeAndLength
+    (Tlv.ControlParameters_ControlParameters, encoder.getLength() - saveLength);
+};
+
+Tlv0_2WireFormat.decodeControlParameters = function
+  (controlParameters, decoder, copy)
+{
+  if (copy == null)
+    copy = true;
+
+  controlParameters.clear();
+  var endOffset = decoder.
+    readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);
+
+  // decode name
+  if (decoder.peekType(Tlv.Name, endOffset)) {
+    var name = new Name();
+    Tlv0_2WireFormat.decodeName(name, decoder, copy);
+    controlParameters.setName(name);
+  }
+
+  // decode face ID
+  controlParameters.setFaceId(decoder.readOptionalNonNegativeIntegerTlv
+    (Tlv.ControlParameters_FaceId, endOffset));
+
+  // decode URI
+  if (decoder.peekType(Tlv.ControlParameters_Uri, endOffset)) {
+    // Set copy false since we just immediately get the string.
+    var uri = new Blob
+      (decoder.readOptionalBlobTlv(Tlv.ControlParameters_Uri, endOffset), false);
+    controlParameters.setUri(uri.toString());
+  }
+
+  // decode integers
+  controlParameters.setLocalControlFeature(decoder.
+    readOptionalNonNegativeIntegerTlv(
+      Tlv.ControlParameters_LocalControlFeature, endOffset));
+  controlParameters.setOrigin(decoder.
+    readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin,
+      endOffset));
+  controlParameters.setCost(decoder.readOptionalNonNegativeIntegerTlv(
+    Tlv.ControlParameters_Cost, endOffset));
+
+  // set forwarding flags
+  if (decoder.peekType(Tlv.ControlParameters_Flags, endOffset)) {
+    var flags = new ForwardingFlags();
+    flags.setNfdForwardingFlags(decoder.
+      readNonNegativeIntegerTlv(Tlv.ControlParameters_Flags, endOffset));
+    controlParameters.setForwardingFlags(flags);
+  }
+
+  // decode strategy
+  if (decoder.peekType(Tlv.ControlParameters_Strategy, endOffset)) {
+    var strategyEndOffset = decoder.readNestedTlvsStart(Tlv.ControlParameters_Strategy);
+    Tlv0_2WireFormat.decodeName(controlParameters.getStrategy(), decoder, copy);
+    decoder.finishNestedTlvs(strategyEndOffset);
+  }
+
+  // decode expiration period
+  controlParameters.setExpirationPeriod(
+    decoder.readOptionalNonNegativeIntegerTlv(
+      Tlv.ControlParameters_ExpirationPeriod, endOffset));
+
+  decoder.finishNestedTlvs(endOffset);
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Tlv0_2WireFormat = require('./tlv-0_2-wire-format.js').Tlv0_2WireFormat;
+
+/**
+ * A Tlv0_1_1WireFormat extends Tlv0_2WireFormat so that it is an alias in case
+ * any applications use Tlv0_1_1WireFormat directly.  These two wire formats are
+ * the same except that Tlv0_2WireFormat adds support for the name component
+ * type ImplicitSha256Digest.
+ * @constructor
+ */
+var Tlv0_1_1WireFormat = function Tlv0_1_1WireFormat()
+{
+  // Inherit from Tlv0_2WireFormat.
+  Tlv0_2WireFormat.call(this);
+};
+
+Tlv0_1_1WireFormat.prototype = new Tlv0_2WireFormat();
+Tlv0_1_1WireFormat.prototype.name = "Tlv0_1_1WireFormat";
+
+exports.Tlv0_1_1WireFormat = Tlv0_1_1WireFormat;
+
+// Default object.
+Tlv0_1_1WireFormat.instance = null;
+
+/**
+ * Get a singleton instance of a Tlv0_1_1WireFormat.
+ * @return {Tlv0_1_1WireFormat} The singleton instance.
+ */
+Tlv0_1_1WireFormat.get = function()
+{
+  if (Tlv0_1_1WireFormat.instance === null)
+    Tlv0_1_1WireFormat.instance = new Tlv0_1_1WireFormat();
+  return Tlv0_1_1WireFormat.instance;
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
+var Tlv0_1_1WireFormat = require('./tlv-0_1_1-wire-format.js').Tlv0_1_1WireFormat;
+
+/**
+ * A Tlv0_1WireFormat extends Tlv0_1_1WireFormat so that it is an alias in case
+ * any applications use Tlv0_1WireFormat directly.  These two wire formats are
+ * the same except that Tlv0_1_1WireFormat adds support for
+ * Sha256WithEcdsaSignature.
+ * @constructor
+ */
+var Tlv0_1WireFormat = function Tlv0_1WireFormat()
+{
+  // Inherit from Tlv0_1_1WireFormat.
+  Tlv0_1_1WireFormat.call(this);
+};
+
+Tlv0_1WireFormat.prototype = new Tlv0_1_1WireFormat();
+Tlv0_1WireFormat.prototype.name = "Tlv0_1WireFormat";
+
+exports.Tlv0_1WireFormat = Tlv0_1WireFormat;
+
+// Default object.
+Tlv0_1WireFormat.instance = null;
+
+/**
+ * Get a singleton instance of a Tlv0_1WireFormat.
+ * @return {Tlv0_1WireFormat} The singleton instance.
+ */
+Tlv0_1WireFormat.get = function()
+{
+  if (Tlv0_1WireFormat.instance === null)
+    Tlv0_1WireFormat.instance = new Tlv0_1WireFormat();
+  return Tlv0_1WireFormat.instance;
+};
+/**
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
+var Tlv0_2WireFormat = require('./tlv-0_2-wire-format.js').Tlv0_2WireFormat;
+
+/**
+ * A TlvWireFormat extends WireFormat to override its methods to
+ * implement encoding and decoding using the preferred implementation of NDN-TLV.
+ * @constructor
+ */
+var TlvWireFormat = function TlvWireFormat()
+{
+  // Inherit from Tlv0_2WireFormat.
+  Tlv0_2WireFormat.call(this);
+};
+
+TlvWireFormat.prototype = new Tlv0_2WireFormat();
+TlvWireFormat.prototype.name = "TlvWireFormat";
+
+exports.TlvWireFormat = TlvWireFormat;
+
+// Default object.
+TlvWireFormat.instance = null;
+
+/**
+ * Get a singleton instance of a TlvWireFormat.  Assuming that the default
+ * wire format was set with WireFormat.setDefaultWireFormat(TlvWireFormat.get()),
+ * you can check if this is the default wire encoding with
+ * if WireFormat.getDefaultWireFormat() == TlvWireFormat.get().
+ * @return {TlvWireFormat} The singleton instance.
+ */
+TlvWireFormat.get = function()
+{
+  if (TlvWireFormat.instance === null)
+    TlvWireFormat.instance = new TlvWireFormat();
+  return TlvWireFormat.instance;
+};
+
+// On loading this module, make this the default wire format.
+// This module will be loaded because WireFormat loads it.
+WireFormat.setDefaultWireFormat(TlvWireFormat.get());
+/**
+ * This file contains utilities to help encode and decode NDN objects.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * author: Meki Cheraoui
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DataUtils = require('./data-utils.js').DataUtils; /** @ignore */
+var KeyLocatorType = require('../key-locator.js').KeyLocatorType; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var Sha256WithRsaSignature = require('../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
+var Sha256WithEcdsaSignature = require('../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
+var HmacWithSha256Signature = require('../hmac-with-sha256-signature.js').HmacWithSha256Signature; /** @ignore */
+var DigestSha256Signature = require('../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
+var ContentType = require('../meta-info.js').ContentType; /** @ignore */
+var WireFormat = require('./wire-format.js').WireFormat;
+
+/**
+ * An EncodingUtils has static methods for encoding data.
+ * @constructor
+ */
+var EncodingUtils = function EncodingUtils()
+{
+};
+
+exports.EncodingUtils = EncodingUtils;
+
+EncodingUtils.encodeToHexInterest = function(interest, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return DataUtils.toHex(interest.wireEncode(wireFormat).buf());
+};
+
+EncodingUtils.encodeToHexData = function(data, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return DataUtils.toHex(data.wireEncode(wireFormat).buf());
+};
+
+EncodingUtils.decodeHexInterest = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  var interest = new Interest();
+  interest.wireDecode(DataUtils.toNumbers(input), wireFormat);
+  return interest;
+};
+
+EncodingUtils.decodeHexData = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  var data = new Data();
+  data.wireDecode(DataUtils.toNumbers(input), wireFormat);
+  return data;
+};
+
+/**
+ * Decode the Buffer array which holds SubjectPublicKeyInfo and return an RSAKey.
+ */
+EncodingUtils.decodeSubjectPublicKeyInfo = function(array)
+{
+  var hex = DataUtils.toHex(array).toLowerCase();
+  var a = _x509_getPublicKeyHexArrayFromCertHex(hex, _x509_getSubjectPublicKeyPosFromCertHex(hex, 0));
+  var rsaKey = new RSAKey();
+  rsaKey.setPublic(a[0], a[1]);
+  return rsaKey;
+}
+
+/**
+ * Return a user friendly HTML string with the contents of data.
+ */
+EncodingUtils.dataToHtml = function(/* Data */ data)
+{
+  if (data == -1)
+    return "NO CONTENT FOUND";
+  if (data == -2)
+    return "CONTENT NAME IS EMPTY";
+
+  var output = "";
+  function append(message) {
+    message = message.replace(/&/g, "&amp;");
+    message = message.replace(/</g, "&lt;");
+
+    output += message;
+    output += "<br/>";
+  }
+
+  // Imitate dumpData in examples/node/test-encode-decode-data.js
+
+  append("name: " + data.getName().toUri());
+  if (data.getContent().size() > 0) {
+    append("content (raw): " + data.getContent().buf().toString('binary'));
+    append("content (hex): " + data.getContent().toHex());
+  }
+  else
+    append("content: <empty>");
+
+  if (!(data.getMetaInfo().getType() == ContentType.BLOB)) {
+    if (data.getMetaInfo().getType() == ContentType.KEY)
+      append("metaInfo.type: KEY");
+    else if (data.getMetaInfo().getType() == ContentType.LINK)
+      append("metaInfo.type: LINK");
+    else if (data.getMetaInfo().getType() == ContentType.NACK)
+      append("metaInfo.type: NACK");
+    else if (data.getMetaInfo().getType() == ContentType.OTHER_CODE)
+      append("metaInfo.type: other code " + data.getMetaInfo().getOtherTypeCode());
+  }
+  append("metaInfo.freshnessPeriod (milliseconds): " +
+    (data.getMetaInfo().getFreshnessPeriod() >= 0 ?
+      "" + data.getMetaInfo().getFreshnessPeriod() : "<none>"));
+  append("metaInfo.finalBlockId: " +
+    (data.getMetaInfo().getFinalBlockId().getValue().size() > 0 ?
+     data.getMetaInfo().getFinalBlockId().getValue().toHex() : "<none>"));
+
+  var keyLocator = null;
+  var signature = data.getSignature();
+  if (signature instanceof Sha256WithRsaSignature) {
+    var signature = data.getSignature();
+    append("Sha256WithRsa signature.signature: " +
+      (signature.getSignature().size() > 0 ?
+       signature.getSignature().toHex() : "<none>"));
+    keyLocator = signature.getKeyLocator();
+  }
+  else if (signature instanceof Sha256WithEcdsaSignature) {
+    var signature = data.getSignature();
+    append("Sha256WithEcdsa signature.signature: " +
+      (signature.getSignature().size() > 0 ?
+       signature.getSignature().toHex() : "<none>"));
+    keyLocator = signature.getKeyLocator();
+  }
+  else if (signature instanceof HmacWithSha256Signature) {
+    var signature = data.getSignature();
+    append("HmacWithSha256 signature.signature: " +
+      (signature.getSignature().size() > 0 ?
+       signature.getSignature().toHex() : "<none>"));
+    keyLocator = signature.getKeyLocator();
+  }
+  else if (signature instanceof DigestSha256Signature) {
+    var signature = data.getSignature();
+    append("DigestSha256 signature.signature: " +
+      (signature.getSignature().size() > 0 ?
+       signature.getSignature().toHex() : "<none>"));
+  }
+  if (keyLocator !== null) {
+    if (keyLocator.getType() == null)
+      append("signature.keyLocator: <none>");
+    else if (keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST)
+      append("signature.keyLocator: KeyLocatorDigest: " + keyLocator.getKeyData().toHex());
+    else if (keyLocator.getType() == KeyLocatorType.KEYNAME)
+      append("signature.keyLocator: KeyName: " + keyLocator.getKeyName().toUri());
+    else
+      append("signature.keyLocator: <unrecognized ndn_KeyLocatorType>");
+  }
+
+  return output;
+};
+
+//
+// Deprecated: For the browser, define these in the global scope.  Applications should access as member of EncodingUtils.
+//
+
+var encodeToHexInterest = function(interest) { return EncodingUtils.encodeToHexInterest(interest); }
+var decodeHexInterest = function(input) { return EncodingUtils.decodeHexInterest(input); }
+var decodeSubjectPublicKeyInfo = function(input) { return EncodingUtils.decodeSubjectPublicKeyInfo(input); }
+
+/**
+ * @deprecated Use interest.wireEncode().
+ */
+function encodeToBinaryInterest(interest) { return interest.wireEncode().buf(); }
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/algo/aes https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// (This is ported from ndn::gep::algo::Aes, and named AesAlgorithm because
+// "Aes" is very short and not all the Common Client Libraries have namespaces.)
+
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DecryptKey = require('../decrypt-key.js').DecryptKey; /** @ignore */
+var EncryptKey = require('../encrypt-key.js').EncryptKey; /** @ignore */
+var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise;
+
+/**
+ * The AesAlgorithm class provides static methods to manipulate keys, encrypt
+ * and decrypt using the AES symmetric key cipher.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var AesAlgorithm = function AesAlgorithm()
+{
+};
+
+exports.AesAlgorithm = AesAlgorithm;
+
+/**
+ * Generate a new random decrypt key for AES based on the given params.
+ * @param {AesKeyParams} params The key params with the key size (in bits).
+ * @return {DecryptKey} The new decrypt key.
+ */
+AesAlgorithm.generateKey = function(params)
+{
+  // Convert the key bit size to bytes.
+  var key = Crypto.randomBytes(params.getKeySize() / 8);
+
+  var decryptKey = new DecryptKey(new Blob(key, false));
+  return decryptKey;
+};
+
+/**
+ * Derive a new encrypt key from the given decrypt key value.
+ * @param {Blob} keyBits The key value of the decrypt key.
+ * @return {EncryptKey} The new encrypt key.
+ */
+AesAlgorithm.deriveEncryptKey = function(keyBits)
+{
+  return new EncryptKey(keyBits);
+};
+
+/**
+ * Decrypt the encryptedData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value.
+ * @param {Blob} encryptedData The data to decrypt.
+ * @param {EncryptParams} params This decrypts according to
+ * params.getAlgorithmType() and other params as needed such as
+ * params.getInitialVector().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the decrypted Blob.
+ */
+AesAlgorithm.decryptPromise = function(keyBits, encryptedData, params, useSync)
+{
+  if (UseSubtleCrypto() && !useSync &&
+      // Crypto.subtle doesn't implement ECB.
+      params.getAlgorithmType() != EncryptAlgorithmType.AesEcb) {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      return crypto.subtle.importKey
+        ("raw", keyBits.buf(), { name: "AES-CBC" }, false,
+         ["encrypt", "decrypt"])
+      .then(function(key) {
+        return crypto.subtle.decrypt
+          ({ name: "AES-CBC", iv: params.getInitialVector().buf() },
+           key, encryptedData.buf());
+      })
+      .then(function(result) {
+        return Promise.resolve(new Blob(new Uint8Array(result), false));
+      });
+    }
+    else
+      return Promise.reject(new Error("unsupported encryption mode"));
+  }
+  else {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.AesEcb) {
+      try {
+        // ECB ignores the initial vector.
+        var cipher = Crypto.createDecipheriv("aes-128-ecb", keyBits.buf(), "");
+        return SyncPromise.resolve(new Blob
+          (Buffer.concat([cipher.update(encryptedData.buf()), cipher.final()]),
+           false));
+      } catch (err) {
+        return SyncPromise.reject(err);
+      }
+    }
+    else if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      try {
+        var cipher = Crypto.createDecipheriv
+          ("aes-128-cbc", keyBits.buf(), params.getInitialVector().buf());
+        return SyncPromise.resolve(new Blob
+          (Buffer.concat([cipher.update(encryptedData.buf()), cipher.final()]),
+           false));
+      } catch (err) {
+        return SyncPromise.reject(err);
+      }
+    }
+    else
+      return SyncPromise.reject(new Error("unsupported encryption mode"));
+  }
+};
+
+/**
+ * Decrypt the encryptedData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value.
+ * @param {Blob} encryptedData The data to decrypt.
+ * @param {EncryptParams} params This decrypts according to
+ * params.getAlgorithmType() and other params as needed such as
+ * params.getInitialVector().
+ * @return {Blob} The decrypted data.
+ * @throws Error If decryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+AesAlgorithm.decrypt = function(keyBits, encryptedData, params)
+{
+  return SyncPromise.getValue(this.decryptPromise
+    (keyBits, encryptedData, params, true));
+};
+
+/**
+ * Encrypt the plainData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value.
+ * @param {Blob} plainData The data to encrypt.
+ * @param {EncryptParams} params This encrypts according to
+ * params.getAlgorithmType() and other params as needed such as
+ * params.getInitialVector().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the encrypted Blob.
+ */
+AesAlgorithm.encryptPromise = function(keyBits, plainData, params, useSync)
+{
+  if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+    if (params.getInitialVector().size() != AesAlgorithm.BLOCK_SIZE)
+      return SyncPromise.reject(new Error("incorrect initial vector size"));
+  }
+
+  if (UseSubtleCrypto() && !useSync &&
+      // Crypto.subtle doesn't implement ECB.
+      params.getAlgorithmType() != EncryptAlgorithmType.AesEcb) {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      return crypto.subtle.importKey
+        ("raw", keyBits.buf(), { name: "AES-CBC" }, false,
+         ["encrypt", "decrypt"])
+      .then(function(key) {
+        return crypto.subtle.encrypt
+          ({ name: "AES-CBC", iv: params.getInitialVector().buf() },
+           key, plainData.buf());
+      })
+      .then(function(result) {
+        return Promise.resolve(new Blob(new Uint8Array(result), false));
+      });
+    }
+    else
+      return Promise.reject(new Error("unsupported encryption mode"));
+  }
+  else {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.AesEcb) {
+      // ECB ignores the initial vector.
+      var cipher = Crypto.createCipheriv("aes-128-ecb", keyBits.buf(), "");
+      return SyncPromise.resolve(new Blob
+        (Buffer.concat([cipher.update(plainData.buf()), cipher.final()]),
+         false));
+    }
+    else if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      var cipher = Crypto.createCipheriv
+        ("aes-128-cbc", keyBits.buf(), params.getInitialVector().buf());
+      return SyncPromise.resolve(new Blob
+        (Buffer.concat([cipher.update(plainData.buf()), cipher.final()]),
+         false));
+    }
+    else
+      return SyncPromise.reject(new Error("unsupported encryption mode"));
+  }
+};
+
+/**
+ * Encrypt the plainData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value.
+ * @param {Blob} plainData The data to encrypt.
+ * @param {EncryptParams} params This encrypts according to
+ * params.getAlgorithmType() and other params as needed such as
+ * params.getInitialVector().
+ * @return {Blob} The encrypted data.
+ * @throws Error If encryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+AesAlgorithm.encrypt = function(keyBits, plainData, params)
+{
+  return SyncPromise.getValue(this.encryptPromise
+    (keyBits, plainData, params, true));
+};
+
+AesAlgorithm.BLOCK_SIZE = 16;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/encrypt-params https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob;
+
+var EncryptAlgorithmType = function EncryptAlgorithmType()
+{
+}
+
+exports.EncryptAlgorithmType = EncryptAlgorithmType;
+
+// These correspond to the TLV codes.
+EncryptAlgorithmType.AesEcb = 0;
+EncryptAlgorithmType.AesCbc = 1;
+EncryptAlgorithmType.RsaPkcs = 2;
+EncryptAlgorithmType.RsaOaep = 3;
+
+/**
+ * An EncryptParams holds an algorithm type and other parameters used to
+ * encrypt and decrypt. Create an EncryptParams with the given parameters.
+ * @param {number} algorithmType The algorithm type from EncryptAlgorithmType,
+ * or null if not specified.
+ * @param {number} initialVectorLength (optional) The initial vector length, or
+ * 0 if the initial vector is not specified. If ommitted, the initial vector is
+ * not specified.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var EncryptParams = function EncryptParams(algorithmType, initialVectorLength)
+{
+  this.algorithmType_ = algorithmType;
+
+  if (initialVectorLength != null && initialVectorLength > 0) {
+    var initialVector = Crypto.randomBytes(initialVectorLength);
+    this.initialVector_ = new Blob(initialVector, false);
+  }
+  else
+    this.initialVector_ = new Blob();
+};
+
+exports.EncryptParams = EncryptParams;
+
+/**
+ * Get the algorithmType.
+ * @return {number} The algorithm type from EncryptAlgorithmType, or null if not
+ * specified.
+ */
+EncryptParams.prototype.getAlgorithmType = function()
+{
+  return this.algorithmType_;
+};
+
+/**
+ * Get the initial vector.
+ * @return {Blob} The initial vector. If not specified, isNull() is true.
+ */
+EncryptParams.prototype.getInitialVector = function()
+{
+  return this.initialVector_;
+};
+
+/**
+ * Set the algorithm type.
+ * @param {number} algorithmType The algorithm type from EncryptAlgorithmType.
+ * If not specified, set to null.
+ * @return {EncryptParams} This EncryptParams so that you can chain calls to
+ * update values.
+ */
+EncryptParams.prototype.setAlgorithmType = function(algorithmType)
+{
+  this.algorithmType_ = algorithmType;
+  return this;
+};
+
+/**
+ * Set the initial vector.
+ * @param {Blob} initialVector The initial vector. If not specified, set to the
+ * default Blob() where isNull() is true.
+ * @return {EncryptParams} This EncryptParams so that you can chain calls to
+ * update values.
+ */
+EncryptParams.prototype.setInitialVector = function(initialVector)
+{
+  this.initialVector_ =
+      typeof initialVector === 'object' && initialVector instanceof Blob ?
+    initialVector : new Blob(initialVector);
+  return this;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/encryptor https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Name = require('../../name.js').Name; /** @ignore */
+var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
+var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
+var TlvWireFormat = require('../../encoding/tlv-wire-format.js').TlvWireFormat; /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var AesAlgorithm = require('./aes-algorithm.js').AesAlgorithm; /** @ignore */
+var RsaAlgorithm = require('./rsa-algorithm.js').RsaAlgorithm; /** @ignore */
+var EncryptParams = require('./encrypt-params.js').EncryptParams; /** @ignore */
+var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var EncryptedContent = require('../encrypted-content.js').EncryptedContent; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise;
+
+/**
+ * Encryptor has static constants and utility methods for encryption, such as
+ * encryptData.
+ * @constructor
+ */
+var Encryptor = function Encryptor(value)
+{
+};
+
+exports.Encryptor = Encryptor;
+
+Encryptor.NAME_COMPONENT_FOR = new Name.Component("FOR");
+Encryptor.NAME_COMPONENT_READ = new Name.Component("READ");
+Encryptor.NAME_COMPONENT_SAMPLE = new Name.Component("SAMPLE");
+Encryptor.NAME_COMPONENT_ACCESS = new Name.Component("ACCESS");
+Encryptor.NAME_COMPONENT_E_KEY = new Name.Component("E-KEY");
+Encryptor.NAME_COMPONENT_D_KEY = new Name.Component("D-KEY");
+Encryptor.NAME_COMPONENT_C_KEY = new Name.Component("C-KEY");
+
+/**
+ * Prepare an encrypted data packet by encrypting the payload using the key
+ * according to the params. In addition, this prepares the encoded
+ * EncryptedContent with the encryption result using keyName and params. The
+ * encoding is set as the content of the data packet. If params defines an
+ * asymmetric encryption algorithm and the payload is larger than the maximum
+ * plaintext size, this encrypts the payload with a symmetric key that is
+ * asymmetrically encrypted and provided as a nonce in the content of the data
+ * packet. The packet's /<dataName>/ is updated to be <dataName>/FOR/<keyName>.
+ * @param {Data} data The data packet which is updated.
+ * @param {Blob} payload The payload to encrypt.
+ * @param {Name} keyName The key name for the EncryptedContent.
+ * @param {Blob} key The encryption key value.
+ * @param {EncryptParams} params The parameters for encryption.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which fulfills when the data packet
+ * is updated.
+ */
+Encryptor.encryptDataPromise = function
+  (data, payload, keyName, key, params, useSync)
+{
+  data.getName().append(Encryptor.NAME_COMPONENT_FOR).append(keyName);
+
+  var algorithmType = params.getAlgorithmType();
+
+  if (algorithmType == EncryptAlgorithmType.AesCbc ||
+      algorithmType == EncryptAlgorithmType.AesEcb) {
+    return Encryptor.encryptSymmetricPromise_
+      (payload, key, keyName, params, useSync)
+    .then(function(content) {
+      data.setContent(content.wireEncode(TlvWireFormat.get()));
+      return SyncPromise.resolve();
+    });
+  }
+  else if (algorithmType == EncryptAlgorithmType.RsaPkcs ||
+           algorithmType == EncryptAlgorithmType.RsaOaep) {
+    // Node.js doesn't have a direct way to get the maximum plain text size, so
+    // try to encrypt the payload first and catch the error if it is too big.
+    return Encryptor.encryptAsymmetricPromise_
+      (payload, key, keyName, params, useSync)
+    .then(function(content) {
+      data.setContent(content.wireEncode(TlvWireFormat.get()));
+      return SyncPromise.resolve();
+    }, function(err) {
+      if (err.message.indexOf("data too large for key size") < 0)
+        // Not the expected error.
+        throw err;
+
+      // The payload is larger than the maximum plaintext size.
+      // 128-bit nonce.
+      var nonceKeyBuffer = Crypto.randomBytes(16);
+      var nonceKey = new Blob(nonceKeyBuffer, false);
+
+      var nonceKeyName = new Name(keyName);
+      nonceKeyName.append("nonce");
+
+      var symmetricParams = new EncryptParams
+        (EncryptAlgorithmType.AesCbc, AesAlgorithm.BLOCK_SIZE);
+
+      var nonceContent;
+      return Encryptor.encryptSymmetricPromise_
+        (payload, nonceKey, nonceKeyName, symmetricParams, useSync)
+      .then(function(localNonceContent) {
+        nonceContent = localNonceContent;
+        return Encryptor.encryptAsymmetricPromise_
+          (nonceKey, key, keyName, params, useSync);
+      })
+      .then(function(payloadContent) {
+        var nonceContentEncoding = nonceContent.wireEncode();
+        var payloadContentEncoding = payloadContent.wireEncode();
+        var content = new Buffer
+          (nonceContentEncoding.size() + payloadContentEncoding.size());
+        payloadContentEncoding.buf().copy(content, 0);
+        nonceContentEncoding.buf().copy(content, payloadContentEncoding.size());
+
+        data.setContent(new Blob(content, false));
+        return SyncPromise.resolve();
+      });
+    });
+  }
+  else
+    return SyncPromise.reject(new Error("Unsupported encryption method"));
+};
+
+/**
+ * Prepare an encrypted data packet by encrypting the payload using the key
+ * according to the params. In addition, this prepares the encoded
+ * EncryptedContent with the encryption result using keyName and params. The
+ * encoding is set as the content of the data packet. If params defines an
+ * asymmetric encryption algorithm and the payload is larger than the maximum
+ * plaintext size, this encrypts the payload with a symmetric key that is
+ * asymmetrically encrypted and provided as a nonce in the content of the data
+ * packet.
+ * @param {Data} data The data packet which is updated.
+ * @param {Blob} payload The payload to encrypt.
+ * @param {Name} keyName The key name for the EncryptedContent.
+ * @param {Blob} key The encryption key value.
+ * @param {EncryptParams} params The parameters for encryption.
+ * @throws Error If encryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+Encryptor.encryptData = function(data, payload, keyName, key, params)
+{
+  return SyncPromise.getValue(Encryptor.encryptDataPromise
+    (data, payload, keyName, key, params, true));
+};
+
+/**
+ * Encrypt the payload using the symmetric key according to params, and return
+ * an EncryptedContent.
+ * @param {Blob} payload The data to encrypt.
+ * @param {Blob} key The key value.
+ * @param {Name} keyName The key name for the EncryptedContent key locator.
+ * @param {EncryptParams} params The parameters for encryption.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns a new EncryptedContent.
+ */
+Encryptor.encryptSymmetricPromise_ = function
+  (payload, key, keyName, params, useSync)
+{
+  var algorithmType = params.getAlgorithmType();
+  var initialVector = params.getInitialVector();
+  var keyLocator = new KeyLocator();
+  keyLocator.setType(KeyLocatorType.KEYNAME);
+  keyLocator.setKeyName(keyName);
+
+  if (algorithmType == EncryptAlgorithmType.AesCbc ||
+      algorithmType == EncryptAlgorithmType.AesEcb) {
+    if (algorithmType == EncryptAlgorithmType.AesCbc) {
+      if (initialVector.size() != AesAlgorithm.BLOCK_SIZE)
+        return SyncPromise.reject(new Error("incorrect initial vector size"));
+    }
+
+    return AesAlgorithm.encryptPromise(key, payload, params, useSync)
+    .then(function(encryptedPayload) {
+      var result = new EncryptedContent();
+      result.setAlgorithmType(algorithmType);
+      result.setKeyLocator(keyLocator);
+      result.setPayload(encryptedPayload);
+      result.setInitialVector(initialVector);
+      return SyncPromise.resolve(result);
+    });
+  }
+  else
+    return SyncPromise.reject(new Error("Unsupported encryption method"));
+};
+
+/**
+ * Encrypt the payload using the asymmetric key according to params, and
+ * return an EncryptedContent.
+ * @param {Blob} payload The data to encrypt. The size should be within range of
+ * the key.
+ * @param {Blob} key The key value.
+ * @param {Name} keyName The key name for the EncryptedContent key locator.
+ * @param {EncryptParams} params The parameters for encryption.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns a new EncryptedContent.
+ */
+Encryptor.encryptAsymmetricPromise_ = function
+  (payload, key, keyName, params, useSync)
+{
+  var algorithmType = params.getAlgorithmType();
+  var keyLocator = new KeyLocator();
+  keyLocator.setType(KeyLocatorType.KEYNAME);
+  keyLocator.setKeyName(keyName);
+
+  if (algorithmType == EncryptAlgorithmType.RsaPkcs ||
+      algorithmType == EncryptAlgorithmType.RsaOaep) {
+    return RsaAlgorithm.encryptPromise(key, payload, params, useSync)
+    .then(function(encryptedPayload) {
+      var result = new EncryptedContent();
+      result.setAlgorithmType(algorithmType);
+      result.setKeyLocator(keyLocator);
+      result.setPayload(encryptedPayload);
+      return SyncPromise.resolve(result);
+    });
+  }
+  else
+    return SyncPromise.reject(new Error("Unsupported encryption method"));
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/algo/rsa https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// (This is ported from ndn::gep::algo::Rsa, and named RsaAlgorithm because
+// "Rsa" is very short and not all the Common Client Libraries have namespaces.)
+
+/** @ignore */
+var constants = require('constants'); /** @ignore */
+var Crypto = require('../../crypto.js'); /** @ignore */
+var Blob = require('../../util/blob.js').Blob; /** @ignore */
+var DecryptKey = require('../decrypt-key.js').DecryptKey; /** @ignore */
+var EncryptKey = require('../encrypt-key.js').EncryptKey; /** @ignore */
+var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
+var OID = require('../../encoding/oid.js').OID; /** @ignore */
+var PrivateKeyStorage = require('../../security/identity/private-key-storage.js').PrivateKeyStorage; /** @ignore */
+var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
+var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
+var rsaKeygen = null;
+try {
+  // This should be installed with: sudo npm install rsa-keygen
+  rsaKeygen = require('rsa-keygen');
+}
+catch (e) {}
+
+/**
+ * The RsaAlgorithm class provides static methods to manipulate keys, encrypt
+ * and decrypt using RSA.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var RsaAlgorithm = function RsaAlgorithm()
+{
+};
+
+exports.RsaAlgorithm = RsaAlgorithm;
+
+/**
+ * Generate a new random decrypt key for RSA based on the given params.
+ * @param {RsaKeyParams} params The key params with the key size (in bits).
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the new DecryptKey
+ * (containing a PKCS8-encoded private key).
+ */
+RsaAlgorithm.generateKeyPromise = function(params, useSync)
+{
+  if (UseSubtleCrypto() && !useSync) {
+    return crypto.subtle.generateKey
+      ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
+         publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+         hash: {name: "SHA-256"} },
+       true, ["sign", "verify"])
+    .then(function(key) {
+      // Export the private key to DER.
+      return crypto.subtle.exportKey("pkcs8", key.privateKey);
+    })
+    .then(function(pkcs8Der) {
+      return Promise.resolve(new DecryptKey
+        (new Blob(new Uint8Array(pkcs8Der), false)));
+    });
+  }
+  else {
+    if (!rsaKeygen)
+      return SyncPromise.reject(new Error
+        ("Need to install rsa-keygen: sudo npm install rsa-keygen"));
+
+    try {
+      var keyPair = rsaKeygen.generate(params.getKeySize());
+      // Get the PKCS1 private key DER from the PEM string and encode as PKCS8.
+      var privateKeyBase64 = keyPair.private_key.toString().replace
+        ("-----BEGIN RSA PRIVATE KEY-----", "").replace
+        ("-----END RSA PRIVATE KEY-----", "");
+      var pkcs1PrivateKeyDer = new Buffer(privateKeyBase64, 'base64');
+      var privateKey = PrivateKeyStorage.encodePkcs8PrivateKey
+        (pkcs1PrivateKeyDer, new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),
+         new DerNode.DerNull()).buf();
+
+      return SyncPromise.resolve(new DecryptKey(privateKey));
+    } catch (err) {
+      return SyncPromise.reject(err);
+    }
+  }
+};
+
+/**
+ * Generate a new random decrypt key for RSA based on the given params.
+ * @param {RsaKeyParams} params The key params with the key size (in bits).
+ * @return {DecryptKey} The new decrypt key (containing a PKCS8-encoded private
+ * key).
+ * @throws Error If generateKeyPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+RsaAlgorithm.generateKey = function(params)
+{
+  return SyncPromise.getValue(this.generateKeyPromise(params, true));
+};
+
+/**
+ * Derive a new encrypt key from the given decrypt key value.
+ * @param {Blob} keyBits The key value of the decrypt key (PKCS8-encoded private
+ * key).
+ * @return {EncryptKey} The new encrypt key (DER-encoded public key).
+ */
+RsaAlgorithm.deriveEncryptKey = function(keyBits)
+{
+  var rsaPrivateKeyDer = RsaAlgorithm.getRsaPrivateKeyDer(keyBits);
+
+  // Decode the PKCS #1 RSAPrivateKey.
+  var parsedNode = DerNode.parse(rsaPrivateKeyDer.buf(), 0);
+  var rsaPrivateKeyChildren = parsedNode.getChildren();
+  var modulus = rsaPrivateKeyChildren[1];
+  var publicExponent = rsaPrivateKeyChildren[2];
+
+  // Encode the PKCS #1 RSAPublicKey.
+  var rsaPublicKey = new DerNode.DerSequence();
+  rsaPublicKey.addChild(modulus);
+  rsaPublicKey.addChild(publicExponent);
+  var rsaPublicKeyDer = rsaPublicKey.encode();
+
+  // Encode the SubjectPublicKeyInfo.
+  var algorithmIdentifier = new DerNode.DerSequence();
+  algorithmIdentifier.addChild(new DerNode.DerOid(new OID
+    (PrivateKeyStorage.RSA_ENCRYPTION_OID)));
+  algorithmIdentifier.addChild(new DerNode.DerNull());
+  var publicKey = new DerNode.DerSequence();
+  publicKey.addChild(algorithmIdentifier);
+  publicKey.addChild(new DerNode.DerBitString(rsaPublicKeyDer.buf(), 0));
+
+  return new EncryptKey(publicKey.encode());
+};
+
+/**
+ * Decrypt the encryptedData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value (PKCS8-encoded private key).
+ * @param {Blob} encryptedData The data to decrypt.
+ * @param {EncryptParams} params This decrypts according to
+ * params.getAlgorithmType().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the decrypted Blob.
+ */
+RsaAlgorithm.decryptPromise = function(keyBits, encryptedData, params, useSync)
+{
+  if (UseSubtleCrypto() && !useSync &&
+      // Crypto.subtle doesn't implement PKCS1 padding.
+      params.getAlgorithmType() != EncryptAlgorithmType.RsaPkcs) {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
+      return crypto.subtle.importKey
+        ("pkcs8", keyBits.buf(), { name: "RSA-OAEP", hash: {name: "SHA-1"} },
+         false, ["decrypt"])
+      .then(function(privateKey) {
+        return crypto.subtle.decrypt
+          ({ name: "RSA-OAEP" }, privateKey, encryptedData.buf());
+      })
+      .then(function(result) {
+        return Promise.resolve(new Blob(new Uint8Array(result), false));
+      });
+    }
+    else
+      return Promise.reject(new Error("unsupported padding scheme"));
+  }
+  else {
+    // keyBits is PKCS #8 but we need the inner RSAPrivateKey.
+    var rsaPrivateKeyDer = RsaAlgorithm.getRsaPrivateKeyDer(keyBits);
+
+    // Encode the key DER as a PEM private key as needed by Crypto.
+    var keyBase64 = rsaPrivateKeyDer.buf().toString('base64');
+    var keyPem = "-----BEGIN RSA PRIVATE KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END RSA PRIVATE KEY-----";
+
+    var padding;
+    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaPkcs)
+      padding = constants.RSA_PKCS1_PADDING;
+    else if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep)
+      padding = constants.RSA_PKCS1_OAEP_PADDING;
+    else
+      return SyncPromise.reject(new Error("unsupported padding scheme"));
+
+    try {
+      // In Node.js, privateDecrypt requires version v0.12.
+      return SyncPromise.resolve(new Blob
+        (Crypto.privateDecrypt({ key: keyPem, padding: padding }, encryptedData.buf()),
+         false));
+    } catch (err) {
+      return SyncPromise.reject(err);
+    }
+  }
+};
+
+/**
+ * Decrypt the encryptedData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value (PKCS8-encoded private key).
+ * @param {Blob} encryptedData The data to decrypt.
+ * @param {EncryptParams} params This decrypts according to
+ * params.getAlgorithmType().
+ * @return {Blob} The decrypted data.
+ * @throws Error If decryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+RsaAlgorithm.decrypt = function(keyBits, encryptedData, params)
+{
+  return SyncPromise.getValue(this.decryptPromise
+    (keyBits, encryptedData, params, true));
+};
+
+/**
+ * Encrypt the plainData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value (DER-encoded public key).
+ * @param {Blob} plainData The data to encrypt.
+ * @param {EncryptParams} params This encrypts according to
+ * params.getAlgorithmType().
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise which returns the encrypted Blob.
+ */
+RsaAlgorithm.encryptPromise = function(keyBits, plainData, params, useSync)
+{
+  if (UseSubtleCrypto() && !useSync &&
+      // Crypto.subtle doesn't implement PKCS1 padding.
+      params.getAlgorithmType() != EncryptAlgorithmType.RsaPkcs) {
+    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
+      return crypto.subtle.importKey
+        ("spki", keyBits.buf(), { name: "RSA-OAEP", hash: {name: "SHA-1"} },
+         false, ["encrypt"])
+      .then(function(publicKey) {
+        return crypto.subtle.encrypt
+          ({ name: "RSA-OAEP" }, publicKey, plainData.buf());
+      })
+      .then(function(result) {
+        return Promise.resolve(new Blob(new Uint8Array(result), false));
+      });
+    }
+    else
+      return Promise.reject(new Error("unsupported padding scheme"));
+  }
+  else {
+    // Encode the key DER as a PEM public key as needed by Crypto.
+    var keyBase64 = keyBits.buf().toString('base64');
+    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
+    for (var i = 0; i < keyBase64.length; i += 64)
+      keyPem += (keyBase64.substr(i, 64) + "\n");
+    keyPem += "-----END PUBLIC KEY-----";
+
+    var padding;
+    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaPkcs)
+      padding = constants.RSA_PKCS1_PADDING;
+    else if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep)
+      padding = constants.RSA_PKCS1_OAEP_PADDING;
+    else
+      return SyncPromise.reject(new Error("unsupported padding scheme"));
+
+    try {
+      // In Node.js, publicEncrypt requires version v0.12.
+      return SyncPromise.resolve(new Blob
+        (Crypto.publicEncrypt({ key: keyPem, padding: padding }, plainData.buf()),
+         false));
+    } catch (err) {
+      return SyncPromise.reject(err);
+    }
+  }
+};
+
+/**
+ * Encrypt the plainData using the keyBits according the encrypt params.
+ * @param {Blob} keyBits The key value (DER-encoded public key).
+ * @param {Blob} plainData The data to encrypt.
+ * @param {EncryptParams} params This encrypts according to
+ * params.getAlgorithmType().
+ * @return {Blob} The encrypted data.
+ * @throws Error If encryptPromise doesn't return a SyncPromise which is
+ * already fulfilled.
+ */
+RsaAlgorithm.encrypt = function(keyBits, plainData, params)
+{
+  return SyncPromise.getValue(this.encryptPromise
+    (keyBits, plainData, params, true));
+};
+
+/**
+ * Decode the PKCS #8 private key, check that the algorithm is RSA, and return
+ * the inner RSAPrivateKey DER.
+ * @param {Blob} The DER-encoded PKCS #8 private key.
+ * @param {Blob} The DER-encoded RSAPrivateKey.
+ */
+RsaAlgorithm.getRsaPrivateKeyDer = function(pkcs8PrivateKeyDer)
+{
+  var parsedNode = DerNode.parse(pkcs8PrivateKeyDer.buf(), 0);
+  var pkcs8Children = parsedNode.getChildren();
+  var algorithmIdChildren = DerNode.getSequence(pkcs8Children, 1).getChildren();
+  var oidString = algorithmIdChildren[0].toVal();
+
+  if (oidString != PrivateKeyStorage.RSA_ENCRYPTION_OID)
+    throw new Error("The PKCS #8 private key is not RSA_ENCRYPTION");
+
+  return pkcs8Children[2].getPayload();
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/consumer-db https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise;
+
+/**
+ * ConsumerDb is a base class the storage of decryption keys for the consumer. A
+ * subclass must implement the methods. For example, see Sqlite3ConsumerDb (for
+ * Nodejs) or IndexedDbConsumerDb (for the browser).
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var ConsumerDb = function ConsumerDb()
+{
+};
+
+exports.ConsumerDb = ConsumerDb;
+
+/**
+ * Create a new ConsumerDb.Error to report an error using ConsumerDb
+ * methods, wrapping the given error object.
+ * Call with: throw new ConsumerDb.Error(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+ConsumerDb.Error = function ConsumerDbError(error)
+{
+  if (error) {
+    error.__proto__ = ConsumerDb.Error.prototype;
+    return error;
+  }
+}
+
+ConsumerDb.Error.prototype = new Error();
+ConsumerDb.Error.prototype.name = "ConsumerDbError";
+
+/**
+ * Get the key with keyName from the database.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
+ * key (or an isNull Blob if cannot find the key with keyName), or that is
+ * rejected with ConsumerDb.Error for a database error.
+ */
+ConsumerDb.prototype.getKeyPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ConsumerDb.getKeyPromise is not implemented"));
+};
+
+/**
+ * Add the key with keyName and keyBlob to the database.
+ * @param {Name} keyName The key name.
+ * @param {Blob} keyBlob The encoded key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
+ * or that is rejected with ConsumerDb.Error if a key with the same keyName
+ * already exists, or other database error.
+ */
+ConsumerDb.prototype.addKeyPromise = function(keyName, keyBlob, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ConsumerDb.addKeyPromise is not implemented"));
+};
+
+/**
+ * Delete the key with keyName from the database. If there is no key with
+ * keyName, do nothing.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is deleted
+ * (or there is no such key), or that is rejected with ConsumerDb.Error for a
+ * database error.
+ */
+ConsumerDb.prototype.deleteKeyPromise = function(keyName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ConsumerDb.addKeyPromise is not implemented"));
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/consumer https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
+var Link = require('../link.js').Link; /** @ignore */
+var EncryptedContent = require('./encrypted-content.js').EncryptedContent; /** @ignore */
+var EncryptError = require('./encrypt-error.js').EncryptError; /** @ignore */
+var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
+var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var RsaAlgorithm = require('./algo/rsa-algorithm.js').RsaAlgorithm; /** @ignore */
+var AesAlgorithm = require('./algo/aes-algorithm.js').AesAlgorithm; /** @ignore */
+var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon;
+
+/**
+ * A Consumer manages fetched group keys used to decrypt a data packet in the
+ * group-based encryption protocol.
+ * Create a Consumer to use the given ConsumerDb, Face and other values.
+ * @param {Face} face The face used for data packet and key fetching.
+ * @param {KeyChain} keyChain The keyChain used to verify data packets.
+ * @param {Name} groupName The reading group name that the consumer belongs to.
+ * This makes a copy of the Name.
+ * @param {Name} consumerName The identity of the consumer. This makes a copy of
+ * the Name.
+ * @param {ConsumerDb} database The ConsumerDb database for storing decryption
+ * keys.
+ * @param {Link} cKeyLink (optional) The Link object to use in Interests for
+ * C-KEY retrieval. This makes a copy of the Link object. If the Link object's
+ * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
+ * object.
+ * @param {Link} dKeyLink (optional) The Link object to use in Interests for
+ * D-KEY retrieval. This makes a copy of the Link object. If the Link object's
+ * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
+ * object.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var Consumer = function Consumer
+  (face, keyChain, groupName, consumerName, database, cKeyLink, dKeyLink)
+{
+  this.database_ = database;
+  this.keyChain_ = keyChain;
+  this.face_ = face;
+  this.groupName_ = new Name(groupName);
+  this.consumerName_ = new Name(consumerName);
+  this.cKeyLink_ =
+    (cKeyLink == undefined ? Consumer.NO_LINK : new Link(cKeyLink));
+  this.dKeyLink_ =
+    (dKeyLink == undefined ? Consumer.NO_LINK : new Link(dKeyLink));
+
+  // The map key is the C-KEY name URI string. The value is the encoded key Blob.
+  // (Use a string because we can't use the Name object as the key in JavaScript.)
+  this.cKeyMap_ = {};
+  // The map key is the D-KEY name URI string. The value is the encoded key Blob.
+  this.dKeyMap_ = {};
+};
+
+exports.Consumer = Consumer;
+
+/**
+ * Express an Interest to fetch the content packet with contentName, and
+ * decrypt it, fetching keys as needed.
+ * @param {Name} contentName The name of the content packet.
+ * @param {function} onConsumeComplete When the content packet is fetched and
+ * decrypted, this calls onConsumeComplete(contentData, result) where
+ * contentData is the fetched Data packet and result is the decrypted plain
+ * text Blob.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param link {Link} (optional) The Link object to use in Interests for data
+ * retrieval. This makes a copy of the Link object. If the Link object's
+ * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
+ * object.
+ */
+Consumer.prototype.consume = function
+  (contentName, onConsumeComplete, onError, link)
+{
+  if (link == undefined)
+    link = Consumer.NO_LINK;
+
+  var interest = new Interest(contentName);
+  var thisConsumer = this;
+  // Copy the Link object since the passed link may become invalid.
+  this.sendInterest_
+    (interest, 1, new Link(link),
+     function(validData) {
+       // Decrypt the content.
+       thisConsumer.decryptContent_(validData, function(plainText) {
+         try {
+           onConsumeComplete(validData, plainText);
+         } catch (ex) {
+           console.log("Error in onConsumeComplete: " + NdnCommon.getErrorWithStackTrace(ex));
+         }
+       }, onError);
+     },
+     onError);
+};
+
+/**
+ * Set the group name.
+ * @param {Name} groupName The reading group name that the consumer belongs to.
+ * This makes a copy of the Name.
+ */
+Consumer.prototype.setGroup = function(groupName)
+{
+  this.groupName_ = new Name(groupName);
+};
+
+/**
+ * Add a new decryption key with keyName and keyBlob to the database.
+ * @param {Name} keyName The key name.
+ * @param {Blob} keyBlob The encoded key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
+ * or that is rejected with Error if the consumer name is not a prefix of the
+ * key name, or ConsumerDb.Error if a key with the same keyName already exists,
+ * or other database error.
+ */
+Consumer.prototype.addDecryptionKeyPromise = function(keyName, keyBlob, useSync)
+{
+  if (!(this.consumerName_.match(keyName)))
+    return SyncPromise.reject(new Error
+      ("addDecryptionKey: The consumer name must be a prefix of the key name"));
+
+  return this.database_.addKeyPromise(keyName, keyBlob, useSync);
+};
+
+/**
+ * Add a new decryption key with keyName and keyBlob to the database.
+ * @param {Name} keyName The key name.
+ * @param {Blob} keyBlob The encoded key.
+ * @param {function} onComplete (optional) This calls onComplete() when the key
+ * is added. (Some database libraries only use a callback, so onComplete is
+ * required to use these.)
+ * @param {function} onError (optional) If defined, then onComplete must be
+ * defined and if there is an exception, then this calls onError(exception)
+ * where exception is Error if the consumer name is not a prefix of the key
+ * name, or ConsumerDb.Error if a key with the same keyName already exists,
+ * or other database error. If onComplete is defined but onError is undefined,
+ * then this will log any thrown exception. (Some database libraries only use a
+ * callback, so onError is required to be notified of an exception.)
+ */
+Consumer.prototype.addDecryptionKey = function
+  (keyName, keyBlob, onComplete, onError)
+{
+  return SyncPromise.complete(onComplete, onError,
+    this.addDecryptionKeyPromise(keyName, keyBlob, !onComplete));
+};
+
+/**
+ * Consume.Error is used internally from promised-based methods to reject with
+ * an error object that has the errorCode and message returned through the
+ * onError callback.
+ * @param {number} errorCode An error code from EncryptError.ErrorCode.
+ * @param {string} message The error message.
+ */
+Consumer.Error = function ConsumerError(errorCode, message)
+{
+  this.errorCode = errorCode;
+  this.message = message;
+};
+
+/**
+ * If exception is a ConsumerError, then call onError with the errorCode and
+ * message, otherwise call onError with ErrorCode.General.
+ */
+Consumer.Error.callOnError = function(onError, exception, messagePrefix)
+{
+  if (!messagePrefix)
+    messagePrefix = "";
+
+  if (exception instanceof Consumer.Error) {
+    try {
+      onError(exception.errorCode, exception.message);
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+  else {
+    try {
+      onError(EncryptError.ErrorCode.General, messagePrefix + exception);
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+}
+
+/**
+ * Decrypt encryptedContent using keyBits.
+ * @param {Blob|EncryptedContent} encryptedContent The EncryptedContent to
+ * decrypt, or a Blob which is first decoded as an EncryptedContent.
+ * @param {Blob} keyBits The key value.
+ * @return {Promise|SyncPromise} A promise that returns the decrypted Blob, or
+ * that is rejected with Consumer.Error or other error.
+ */
+Consumer.decryptPromise_ = function(encryptedContent, keyBits)
+{
+  return SyncPromise.resolve()
+  .then(function() {
+    if (typeof encryptedContent == 'object' && encryptedContent instanceof Blob) {
+      // Decode as EncryptedContent.
+      var encryptedBlob = encryptedContent;
+      encryptedContent = new EncryptedContent();
+      encryptedContent.wireDecode(encryptedBlob);
+    }
+
+    var payload = encryptedContent.getPayload();
+
+    if (encryptedContent.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
+      // Prepare the parameters.
+      var decryptParams = new EncryptParams(EncryptAlgorithmType.AesCbc);
+      decryptParams.setInitialVector(encryptedContent.getInitialVector());
+
+      // Decrypt the content.
+      return AesAlgorithm.decryptPromise(keyBits, payload, decryptParams);
+    }
+    else if (encryptedContent.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
+      // Prepare the parameters.
+      var decryptParams = new EncryptParams(EncryptAlgorithmType.RsaOaep);
+
+      // Decrypt the content.
+      return RsaAlgorithm.decryptPromise(keyBits, payload, decryptParams);
+    }
+    else
+      return SyncPromise.reject(new Consumer.Error
+        (EncryptError.ErrorCode.UnsupportedEncryptionScheme,
+          "" + encryptedContent.getAlgorithmType()));
+  });
+};
+
+/**
+ * Decrypt encryptedContent using keyBits.
+ * @param {Blob|EncryptedContent} encryptedContent The EncryptedContent to
+ * decrypt, or a Blob which is first decoded as an EncryptedContent.
+ * @param {Blob} keyBits The key value.
+ * @param {function} onPlainText When the data packet is decrypted, this calls
+ * onPlainText(decryptedBlob) with the decrypted Blob.
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ */
+Consumer.decrypt_ = function(encryptedContent, keyBits, onPlainText, onError)
+{
+  Consumer.decryptPromise_(encryptedContent, keyBits)
+  .then(function(decryptedBlob) {
+    onPlainText(decryptedBlob);
+  }, function(ex) {
+    Consumer.Error.callOnError(onError, ex);
+  });
+};
+
+/**
+ * Decrypt the data packet.
+ * @param {Data} data The data packet. This does not verify the packet.
+ * @param {function} onPlainText When the data packet is decrypted, this calls
+ * onPlainText(decryptedBlob) with the decrypted Blob.
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ */
+Consumer.prototype.decryptContent_ = function(data, onPlainText, onError)
+{
+  // Get the encrypted content.
+  var dataEncryptedContent = new EncryptedContent();
+  try {
+    dataEncryptedContent.wireDecode(data.getContent());
+  } catch (ex) {
+    Consumer.Error.callOnError(onError, ex, "Error decoding EncryptedContent: ");
+    return;
+  }
+  var cKeyName = dataEncryptedContent.getKeyLocator().getKeyName();
+
+  // Check if the content key is already in the store.
+  var cKey = this.cKeyMap_[cKeyName.toUri()];
+  if (cKey)
+    this.decrypt_(dataEncryptedContent, cKey, onPlainText, onError);
+  else {
+    // Retrieve the C-KEY Data from the network.
+    var interestName = new Name(cKeyName);
+    interestName.append(Encryptor.NAME_COMPONENT_FOR).append(this.groupName_);
+    var interest = new Interest(interestName);
+    var thisConsumer = this;
+    this.sendInterest_
+      (interest, 1, this.cKeyLink_,
+       function(validCKeyData) {
+         thisConsumer.decryptCKey_(validCKeyData, function(cKeyBits) {
+           thisConsumer.cKeyMap_[cKeyName.toUri()] = cKeyBits;
+           Consumer.decrypt_
+             (dataEncryptedContent, cKeyBits, onPlainText, onError);
+         }, onError);
+       },
+       onError);
+  }
+};
+
+/**
+ * Decrypt cKeyData.
+ * @param {Data} cKeyData The C-KEY data packet.
+ * @param {function} onPlainText When the data packet is decrypted, this calls
+ * onPlainText(decryptedBlob) with the decrypted Blob.
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ */
+Consumer.prototype.decryptCKey_ = function(cKeyData, onPlainText, onError)
+{
+  // Get the encrypted content.
+  var cKeyContent = cKeyData.getContent();
+  var cKeyEncryptedContent = new EncryptedContent();
+  try {
+    cKeyEncryptedContent.wireDecode(cKeyContent);
+  } catch (ex) {
+    Consumer.Error.callOnError(onError, ex, "Error decoding EncryptedContent: ");
+    return;
+  }
+  var eKeyName = cKeyEncryptedContent.getKeyLocator().getKeyName();
+  var dKeyName = eKeyName.getPrefix(-3);
+  dKeyName.append(Encryptor.NAME_COMPONENT_D_KEY).append(eKeyName.getSubName(-2));
+
+  // Check if the decryption key is already in the store.
+  var dKey = this.dKeyMap_[dKeyName.toUri()];
+  if (dKey)
+    this.decrypt_(cKeyEncryptedContent, dKey, onPlainText, onError);
+  else {
+    // Get the D-Key Data.
+    var interestName = new Name(dKeyName);
+    interestName.append(Encryptor.NAME_COMPONENT_FOR).append(this.consumerName_);
+    var interest = new Interest(interestName);
+    var thisConsumer = this;
+    this.sendInterest_
+      (interest, 1, this.dKeyLink_,
+       function(validDKeyData) {
+         thisConsumer.decryptDKeyPromise_(validDKeyData)
+         .then(function(dKeyBits) {
+           thisConsumer.dKeyMap_[dKeyName.toUri()] = dKeyBits;
+           Consumer.decrypt_
+             (cKeyEncryptedContent, dKeyBits, onPlainText, onError);
+         }, function(ex) {
+           Consumer.Error.callOnError(onError, ex, "decryptDKey error: ");
+         });
+       },
+       onError);
+  }
+};
+
+/**
+ * Decrypt dKeyData.
+ * @param {Data} dKeyData The D-KEY data packet.
+ * @return {Promise|SyncPromise} A promise that returns the decrypted Blob, or
+ * that is rejected with Consumer.Error or other error.
+ */
+Consumer.prototype.decryptDKeyPromise_ = function(dKeyData)
+{
+  var dataContent;
+  var encryptedNonce;
+  var encryptedPayloadBlob;
+  var thisConsumer = this;
+
+  return SyncPromise.resolve()
+  .then(function() {
+    // Get the encrypted content.
+    dataContent = dKeyData.getContent();
+
+    // Process the nonce.
+    // dataContent is a sequence of the two EncryptedContent.
+    encryptedNonce = new EncryptedContent();
+    encryptedNonce.wireDecode(dataContent);
+    var consumerKeyName = encryptedNonce.getKeyLocator().getKeyName();
+
+    // Get consumer decryption key.
+    return thisConsumer.getDecryptionKeyPromise_(consumerKeyName);
+  })
+  .then(function(consumerKeyBlob) {
+    if (consumerKeyBlob.size() == 0)
+      return SyncPromise.reject(new Consumer.Error
+        (EncryptError.ErrorCode.NoDecryptKey,
+         "The desired consumer decryption key in not in the database"));
+
+    // Process the D-KEY.
+    // Use the size of encryptedNonce to find the start of encryptedPayload.
+    var encryptedPayloadBuffer = dataContent.buf().slice
+      (encryptedNonce.wireEncode().size());
+    encryptedPayloadBlob = new Blob(encryptedPayloadBuffer, false);
+    if (encryptedPayloadBlob.size() == 0)
+      return SyncPromise.reject(new Consumer.Error
+        (EncryptError.ErrorCode.InvalidEncryptedFormat,
+         "The data packet does not satisfy the D-KEY packet format"));
+
+    // Decrypt the D-KEY.
+    return Consumer.decryptPromise_(encryptedNonce, consumerKeyBlob);
+  })
+  .then(function(nonceKeyBits) {
+    return Consumer.decryptPromise_(encryptedPayloadBlob, nonceKeyBits);
+  });
+};
+
+/**
+ * Express the interest, call verifyData for the fetched Data packet and call
+ * onVerified if verify succeeds. If verify fails, call
+ * onError(EncryptError.ErrorCode.Validation, "verifyData failed"). If the
+ * interest times out, re-express nRetrials times. If the interest times out
+ * nRetrials times, or for a network Nack, call
+ * onError(EncryptError.ErrorCode.DataRetrievalFailure, interest.getName().toUri()).
+ * @param {Interest} interest The Interest to express.
+ * @param {number} nRetrials The number of retrials left after a timeout.
+ * @param {Link} link The Link object to use in the Interest. This does not make
+ * a copy of the Link object. If the Link object's getDelegations().size() is
+ * zero, don't use it.
+ * @param {function} onVerified When the fetched Data packet validation
+ * succeeds, this calls onVerified(data).
+ * @param {function} onError This calls onError(errorCode, message) for an error,
+ * where errorCode is an error code from EncryptError.ErrorCode.
+ */
+Consumer.prototype.sendInterest_ = function
+  (interest, nRetrials, link, onVerified, onError)
+{
+  // Prepare the callback functions.
+  var thisConsumer = this;
+  var onData = function(contentInterest, contentData) {
+    try {
+      thisConsumer.keyChain_.verifyData
+        (contentData, onVerified,
+         function(d, reason) {
+           try {
+             onError
+               (EncryptError.ErrorCode.Validation, "verifyData failed. Reason: " +
+                reason);
+           } catch (ex) {
+             console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+           }
+         });
+    } catch (ex) {
+      Consumer.Error.callOnError(onError, ex, "verifyData error: ");
+    }
+  };
+
+  function onNetworkNack(interest, networkNack) {
+    // We have run out of options. Report a retrieval failure.
+    try {
+      onError(EncryptError.ErrorCode.DataRetrievalFailure,
+              interest.getName().toUri());
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+
+  var onTimeout = function(interest) {
+    if (nRetrials > 0)
+      thisConsumer.sendInterest_(interest, nRetrials - 1, link, onVerified, onError);
+    else
+      onNetworkNack(interest, new NetworkNack());
+  };
+
+  var request;
+  if (link.getDelegations().size() === 0)
+    // We can use the supplied interest without copying.
+    request = interest;
+  else {
+    // Copy the supplied interest and add the Link.
+    request = new Interest(interest);
+    // This will use a cached encoding if available.
+    request.setLinkWireEncoding(link.wireEncode());
+  }
+
+  try {
+    this.face_.expressInterest(request, onData, onTimeout, onNetworkNack);
+  } catch (ex) {
+    Consumer.Error.callOnError(onError, ex, "expressInterest error: ");
+  }
+};
+
+/**
+ * Get the encoded blob of the decryption key with decryptionKeyName from the
+ * database.
+ * @param {Name} decryptionKeyName The key name.
+ * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
+ * key (or an isNull Blob if cannot find the key with decryptionKeyName), or
+ * that is rejected with ConsumerDb.Error for a database error.
+ */
+Consumer.prototype.getDecryptionKeyPromise_ = function(decryptionKeyName)
+{
+  return this.database_.getKeyPromise(decryptionKeyName);
+};
+
+Consumer.NO_LINK = new Link();
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/decrypt-key https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * A DecryptKey supplies the key for decrypt.
+ * Create a DecryptKey with the given key value.
+ * @param {Blob|DecryptKey} value If value is another DecryptKey then copy it.
+ * Otherwise, value is the key value.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var DecryptKey = function DecryptKey(value)
+{
+  if (typeof value === 'object' && value instanceof DecryptKey) {
+    // Make a deep copy.
+    this.keyBits_ = value.keyBits_;
+  }
+  else {
+    var keyBits = value;
+    this.keyBits_ = typeof keyBits === 'object' && keyBits instanceof Blob ?
+      keyBits : new Blob(keyBits);
+  }
+};
+
+exports.DecryptKey = DecryptKey;
+
+/**
+ * Get the key value.
+ * @return {Blob} The key value.
+ */
+DecryptKey.prototype.getKeyBits = function() { return this.keyBits_; };
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/error-code https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * EncryptError holds the ErrorCode enum for errors from the encrypt library.
+ */
+var EncryptError = function EncryptError()
+{
+};
+
+exports.EncryptError = EncryptError;
+
+EncryptError.ErrorCode = {
+  Timeout:                     1,
+  Validation:                  2,
+  UnsupportedEncryptionScheme: 32,
+  InvalidEncryptedFormat:      33,
+  NoDecryptKey:                34,
+  EncryptionFailure:           35,
+  DataRetrievalFailure:        36,
+  General:                     100
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/encrypt-key https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * An EncryptKey supplies the key for encrypt.
+ * Create an EncryptKey with the given key value.
+ * @param {Blob|EncryptKey} value If value is another EncryptKey then copy it.
+ * Otherwise, value is the key value.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var EncryptKey = function EncryptKey(value)
+{
+  if (typeof value === 'object' && value instanceof EncryptKey) {
+    // Make a deep copy.
+    this.keyBits_ = value.keyBits_;
+  }
+  else {
+    var keyBits = value;
+    this.keyBits_ = typeof keyBits === 'object' && keyBits instanceof Blob ?
+      keyBits : new Blob(keyBits);
+  }
+};
+
+exports.EncryptKey = EncryptKey;
+
+/**
+ * Get the key value.
+ * @return {Blob} The key value.
+ */
+EncryptKey.prototype.getKeyBits = function() { return this.keyBits_; };
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/encrypted-content https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var KeyLocator = require('../key-locator.js').KeyLocator; /** @ignore */
+var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * An EncryptedContent holds an encryption type, a payload and other fields
+ * representing encrypted content.
+ * @param {EncryptedContent} (optional) If value is another EncryptedContent
+ * then copy it. If value is omitted then create an EncryptedContent with
+ * unspecified values.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var EncryptedContent = function EncryptedContent(value)
+{
+  if (typeof value === 'object' && value instanceof EncryptedContent) {
+    // Make a deep copy.
+    this.algorithmType_ = value.algorithmType_;
+    this.keyLocator_ = new KeyLocator(value.keyLocator_);
+    this.initialVector_ = value.initialVector_;
+    this.payload_ = value.payload_;
+  }
+  else {
+    this.algorithmType_ = null;
+    this.keyLocator_ = new KeyLocator();
+    this.initialVector_ = new Blob();
+    this.payload_ = new Blob();
+  }
+};
+
+exports.EncryptedContent = EncryptedContent;
+
+/**
+ * Get the algorithm type from EncryptAlgorithmType.
+ * @return {number} The algorithm type from EncryptAlgorithmType, or null if
+ * not specified.
+ */
+EncryptedContent.prototype.getAlgorithmType = function()
+{
+  return this.algorithmType_;
+};
+
+/**
+ * Get the key locator.
+ * @return {KeyLocator} The key locator. If not specified, getType() is null.
+ */
+EncryptedContent.prototype.getKeyLocator = function()
+{
+  return this.keyLocator_;
+};
+
+/**
+ * Get the initial vector.
+ * @return {Blob} The initial vector. If not specified, isNull() is true.
+ */
+EncryptedContent.prototype.getInitialVector = function()
+{
+  return this.initialVector_;
+};
+
+/**
+ * Get the payload.
+ * @return {Blob} The payload. If not specified, isNull() is true.
+ */
+EncryptedContent.prototype.getPayload = function()
+{
+  return this.payload_;
+};
+
+/**
+ * Set the algorithm type.
+ * @param {number} algorithmType The algorithm type from EncryptAlgorithmType.
+ * If not specified, set to null.
+ * @return {EncryptedContent} This EncryptedContent so that you can chain calls
+ * to update values.
+ */
+EncryptedContent.prototype.setAlgorithmType = function(algorithmType)
+{
+  this.algorithmType_ = algorithmType;
+  return this;
+};
+
+/**
+ * Set the key locator.
+ * @param {KeyLocator} keyLocator The key locator. This makes a copy of the
+ * object. If not specified, set to the default KeyLocator().
+ * @return {EncryptedContent} This EncryptedContent so that you can chain calls
+ * to update values.
+ */
+EncryptedContent.prototype.setKeyLocator = function(keyLocator)
+{
+  this.keyLocator_ = typeof keyLocator === 'object' &&
+                       keyLocator instanceof KeyLocator ?
+    new KeyLocator(keyLocator) : new KeyLocator();
+  return this;
+};
+
+/**
+ * Set the initial vector.
+ * @param {Blob} initialVector The initial vector. If not specified, set to the
+ * default Blob() where isNull() is true.
+ * @return {EncryptedContent} This EncryptedContent so that you can chain calls
+ * to update values.
+ */
+EncryptedContent.prototype.setInitialVector = function(initialVector)
+{
+  this.initialVector_ =
+      typeof initialVector === 'object' && initialVector instanceof Blob ?
+    initialVector : new Blob(initialVector);
+  return this;
+};
+
+/**
+ * Set the encrypted payload.
+ * @param {Blob} payload The payload. If not specified, set to the default Blob()
+ * where isNull() is true.
+ * @return {EncryptedContent} This EncryptedContent so that you can chain calls
+ * to update values.
+ */
+EncryptedContent.prototype.setPayload = function(payload)
+{
+  this.payload_ = typeof payload === 'object' && payload instanceof Blob ?
+    payload : new Blob(payload);
+  return this;
+};
+
+/**
+ * Encode this EncryptedContent for a particular wire format.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {Blob} The encoded buffer in a Blob object.
+ */
+EncryptedContent.prototype.wireEncode = function(wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  return wireFormat.encodeEncryptedContent(this);
+};
+
+/**
+ * Decode the input using a particular wire format and update this
+ * EncryptedContent.
+ * @param {Blob|Buffer} input The buffer with the bytes to decode.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
+ * this object. If omitted, use WireFormat.getDefaultWireFormat().
+ */
+EncryptedContent.prototype.wireDecode = function(input, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+  if (typeof input === 'object' && input instanceof Blob)
+    // Input is a blob, so get its buf() and set copy false.
+    wireFormat.decodeEncryptedContent(this, input.buf(), false);
+  else
+    wireFormat.decodeEncryptedContent(this, input, true);
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/group-manager-db https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise;
+
+/**
+ * GroupManagerDb is a base class for the storage of data used by the
+ * GroupManager. It contains two tables to store Schedules and Members.
+ * This is an abstract base class. A subclass must implement the methods.
+ * For example, see Sqlite3GroupManagerDb (for Nodejs) or IndexedDbGroupManagerDb
+ * (for the browser).
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var GroupManagerDb = function GroupManagerDb()
+{
+};
+
+exports.GroupManagerDb = GroupManagerDb;
+
+/**
+ * Create a new GroupManagerDb.Error to report an error using GroupManagerDb
+ * methods, wrapping the given error object.
+ * Call with: throw new GroupManagerDb.Error(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+GroupManagerDb.Error = function GroupManagerDbError(error)
+{
+  if (error) {
+    error.__proto__ = GroupManagerDb.Error.prototype;
+    return error;
+  }
+}
+
+GroupManagerDb.Error.prototype = new Error();
+GroupManagerDb.Error.prototype.name = "GroupManagerDbError";
+
+////////////////////////////////////////////////////// Schedule management.
+
+/**
+ * Check if there is a schedule with the given name.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns true if there is a
+ * schedule (else false), or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+GroupManagerDb.prototype.hasSchedulePromise = function(name, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.hasSchedulePromise is not implemented"));
+};
+
+/**
+ * List all the names of the schedules.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new array of string
+ * with the names of all schedules, or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManagerDb.prototype.listAllScheduleNamesPromise = function(useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.listAllScheduleNamesPromise is not implemented"));
+};
+
+/**
+ * Get a schedule with the given name.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new Schedule object,
+ * or that is rejected with GroupManagerDb.Error if the schedule does not exist
+ * or other database error.
+ */
+GroupManagerDb.prototype.getSchedulePromise = function(name, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.getSchedulePromise is not implemented"));
+};
+
+/**
+ * For each member using the given schedule, get the name and public key DER
+ * of the member's key.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new array of object
+ * (where "keyName" is the Name of the public key and "publicKey" is the Blob of
+ * the public key DER), or that is rejected with GroupManagerDb.Error for a
+ * database error. Note that the member's identity name is keyName.getPrefix(-1).
+ * If the schedule name is not found, the list is empty.
+ */
+GroupManagerDb.prototype.getScheduleMembersPromise = function
+  (name, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.getScheduleMembersPromise is not implemented"));
+};
+
+/**
+ * Add a schedule with the given name.
+ * @param {string} name The name of the schedule. The name cannot be empty.
+ * @param {Schedule} schedule The Schedule to add.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * added, or that is rejected with GroupManagerDb.Error if a schedule with the
+ * same name already exists, if the name is empty, or other database error.
+ */
+GroupManagerDb.prototype.addSchedulePromise = function(name, schedule, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.addSchedulePromise is not implemented"));
+};
+
+/**
+ * Delete the schedule with the given name. Also delete members which use this
+ * schedule. If there is no schedule with the name, then do nothing.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * deleted (or there is no such schedule), or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManagerDb.prototype.deleteSchedulePromise = function(name, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.deleteSchedulePromise is not implemented"));
+};
+
+/**
+ * Rename a schedule with oldName to newName.
+ * @param {string} oldName The name of the schedule to be renamed.
+ * @param {string} newName The new name of the schedule. The name cannot be empty.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * renamed, or that is rejected with GroupManagerDb.Error if a schedule with
+ * newName already exists, if the schedule with oldName does not exist, if
+ * newName is empty, or other database error.
+ */
+GroupManagerDb.prototype.renameSchedulePromise = function
+  (oldName, newName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.renameSchedulePromise is not implemented"));
+};
+
+/**
+ * Update the schedule with name and replace the old object with the given
+ * schedule. Otherwise, if no schedule with name exists, a new schedule
+ * with name and the given schedule will be added to database.
+ * @param {string} name The name of the schedule. The name cannot be empty.
+ * @param {Schedule} schedule The Schedule to update or add.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * updated, or that is rejected with GroupManagerDb.Error if the name is empty,
+ * or other database error.
+ */
+GroupManagerDb.prototype.updateSchedulePromise = function
+  (name, schedule, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.updateSchedulePromise is not implemented"));
+};
+
+////////////////////////////////////////////////////// Member management.
+
+/**
+ * Check if there is a member with the given identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns true if there is a
+ * member (else false), or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+GroupManagerDb.prototype.hasMemberPromise = function(identity, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.hasMemberPromise is not implemented"));
+};
+
+/**
+ * List all the members.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new array of Name with
+ * the names of all members, or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+GroupManagerDb.prototype.listAllMembersPromise = function(useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.listAllMembersPromise is not implemented"));
+};
+
+/**
+ * Get the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the string schedule name,
+ * or that is rejected with GroupManagerDb.Error if there's no member with the
+ * given identity name in the database, or other database error.
+ */
+GroupManagerDb.prototype.getMemberSchedulePromise = function(identity, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.getMemberSchedulePromise is not implemented"));
+};
+
+/**
+ * Add a new member with the given key named keyName into a schedule named
+ * scheduleName. The member's identity name is keyName.getPrefix(-1).
+ * @param {string} scheduleName The schedule name.
+ * @param {Name} keyName The name of the key.
+ * @param {Blob} key A Blob of the public key DER.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * added, or that is rejected with GroupManagerDb.Error if there's no schedule
+ * named scheduleName, if the member's identity name already exists, or other
+ * database error.
+ */
+GroupManagerDb.prototype.addMemberPromise = function
+  (scheduleName, keyName, key, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.addMemberPromise is not implemented"));
+};
+
+/**
+ * Change the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {string} scheduleName The new schedule name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * updated, or that is rejected with GroupManagerDb.Error if there's no member
+ * with the given identity name in the database, or there's no schedule named
+ * scheduleName, or other database error.
+ */
+GroupManagerDb.prototype.updateMemberSchedulePromise = function
+  (identity, scheduleName, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.updateMemberSchedulePromise is not implemented"));
+};
+
+/**
+ * Delete a member with the given identity name. If there is no member with
+ * the identity name, then do nothing.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * deleted (or there is no such member), or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManagerDb.prototype.deleteMemberPromise = function(identity, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("GroupManagerDb.deleteMemberPromise is not implemented"));
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/group-manager https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
+var IdentityCertificate = require('../security/certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
+var SecurityException = require('../security/security-exception.js').SecurityException; /** @ignore */
+var RsaKeyParams = require('../security/key-params.js').RsaKeyParams; /** @ignore */
+var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
+var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
+var RsaAlgorithm = require('./algo/rsa-algorithm.js').RsaAlgorithm; /** @ignore */
+var Interval = require('./interval.js').Interval; /** @ignore */
+var Schedule = require('./schedule.js').Schedule;
+
+/**
+ * A GroupManager manages keys and schedules for group members in a particular
+ * namespace.
+ * Create a group manager with the given values. The group manager namespace
+ * is <prefix>/read/<dataType> .
+ * @param {Name} prefix The prefix for the group manager namespace.
+ * @param {Name} dataType The data type for the group manager namespace.
+ * @param {GroupManagerDb} database The GroupManagerDb for storing the group
+ * management information (including user public keys and schedules).
+ * @param {number} keySize The group key will be an RSA key with keySize bits.
+ * @param {number} freshnessHours The number of hours of the freshness period of
+ *   data packets carrying the keys.
+ * @param {KeyChain} keyChain The KeyChain to use for signing data packets. This
+ * signs with the default identity.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var GroupManager = function GroupManager
+  (prefix, dataType, database, keySize, freshnessHours, keyChain)
+{
+  this.namespace_ = new Name(prefix).append(Encryptor.NAME_COMPONENT_READ)
+    .append(dataType);
+  this.database_ = database;
+  this.keySize_ = keySize;
+  this.freshnessHours_ = freshnessHours;
+
+  this.keyChain_ = keyChain;
+};
+
+exports.GroupManager = GroupManager;
+
+/**
+ * Create a group key for the interval into which timeSlot falls. This creates
+ * a group key if it doesn't exist, and encrypts the key using the public key of
+ * each eligible member.
+ * @param {number} timeSlot The time slot to cover as milliseconds since
+ * Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a List of Data packets
+ * (where the first is the E-KEY data packet with the group's public key and the
+ * rest are the D-KEY data packets with the group's private key encrypted with
+ * the public key of each eligible member), or that is rejected with
+ * GroupManagerDb.Error for a database error or SecurityException for an error
+ * using the security KeyChain.
+ */
+GroupManager.prototype.getGroupKeyPromise = function(timeSlot, useSync)
+{
+  var memberKeys = [];
+  var result = [];
+  var thisManager = this;
+  var privateKeyBlob;
+  var publicKeyBlob;
+  var startTimeStamp;
+  var endTimeStamp;
+
+  // Get the time interval.
+  return this.calculateIntervalPromise_(timeSlot, memberKeys, useSync)
+  .then(function(finalInterval) {
+    if (finalInterval.isValid() == false)
+      return SyncPromise.resolve(result);
+
+    startTimeStamp = Schedule.toIsoString(finalInterval.getStartTime());
+    endTimeStamp = Schedule.toIsoString(finalInterval.getEndTime());
+
+    // Generate the private and public keys.
+    return thisManager.generateKeyPairPromise_(useSync)
+    .then(function(keyPair) {
+      privateKeyBlob = keyPair.privateKeyBlob;
+      publicKeyBlob = keyPair.publicKeyBlob;
+
+      // Add the first element to the result.
+      // The E-KEY (public key) data packet name convention is:
+      // /<data_type>/E-KEY/[start-ts]/[end-ts]
+      return thisManager.createEKeyDataPromise_
+        (startTimeStamp, endTimeStamp, publicKeyBlob, useSync);
+    })
+    .then(function(data) {
+      result.push(data);
+
+      // Encrypt the private key with the public key from each member's certificate.
+
+      // Process the memberKeys entry at i, and recursively call to process the
+      // next entry. Return a promise which is resolved when all are processed.
+      // (We have to make a recursive function to use Promises.)
+      function processMemberKey(i) {
+        if (i >= memberKeys.length)
+          // Finished.
+          return SyncPromise.resolve();
+
+        var keyName = memberKeys[i].keyName;
+        var certificateKey = memberKeys[i].publicKey;
+
+        return thisManager.createDKeyDataPromise_
+          (startTimeStamp, endTimeStamp, keyName, privateKeyBlob, certificateKey,
+           useSync)
+        .then(function(data) {
+          result.push(data);
+
+          return processMemberKey(i + 1);
+        });
+      }
+
+      return processMemberKey(0);
+    })
+    .then(function() {
+      return SyncPromise.resolve(result);
+    });
+  });
+};
+
+/**
+ * Add a schedule with the given scheduleName.
+ * @param {string} scheduleName The name of the schedule. The name cannot be
+ * empty.
+ * @param {Schedule} schedule The Schedule to add.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * added, or that is rejected with GroupManagerDb.Error if a schedule with the
+ * same name already exists, if the name is empty, or other database error.
+ */
+GroupManager.prototype.addSchedulePromise = function
+  (scheduleName, schedule, useSync)
+{
+  return this.database_.addSchedulePromise(scheduleName, schedule, useSync);
+};
+
+/**
+ * Delete the schedule with the given scheduleName. Also delete members which
+ * use this schedule. If there is no schedule with the name, then do nothing.
+ * @param {string} scheduleName The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * deleted (or there is no such schedule), or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManager.prototype.deleteSchedulePromise = function(scheduleName, useSync)
+{
+  return this.database_.deleteSchedulePromise(scheduleName, useSync);
+};
+
+/**
+ * Update the schedule with scheduleName and replace the old object with the
+ * given schedule. Otherwise, if no schedule with name exists, a new schedule
+ * with name and the given schedule will be added to database.
+ * @param {string} scheduleName The name of the schedule. The name cannot be
+ * empty.
+ * @param {Schedule} schedule The Schedule to update or add.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
+ * updated, or that is rejected with GroupManagerDb.Error if the name is empty,
+ * or other database error.
+ */
+GroupManager.prototype.updateSchedulePromise = function
+  (name, scheduleName, useSync)
+{
+  return this.database_.updateSchedulePromise(scheduleName, schedule, useSync);
+};
+
+/**
+ * Add a new member with the given memberCertificate into a schedule named
+ * scheduleName. If cert is an IdentityCertificate made from memberCertificate,
+ * then the member's identity name is cert.getPublicKeyName().getPrefix(-1).
+ * @param {string} scheduleName The schedule name.
+ * @param {Data} memberCertificate The member's certificate.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * added, or that is rejected with GroupManagerDb.Error if there's no schedule
+ * named scheduleName, if the member's identity name already exists, or other
+ * database error. Or a promise that is rejected with DerDecodingException for
+ * an error decoding memberCertificate as a certificate.
+ */
+GroupManager.prototype.addMemberPromise = function
+  (scheduleName, memberCertificate, useSync)
+{
+  var cert = new IdentityCertificate(memberCertificate);
+  return this.database_.addMemberPromise
+    (scheduleName, cert.getPublicKeyName(), cert.getPublicKeyInfo().getKeyDer(),
+     useSync);
+};
+
+/**
+ * Remove a member with the given identity name. If there is no member with
+ * the identity name, then do nothing.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * removed (or there is no such member), or that is rejected with
+ * GroupManagerDb.Error for a database error.
+ */
+GroupManager.prototype.removeMemberPromise = function(identity, useSync)
+{
+  return this.database_.deleteMemberPromise(identity, useSync);
+};
+
+/**
+ * Change the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {string} scheduleName The new schedule name.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the member is
+ * updated, or that is rejected with GroupManagerDb.Error if there's no member
+ * with the given identity name in the database, or there's no schedule named
+ * scheduleName.
+ */
+GroupManager.prototype.updateMemberSchedulePromise = function
+  (identity, scheduleName, useSync)
+{
+  return this.database_.updateMemberSchedulePromise
+    (identity, scheduleName, useSync);
+};
+
+/**
+ * Calculate an Interval that covers the timeSlot.
+ * @param {number} timeSlot The time slot to cover as milliseconds since
+ * Jan 1, 1970 UTC.
+ * @param {Array<object>} memberKeys First clear memberKeys then fill it with
+ * the info of members who are allowed to access the interval. memberKeys is an
+ * array of object where "keyName" is the Name of the public key and "publicKey"
+ * is the Blob of the public key DER. The memberKeys entries are sorted by
+ * the entry keyName.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a new nterval covering
+ * the time slot, or that is rejected with GroupManagerDb.Error for a database
+ * error.
+ */
+GroupManager.prototype.calculateIntervalPromise_ = function
+  (timeSlot, memberKeys, useSync)
+{
+  // Prepare.
+  var positiveResult = new Interval();
+  var negativeResult = new Interval();
+  // Clear memberKeys.
+  memberKeys.splice(0, memberKeys.length);
+  var thisManager = this;
+
+  // Get the all intervals from the schedules.
+  return this.database_.listAllScheduleNamesPromise(useSync)
+  .then(function(scheduleNames) {
+    // Process the scheduleNames entry at i, and recursively call to process the
+    // next entry. Return a promise which is resolved when all are processed.
+    // (We have to make a recursive function to use Promises.)
+    function processSchedule(i) {
+      if (i >= scheduleNames.length)
+        // Finished.
+        return SyncPromise.resolve();
+
+      var scheduleName = scheduleNames[i];
+
+      return thisManager.database_.getSchedulePromise(scheduleName, useSync)
+      .then(function(schedule) {
+        var result = schedule.getCoveringInterval(timeSlot);
+        var tempInterval = result.interval;
+
+        if (result.isPositive) {
+          if (!positiveResult.isValid())
+            positiveResult = tempInterval;
+          positiveResult.intersectWith(tempInterval);
+
+          return thisManager.database_.getScheduleMembersPromise
+            (scheduleName, useSync)
+          .then(function(map) {
+            // Add each entry in map to memberKeys.
+            for (var iMap = 0; iMap < map.length; ++iMap)
+              GroupManager.memberKeysAdd_(memberKeys, map[iMap]);
+
+            return processSchedule(i + 1);
+          });
+        }
+        else {
+          if (!negativeResult.isValid())
+            negativeResult = tempInterval;
+          negativeResult.intersectWith(tempInterval);
+
+          return processSchedule(i + 1);
+        }
+      });
+    }
+
+    return processSchedule(0);
+  })
+  .then(function() {
+    if (!positiveResult.isValid())
+      // Return an invalid interval when there is no member which has an
+      // interval covering the time slot.
+      return SyncPromise.resolve(new Interval(false));
+
+    // Get the final interval result.
+    var finalInterval;
+    if (negativeResult.isValid())
+      finalInterval = positiveResult.intersectWith(negativeResult);
+    else
+      finalInterval = positiveResult;
+
+    return SyncPromise.resolve(finalInterval);
+  });
+};
+
+/**
+ * Add entry to memberKeys, sorted by entry.keyName. If there is already an
+ * entry with keyName, then don't add.
+ */
+GroupManager.memberKeysAdd_ = function(memberKeys, entry)
+{
+  // Find the index of the first node where the keyName is not less than
+  // entry.keyName.
+  var i = 0;
+  while (i < memberKeys.length) {
+    var comparison = memberKeys[i].keyName.compare(entry.keyName);
+    if (comparison == 0)
+      // A duplicate, so don't add.
+      return;
+
+    if (comparison > 0)
+      break;
+    i += 1;
+  }
+
+  memberKeys.splice(i, 0, entry);
+};
+
+/**
+ * Generate an RSA key pair according to keySize_.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns an object where
+ * "privateKeyBlob" is the encoding Blob of the private key and "publicKeyBlob"
+ * is the encoding Blob of the public key.
+ */
+GroupManager.prototype.generateKeyPairPromise_ = function(useSync)
+{
+  var params = new RsaKeyParams(this.keySize_);
+
+  return RsaAlgorithm.generateKeyPromise(params)
+  .then(function(privateKey) {
+    var privateKeyBlob = privateKey.getKeyBits();
+    var publicKey = RsaAlgorithm.deriveEncryptKey(privateKeyBlob);
+    var publicKeyBlob = publicKey.getKeyBits();
+
+    return SyncPromise.resolve
+      ({ privateKeyBlob: privateKeyBlob, publicKeyBlob: publicKeyBlob });
+  });
+};
+
+/**
+ * Create an E-KEY Data packet for the given public key.
+ * @param {string} startTimeStamp The start time stamp string to put in the name.
+ * @param {string} endTimeStamp The end time stamp string to put in the name.
+ * @param {Blob} publicKeyBlob A Blob of the public key DER.
+ * @return The Data packet.
+ * @throws SecurityException for an error using the security KeyChain.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the Data packet, or that
+ * is rejected with SecurityException for an error using the security KeyChain.
+ */
+GroupManager.prototype.createEKeyDataPromise_ = function
+  (startTimeStamp, endTimeStamp, publicKeyBlob, useSync)
+{
+  var name = new Name(this.namespace_);
+  name.append(Encryptor.NAME_COMPONENT_E_KEY).append(startTimeStamp)
+    .append(endTimeStamp);
+
+  var data = new Data(name);
+  data.getMetaInfo().setFreshnessPeriod
+    (this.freshnessHours_ * GroupManager.MILLISECONDS_IN_HOUR);
+  data.setContent(publicKeyBlob);
+
+  return this.keyChain_.signPromise(data);
+};
+
+/**
+ * Create a D-KEY Data packet with an EncryptedContent for the given private
+ * key, encrypted with the certificate key.
+ * @param {string} startTimeStamp The start time stamp string to put in the name.
+ * @param {string} endTimeStamp The end time stamp string to put in the name.
+ * @param {Name} keyName The key name to put in the data packet name and the
+ * EncryptedContent key locator.
+ * @param {Blob} privateKeyBlob A Blob of the encoded private key.
+ * @param {Blob} certificateKey The certificate key encoding, used to encrypt
+ * the private key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns the Data packet, or that
+ * is rejected with SecurityException for an error using the security KeyChain.
+ */
+GroupManager.prototype.createDKeyDataPromise_ = function
+  (startTimeStamp, endTimeStamp, keyName, privateKeyBlob, certificateKey,
+   useSync)
+{
+  var name = new Name(this.namespace_);
+  name.append(Encryptor.NAME_COMPONENT_D_KEY);
+  name.append(startTimeStamp).append(endTimeStamp);
+  var data = new Data(name);
+  data.getMetaInfo().setFreshnessPeriod
+    (this.freshnessHours_ * GroupManager.MILLISECONDS_IN_HOUR);
+  var encryptParams = new EncryptParams(EncryptAlgorithmType.RsaOaep);
+  var thisManager = this;
+
+  return Encryptor.encryptDataPromise
+    (data, privateKeyBlob, keyName, certificateKey, encryptParams, useSync)
+  .catch(function(ex) {
+    // Consolidate errors such as InvalidKeyException.
+    return SyncPromise.reject(SecurityException(new Error
+      ("createDKeyData: Error in encryptData: " + ex)));
+  })
+  .then(function() {
+    return thisManager.keyChain_.signPromise(data);
+  });
+};
+
+GroupManager.MILLISECONDS_IN_HOUR = 3600 * 1000;
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/interval https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * An Interval defines a time duration which contains a start timestamp and an
+ * end timestamp. Create an Interval with one of these forms:
+ * Interval(isValid).
+ * Interval(startTime, endTime).
+ * Interval(interval).
+ * @param {boolean} isValid True to create a valid empty interval, false to
+ * create an invalid interval.
+ * @param {number} startTime The start time as milliseconds since Jan 1, 1970 UTC.
+ * The start time must be less than the end time. To create an empty interval
+ * (start time equals end time), use the constructor Interval(true).
+ * @param {number} endTime The end time as milliseconds since Jan 1, 1970 UTC.
+ * @param {Interval} interval The other interval with values to copy.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var Interval = function Interval(value, endTime)
+{
+  if (typeof value === 'object' && value instanceof Interval) {
+    // Make a copy.
+    this.startTime_ = value.startTime_;
+    this.endTime_ = value.endTime_;
+    this.isValid_ = value.isValid_;
+  }
+  else if (typeof value === 'number') {
+    var startTime = value;
+
+    if (!(startTime < endTime))
+      throw new Error("Interval start time must be less than the end time");
+
+    this.startTime_ = startTime;
+    this.endTime_ = endTime;
+    this.isValid_ = true;
+  }
+  else {
+    var isValid = (value ? true : false);
+
+    this.startTime_ = -Number.MAX_VALUE;
+    this.endTime_ = -Number.MAX_VALUE;
+    this.isValid_ = isValid;
+  }
+};
+
+exports.Interval = Interval;
+
+/**
+ * Set this interval to have the same values as the other interval.
+ * @param {Interval} other The other Interval with values to copy.
+ */
+Interval.prototype.set = function(other)
+{
+  this.startTime_ = other.startTime_;
+  this.endTime_ = other.endTime_;
+  this.isValid_ = other.isValid_;
+};
+
+/**
+ * Check if the time point is in this interval.
+ * @param {number} timePoint The time point to check as milliseconds since
+ * Jan 1, 1970 UTC.
+ * @return {boolean} True if timePoint is in this interval.
+ * @throws Error if this Interval is invalid.
+ */
+Interval.prototype.covers = function(timePoint)
+{
+  if (!this.isValid_)
+    throw new Error("Interval.covers: This Interval is invalid");
+
+  if (this.isEmpty())
+    return false;
+  else
+    return this.startTime_ <= timePoint && timePoint < this.endTime_;
+};
+
+/**
+ * Set this Interval to the intersection of this and the other interval.
+ * This and the other interval should be valid but either can be empty.
+ * @param {Interval} interval The other Interval to intersect with.
+ * @return {Interval} This Interval.
+ * @throws Error if this Interval or the other interval is invalid.
+ */
+Interval.prototype.intersectWith = function(interval)
+{
+  if (!this.isValid_)
+    throw new Error("Interval.intersectWith: This Interval is invalid");
+  if (!interval.isValid_)
+    throw new Error("Interval.intersectWith: The other Interval is invalid");
+
+  if (this.isEmpty() || interval.isEmpty()) {
+    // If either is empty, the result is empty.
+    this.startTime_ = this.endTime_;
+    return this;
+  }
+
+  if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_) {
+    // The two intervals don't have an intersection, so the result is empty.
+    this.startTime_ = this.endTime_;
+    return this;
+  }
+
+  // Get the start time.
+  if (this.startTime_ <= interval.startTime_)
+    this.startTime_ = interval.startTime_;
+
+  // Get the end time.
+  if (this.endTime_ > interval.endTime_)
+    this.endTime_ = interval.endTime_;
+
+  return this;
+};
+
+/**
+ * Set this Interval to the union of this and the other interval.
+ * This and the other interval should be valid but either can be empty.
+ * This and the other interval should have an intersection. (Contiguous
+ * intervals are not allowed.)
+ * @param {Interval} interval The other Interval to union with.
+ * @return {Interval} This Interval.
+ * @throws Error if this Interval or the other interval is invalid, or if the
+ * two intervals do not have an intersection.
+ */
+Interval.prototype.unionWith = function(interval)
+{
+  if (!this.isValid_)
+    throw new Error("Interval.intersectWith: This Interval is invalid");
+  if (!interval.isValid_)
+    throw new Error("Interval.intersectWith: The other Interval is invalid");
+
+  if (this.isEmpty()) {
+    // This interval is empty, so use the other.
+    this.startTime_ = interval.startTime_;
+    this.endTime_ = interval.endTime_;
+    return this;
+  }
+
+  if (interval.isEmpty())
+    // The other interval is empty, so keep using this one.
+    return this;
+
+  if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_)
+    throw new Error
+      ("Interval.unionWith: The two intervals do not have an intersection");
+
+  // Get the start time.
+  if (this.startTime_ > interval.startTime_)
+    this.startTime_ = interval.startTime_;
+
+  // Get the end time.
+  if (this.endTime_ < interval.endTime_)
+    this.endTime_ = interval.endTime_;
+
+  return this;
+};
+
+/**
+ * Get the start time.
+ * @return {number} The start time as milliseconds since Jan 1, 1970 UTC.
+ * @throws Error if this Interval is invalid.
+ */
+Interval.prototype.getStartTime = function()
+{
+  if (!this.isValid_)
+    throw new Error("Interval.getStartTime: This Interval is invalid");
+  return this.startTime_;
+};
+
+/**
+ * Get the end time.
+ * @return {number} The end time as milliseconds since Jan 1, 1970 UTC.
+ * @throws Error if this Interval is invalid.
+ */
+Interval.prototype.getEndTime = function()
+{
+  if (!this.isValid_)
+    throw new Error("Interval.getEndTime: This Interval is invalid");
+  return this.endTime_;
+};
+
+/**
+ * Check if this Interval is valid.
+ * @return {boolean} True if this interval is valid, false if invalid.
+ */
+Interval.prototype.isValid = function() { return this.isValid_; };
+
+/**
+ * Check if this Interval is empty.
+ * @return {boolean} True if this Interval is empty (start time equals end time),
+ * false if not.
+ * @throws Error if this Interval is invalid.
+ */
+Interval.prototype.isEmpty = function()
+{
+  if (!this.isValid_)
+    throw new Error("Interval.isEmpty: This Interval is invalid");
+  return this.startTime_ == this.endTime_;
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/producer-db https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise;
+
+/**
+ * ProducerDb is a base class for the storage of keys for the producer. It contains
+ * one table that maps time slots (to the nearest hour) to the content key
+ * created for that time slot. A subclass must implement the methods. For
+ * example, see Sqlite3ProducerDb (for Nodejs) or IndexedDbProducerDb (for the
+ * browser).
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var ProducerDb = function ProducerDb()
+{
+};
+
+exports.ProducerDb = ProducerDb;
+
+/**
+ * Create a new ProducerDb.Error to report an error using ProducerDb
+ * methods, wrapping the given error object.
+ * Call with: throw new ProducerDb.Error(new Error("message")).
+ * @constructor
+ * @param {Error} error The exception created with new Error.
+ */
+ProducerDb.Error = function ProducerDbError(error)
+{
+  if (error) {
+    error.__proto__ = ProducerDb.Error.prototype;
+    return error;
+  }
+}
+
+ProducerDb.Error.prototype = new Error();
+ProducerDb.Error.prototype.name = "ProducerDbError";
+
+/**
+ * Check if a content key exists for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns true if there is a
+ * content key for timeSlot (else false), or that is rejected with
+ * ProducerDb.Error for a database error.
+ */
+ProducerDb.prototype.hasContentKeyPromise = function(timeSlot, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ProducerDb.hasContentKeyPromise is not implemented"));
+};
+
+/**
+ * Get the content key for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
+ * key, or that is rejected with ProducerDb.Error if there is no key covering
+ * timeSlot, or other database error
+ */
+ProducerDb.prototype.getContentKeyPromise = function(timeSlot, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ProducerDb.getContentKeyPromise is not implemented"));
+};
+
+/**
+ * Add key as the content key for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {Blob} key The encoded key.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
+ * or that is rejected with ProducerDb.Error if a key for the same hour already
+ * exists in the database, or other database error.
+ */
+ProducerDb.prototype.addContentKeyPromise = function
+  (timeSlot, key, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ProducerDb.addContentKeyPromise is not implemented"));
+};
+
+/**
+ * Delete the content key for the hour covering timeSlot. If there is no key for
+ * the time slot, do nothing.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a SyncPromise which
+ * is already fulfilled. If omitted or false, this may return a SyncPromise or
+ * an async Promise.
+ * @return {Promise|SyncPromise} A promise that fulfills when the key is deleted
+ * (or there is no such key), or that is rejected with ProducerDb.Error for a
+ * database error.
+ */
+ProducerDb.prototype.deleteContentKeyPromise = function(timeSlot, useSync)
+{
+  return SyncPromise.reject(new Error
+    ("ProducerDb.deleteContentKeyPromise is not implemented"));
+};
+
+/**
+ * Get the hour-based time slot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @return {number} The hour-based time slot as hours since Jan 1, 1970 UTC.
+ */
+ProducerDb.getFixedTimeSlot = function(timeSlot)
+{
+  return Math.floor(Math.round(timeSlot) / 3600000.0);
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/producer https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var Link = require('../link.js').Link; /** @ignore */
+var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
+var Exclude = require('../exclude.js').Exclude; /** @ignore */
+var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
+var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
+var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
+var AesKeyParams = require('../security/key-params.js').AesKeyParams; /** @ignore */
+var AesAlgorithm = require('./algo/aes-algorithm.js').AesAlgorithm; /** @ignore */
+var Schedule = require('./schedule.js').Schedule; /** @ignore */
+var EncryptError = require('./encrypt-error.js').EncryptError; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
+var SyncPromise = require('../util/sync-promise.js').SyncPromise;
+
+/**
+ * A Producer manages content keys used to encrypt a data packet in the
+ * group-based encryption protocol.
+ * Create a Producer to use the given ProducerDb, Face and other values.
+ *
+ * A producer can produce data with a naming convention:
+ *   /<prefix>/SAMPLE/<dataType>/[timestamp]
+ *
+ * The produced data packet is encrypted with a content key,
+ * which is stored in the ProducerDb database.
+ *
+ * A producer also needs to produce data containing a content key
+ * encrypted with E-KEYs. A producer can retrieve E-KEYs through the face,
+ * and will re-try for at most repeatAttemps times when E-KEY retrieval fails.
+ *
+ * @param {Name} prefix The producer name prefix. This makes a copy of the Name.
+ * @param {Name} dataType The dataType portion of the producer name. This makes
+ * a copy of the Name.
+ * @param {Face} face The face used to retrieve keys.
+ * @param {KeyChain} keyChain The keyChain used to sign data packets.
+ * @param {ProducerDb} database The ProducerDb database for storing keys.
+ * @param {number} repeatAttempts (optional) The maximum retry for retrieving
+ * keys. If omitted, use a default value of 3.
+ * @param {Link} keyRetrievalLink (optional) The Link object to use in Interests
+ * for key retrieval. This makes a copy of the Link object. If the Link object's
+ * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
+ * object.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var Producer = function Producer
+  (prefix, dataType, face, keyChain, database, repeatAttempts, keyRetrievalLink)
+{
+  this.face_ = face;
+  this.keyChain_ = keyChain;
+  this.database_ = database;
+  this.maxRepeatAttempts_ = (repeatAttempts == undefined ? 3 : repeatAttempts);
+  this.keyRetrievalLink_ =
+    (keyRetrievalLink == undefined ? Producer.NO_LINK : new Link(keyRetrievalLink));
+
+  // The map key is the key name URI string. The value is an object with fields
+  // "keyName" and "keyInfo" where "keyName" is the same Name used for the key
+  // name URI string, and "keyInfo" is the Producer.KeyInfo_.
+  // (Use a string because we can't use the Name object as the key in JavaScript.)
+  // (Also put the original Name in the value because we need to iterate over
+  // eKeyInfo_ and we don't want to rebuild the Name from the name URI string.)
+  this.eKeyInfo_ = {};
+  // The map key is the time stamp. The value is a Producer.KeyRequest_.
+  this.keyRequests_ = {};
+
+  var fixedPrefix = new Name(prefix);
+  var fixedDataType = new Name(dataType);
+
+  // Fill ekeyInfo_ with all permutations of dataType, including the 'E-KEY'
+  // component of the name. This will be used in createContentKey to send
+  // interests without reconstructing names every time.
+  fixedPrefix.append(Encryptor.NAME_COMPONENT_READ);
+  while (fixedDataType.size() > 0) {
+    var nodeName = new Name(fixedPrefix);
+    nodeName.append(fixedDataType);
+    nodeName.append(Encryptor.NAME_COMPONENT_E_KEY);
+
+    this.eKeyInfo_[nodeName.toUri()] =
+      { keyName: nodeName, keyInfo: new Producer.KeyInfo_() };
+    fixedDataType = fixedDataType.getPrefix(-1);
+  }
+  fixedPrefix.append(dataType);
+  this.namespace_ = new Name(prefix);
+  this.namespace_.append(Encryptor.NAME_COMPONENT_SAMPLE);
+  this.namespace_.append(dataType);
+};
+
+exports.Producer = Producer;
+
+/**
+ * Create the content key corresponding to the timeSlot. This first checks if
+ * the content key exists. For an existing content key, this returns the
+ * content key name directly. If the key does not exist, this creates one and
+ * encrypts it using the corresponding E-KEYs. The encrypted content keys are
+ * passed to the onEncryptedKeys callback.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys If this creates a content key, then this
+ * calls onEncryptedKeys(keys) where keys is a list of encrypted content key
+ * Data packets. If onEncryptedKeys is null, this does not use it.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onContentKeyName This calls onContentKeyName(contentKeyName)
+ * with the content key name for the time slot. If onContentKeyName is null,
+ * this does not use it. (A callback is needed because of async database
+ * operations.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) This calls onError(errorCode, message)
+ * for an error, where errorCode is from EncryptError.ErrorCode and message is a
+ * string. If omitted, use a default callback which does nothing.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+Producer.prototype.createContentKey = function
+  (timeSlot, onEncryptedKeys, onContentKeyName, onError)
+{
+  if (!onError)
+    onError = Producer.defaultOnError;
+
+  var hourSlot = Producer.getRoundedTimeSlot_(timeSlot);
+
+  // Create the content key name.
+  var contentKeyName = new Name(this.namespace_);
+  contentKeyName.append(Encryptor.NAME_COMPONENT_C_KEY);
+  contentKeyName.append(Schedule.toIsoString(hourSlot));
+
+  var contentKeyBits;
+  var thisProducer = this;
+
+  // Check if we have created the content key before.
+  this.database_.hasContentKeyPromise(timeSlot)
+  .then(function(exists) {
+    if (exists) {
+      if (onContentKeyName != null)
+        onContentKeyName(contentKeyName);
+      return;
+    }
+
+    // We haven't created the content key. Create one and add it into the database.
+    var aesParams = new AesKeyParams(128);
+    contentKeyBits = AesAlgorithm.generateKey(aesParams).getKeyBits();
+    thisProducer.database_.addContentKeyPromise(timeSlot, contentKeyBits)
+    .then(function() {
+      // Now we need to retrieve the E-KEYs for content key encryption.
+      var timeCount = Math.round(timeSlot);
+      thisProducer.keyRequests_[timeCount] =
+        new Producer.KeyRequest_(thisProducer.getEKeyInfoSize_());
+      var keyRequest = thisProducer.keyRequests_[timeCount];
+
+      // Check if the current E-KEYs can cover the content key.
+      var timeRange = new Exclude();
+      Producer.excludeAfter
+        (timeRange, new Name.Component(Schedule.toIsoString(timeSlot)));
+      for (var keyNameUri in thisProducer.eKeyInfo_) {
+         // For each current E-KEY.
+        var entry = thisProducer.eKeyInfo_[keyNameUri];
+        var keyInfo = entry.keyInfo;
+        if (timeSlot < keyInfo.beginTimeSlot || timeSlot >= keyInfo.endTimeSlot) {
+          // The current E-KEY cannot cover the content key, so retrieve one.
+          keyRequest.repeatAttempts[keyNameUri] = 0;
+          thisProducer.sendKeyInterest_
+            (new Interest(entry.keyName).setExclude(timeRange).setChildSelector(1),
+             timeSlot, onEncryptedKeys, onError);
+        }
+        else {
+          // The current E-KEY can cover the content key.
+          // Encrypt the content key directly.
+          var eKeyName = new Name(entry.keyName);
+          eKeyName.append(Schedule.toIsoString(keyInfo.beginTimeSlot));
+          eKeyName.append(Schedule.toIsoString(keyInfo.endTimeSlot));
+          thisProducer.encryptContentKeyPromise_
+            (keyInfo.keyBits, eKeyName, timeSlot, onEncryptedKeys, onError);
+        }
+      }
+
+      if (onContentKeyName != null)
+        onContentKeyName(contentKeyName);
+    });
+  });
+};
+
+/**
+ * Encrypt the given content with the content key that covers timeSlot, and
+ * update the data packet with the encrypted content and an appropriate data
+ * name.
+ * @param {Data} data An empty Data object which is updated.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {Blob} content The content to encrypt.
+ * @param {function} onComplete This calls onComplete() when the data packet has
+ * been updated.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onError (optional) This calls onError(errorCode, message)
+ * for an error, where errorCode is from EncryptError.ErrorCode and message is a
+ * string. If omitted, use a default callback which does nothing.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ */
+Producer.prototype.produce = function
+  (data, timeSlot, content, onComplete, onError)
+{
+  if (!onError)
+    onError = Producer.defaultOnError;
+
+  var thisProducer = this;
+
+  // Get a content key.
+  this.createContentKey(timeSlot, null, function(contentKeyName) {
+    thisProducer.database_.getContentKeyPromise(timeSlot)
+    .then(function(contentKey) {
+      // Produce data.
+      var dataName = new Name(thisProducer.namespace_);
+      dataName.append(Schedule.toIsoString(timeSlot));
+
+      data.setName(dataName);
+      var params = new EncryptParams(EncryptAlgorithmType.AesCbc, 16);
+      return Encryptor.encryptData
+        (data, content, contentKeyName, contentKey, params);
+    })
+    .then(function() {
+      return thisProducer.keyChain_.signPromise(data);
+    })
+    .then(function() {
+      try {
+        onComplete();
+      } catch (ex) {
+        console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }, function(error) {
+      try {
+        onError(EncryptError.ErrorCode.General, "" + error);
+      } catch (ex) {
+        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    });
+  }, onError);
+};
+
+/**
+ * The default onError callback which does nothing.
+ */
+Producer.defaultOnError = function(errorCode, message)
+{
+  // Do nothing.
+};
+
+Producer.KeyInfo_ = function ProducerKeyInfo()
+{
+  this.beginTimeSlot = 0.0;
+  this.endTimeSlot = 0.0;
+  this.keyBits = null; // Blob
+};
+
+Producer.KeyRequest_ = function ProducerKeyRequest(interests)
+{
+  this.interestCount = interests; // number
+  // The map key is the name URI string. The value is an int count.
+  // (Use a string because we can't use the Name object as the key in JavaScript.)
+  this.repeatAttempts = {};
+  this.encryptedKeys = []; // of Data
+};
+
+/**
+ * Round timeSlot to the nearest whole hour, so that we can store content keys
+ * uniformly (by start of the hour).
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @return {number} The start of the hour as milliseconds since Jan 1, 1970 UTC.
+ */
+Producer.getRoundedTimeSlot_ = function(timeSlot)
+{
+  return Math.round(Math.floor(Math.round(timeSlot) / 3600000.0) * 3600000.0);
+}
+
+/**
+ * Send an interest with the given name through the face with callbacks to
+ * handleCoveringKey_, handleTimeout_ and handleNetworkNack_.
+ * @param {Interest} interest The interest to send.
+ * @param {number} timeSlot The time slot, passed to handleCoveringKey_,
+ * handleTimeout_ and handleNetworkNack_.
+ * @param {function} onEncryptedKeys The OnEncryptedKeys callback, passed to
+ * handleCoveringKey_, handleTimeout_ and handleNetworkNack_.
+ * @param {function} onError This calls onError(errorCode, message) for an error.
+ */
+Producer.prototype.sendKeyInterest_ = function
+  (interest, timeSlot, onEncryptedKeys, onError)
+{
+  var thisProducer = this;
+
+  function onKey(interest, data) {
+    thisProducer.handleCoveringKey_
+      (interest, data, timeSlot, onEncryptedKeys, onError);
+  }
+
+  function onTimeout(interest) {
+    thisProducer.handleTimeout_(interest, timeSlot, onEncryptedKeys, onError);
+  }
+
+  function onNetworkNack(interest, networkNack) {
+    thisProducer.handleNetworkNack_
+      (interest, networkNack, timeSlot, onEncryptedKeys, onError);
+  }
+
+  var request;
+  if (this.keyRetrievalLink_.getDelegations().size() === 0)
+    // We can use the supplied interest without copying.
+    request = interest;
+  else {
+    // Copy the supplied interest and add the Link.
+    request = new Interest(interest);
+    // This will use a cached encoding if available.
+    request.setLinkWireEncoding(this.keyRetrievalLink_.wireEncode());
+  }
+
+  this.face_.expressInterest(request, onKey, onTimeout, onNetworkNack);
+};
+
+/**
+ * This is called from an expressInterest timeout to update the state of
+ * keyRequest. Re-express the interest if the number of retrials is less than
+ * the max limit.
+ * @param {Interest} interest The timed-out interest.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys When there are no more interests to process,
+ * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
+ * key Data packets. If onEncryptedKeys is null, this does not use it.
+ * @param {function} onError This calls onError(errorCode, message) for an error.
+ */
+Producer.prototype.handleTimeout_ = function
+  (interest, timeSlot, onEncryptedKeys, onError)
+{
+  var timeCount = Math.round(timeSlot);
+  var keyRequest = this.keyRequests_[timeCount];
+
+  var interestName = interest.getName();
+  var interestNameUri = interestName.toUri();
+
+  if (keyRequest.repeatAttempts[interestNameUri] < this.maxRepeatAttempts_) {
+    // Increase the retrial count.
+    ++keyRequest.repeatAttempts[interestNameUri];
+    this.sendKeyInterest_(interest, timeSlot, onEncryptedKeys, onError);
+  }
+  else
+    // Treat an eventual timeout as a network Nack.
+    this.handleNetworkNack_
+      (interest, new NetworkNack(), timeSlot, onEncryptedKeys, onError);
+};
+
+/**
+ * This is called from an expressInterest OnNetworkNack to handle a network
+ * Nack for the E-KEY requested through the Interest. Decrease the outstanding
+ * E-KEY interest count for the C-KEY corresponding to the timeSlot.
+ * @param {Interest} interest The interest given to expressInterest.
+ * @param {NetworkNack} networkNack The returned NetworkNack (unused).
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys When there are no more interests to process,
+ * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
+ * key Data packets. If onEncryptedKeys is null, this does not use it.
+ */
+Producer.prototype.handleNetworkNack_ = function
+  (interest, networkNack, timeSlot, onEncryptedKeys, onError)
+{
+  // We have run out of options....
+  var timeCount = Math.round(timeSlot);
+  this.updateKeyRequest_
+    (this.keyRequests_[timeCount], timeCount, onEncryptedKeys);
+};
+
+/**
+ * Decrease the count of outstanding E-KEY interests for the C-KEY for
+ * timeCount. If the count decreases to 0, invoke onEncryptedKeys.
+ * @param {Producer.KeyRequest_} keyRequest The KeyRequest with the
+ * interestCount to update.
+ * @param {number} timeCount The time count for indexing keyRequests_.
+ * @param {function} onEncryptedKeys When there are no more interests to
+ * process, this calls onEncryptedKeys(keys) where keys is a list of encrypted
+ * content key Data packets. If onEncryptedKeys is null, this does not use it.
+ */
+Producer.prototype.updateKeyRequest_ = function
+  (keyRequest, timeCount, onEncryptedKeys)
+{
+  --keyRequest.interestCount;
+  if (keyRequest.interestCount == 0 && onEncryptedKeys != null) {
+    try {
+      onEncryptedKeys(keyRequest.encryptedKeys);
+    } catch (ex) {
+      console.log("Error in onEncryptedKeys: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    delete this.keyRequests_[timeCount];
+  }
+};
+
+/**
+ * This is called from an expressInterest OnData to check that the encryption
+ * key contained in data fits the timeSlot. This sends a refined interest if
+ * required.
+ * @param {Interest} interest The interest given to expressInterest.
+ * @param {Data} data The fetched Data packet.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys When there are no more interests to process,
+ * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
+ * key Data packets. If onEncryptedKeys is null, this does not use it.
+ * @param {function} onError This calls onError(errorCode, message) for an error.
+ */
+Producer.prototype.handleCoveringKey_ = function
+  (interest, data, timeSlot, onEncryptedKeys, onError)
+{
+  var timeCount = Math.round(timeSlot);
+  var keyRequest = this.keyRequests_[timeCount];
+
+  var interestName = interest.getName();
+  var interestNameUrl = interestName.toUri();
+  var keyName = data.getName();
+
+  var begin = Schedule.fromIsoString
+    (keyName.get(Producer.START_TIME_STAMP_INDEX).getValue().toString());
+  var end = Schedule.fromIsoString
+    (keyName.get(Producer.END_TIME_STAMP_INDEX).getValue().toString());
+
+  if (timeSlot >= end) {
+    // If the received E-KEY covers some earlier period, try to retrieve an
+    // E-KEY covering a later one.
+    var timeRange = new Exclude(interest.getExclude());
+    Producer.excludeBefore(timeRange, keyName.get(Producer.START_TIME_STAMP_INDEX));
+    keyRequest.repeatAttempts[interestNameUrl] = 0;
+    this.sendKeyInterest_
+      (new Interest(interestName).setExclude(timeRange).setChildSelector(1),
+       timeSlot, onEncryptedKeys, onError);
+  }
+  else {
+    // If the received E-KEY covers the content key, encrypt the content.
+    var encryptionKey = data.getContent();
+    var thisProducer = this;
+    this.encryptContentKeyPromise_
+      (encryptionKey, keyName, timeSlot, onEncryptedKeys, onError)
+    .then(function(success) {
+      if (success) {
+        var keyInfo = thisProducer.eKeyInfo_[interestNameUrl].keyInfo;
+        keyInfo.beginTimeSlot = begin;
+        keyInfo.endTimeSlot = end;
+        keyInfo.keyBits = encryptionKey;
+      }
+    });
+  }
+};
+
+/**
+ * Get the content key from the database_ and encrypt it for the timeSlot
+ * using encryptionKey.
+ * @param {Blob} encryptionKey The encryption key value.
+ * @param {Name} eKeyName The key name for the EncryptedContent.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {function} onEncryptedKeys When there are no more interests to process,
+ * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
+ * key Data packets. If onEncryptedKeys is null, this does not use it.
+ * @param {function} onError This calls onError(errorCode, message) for an error.
+ * @return {Promise} A promise that returns true if encryption succeeds,
+ * otherwise false.
+ */
+Producer.prototype.encryptContentKeyPromise_ = function
+  (encryptionKey, eKeyName, timeSlot, onEncryptedKeys, onError)
+{
+  var timeCount = Math.round(timeSlot);
+  var keyRequest = this.keyRequests_[timeCount];
+
+  var keyName = new Name(this.namespace_);
+  keyName.append(Encryptor.NAME_COMPONENT_C_KEY);
+  keyName.append(Schedule.toIsoString(Producer.getRoundedTimeSlot_(timeSlot)));
+
+  var cKeyData;
+  var thisProducer = this;
+
+  return this.database_.getContentKeyPromise(timeSlot)
+  .then(function(contentKey) {
+    cKeyData = new Data();
+    cKeyData.setName(keyName);
+    var params = new EncryptParams(EncryptAlgorithmType.RsaOaep);
+    return Encryptor.encryptDataPromise
+      (cKeyData, contentKey, eKeyName, encryptionKey, params);
+  })
+  .then(function() {
+    return SyncPromise.resolve(true);
+  }, function(error) {
+    try {
+      onError(EncryptError.ErrorCode.EncryptionFailure,
+              "encryptData failed: " + error);
+    } catch (ex) {
+      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+    return SyncPromise.resolve(false);
+  })
+  .then(function(success) {
+    if (success) {
+      return thisProducer.keyChain_.signPromise(cKeyData)
+      .then(function() {
+        keyRequest.encryptedKeys.push(cKeyData);
+        thisProducer.updateKeyRequest_(keyRequest, timeCount, onEncryptedKeys);
+        return SyncPromise.resolve(true);
+      });
+    }
+    else
+      return SyncPromise.resolve(false);
+  });
+};
+
+Producer.prototype.getEKeyInfoSize_ = function()
+{
+  // Note: This is really a method to find the key count in any object, but we
+  // don't want to claim that it is a tested and general utility method.
+  var size = 0;
+  for (key in this.eKeyInfo_) {
+    if (this.eKeyInfo_.hasOwnProperty(key))
+      ++size;
+  }
+
+  return size;
+};
+
+// TODO: Move this to be the main representation inside the Exclude object.
+/**
+ * Create a new ExcludeEntry.
+ * @param {Name.Component} component
+ * @param {boolean} anyFollowsComponent
+ */
+Producer.ExcludeEntry = function ExcludeEntry(component, anyFollowsComponent)
+{
+  this.component_ = component;
+  this.anyFollowsComponent_ = anyFollowsComponent;
+};
+
+/**
+ * Create a list of ExcludeEntry from the Exclude object.
+ * @param {Exclude} exclude The Exclude object to read.
+ * @return {Array<ExcludeEntry>} A new array of ExcludeEntry.
+ */
+Producer.getExcludeEntries = function(exclude)
+{
+  var entries = [];
+
+  for (var i = 0; i < exclude.size(); ++i) {
+    if (exclude.get(i) == Exclude.ANY) {
+      if (entries.length == 0)
+        // Add a "beginning ANY".
+        entries.push(new Producer.ExcludeEntry(new Name.Component(), true));
+      else
+        // Set anyFollowsComponent of the final component.
+        entries[entries.length - 1].anyFollowsComponent_ = true;
+    }
+    else
+      entries.push(new Producer.ExcludeEntry(exclude.get(i), false));
+  }
+
+  return entries;
+};
+
+/**
+ * Set the Exclude object from the array of ExcludeEntry.
+ * @param {Exclude} exclude The Exclude object to update.
+ * @param {Array<ExcludeEntry>} entries The array of ExcludeEntry.
+ */
+Producer.setExcludeEntries = function(exclude, entries)
+{
+  exclude.clear();
+
+  for (var i = 0; i < entries.length; ++i) {
+    var entry = entries[i];
+
+    if (i == 0 && entry.component_.getValue().size() == 0 &&
+        entry.anyFollowsComponent_)
+      // This is a "beginning ANY".
+      exclude.appendAny();
+    else {
+      exclude.appendComponent(entry.component_);
+      if (entry.anyFollowsComponent_)
+        exclude.appendAny();
+    }
+  }
+};
+
+/**
+ * Get the latest entry in the array whose component_ is less than or equal to
+ * component.
+ * @param {Array<ExcludeEntry>} entries The array of ExcludeEntry.
+ * @param {Name.Component} component The component to compare.
+ * @return {number} The index of the found entry, or -1 if not found.
+ */
+Producer.findEntryBeforeOrAt = function(entries, component)
+{
+  var i = entries.length - 1;
+  while (i >= 0) {
+    if (entries[i].component_.compare(component) <= 0)
+      break;
+    --i;
+  }
+
+  return i;
+};
+
+/**
+ * Exclude all components in the range beginning at "from".
+ * @param {Exclude} exclude The Exclude object to update.
+ * @param {Name.Component} from The first component in the exclude range.
+ */
+Producer.excludeAfter = function(exclude, from)
+{
+  var entries = Producer.getExcludeEntries(exclude);
+
+  var iNewFrom;
+  var iFoundFrom = Producer.findEntryBeforeOrAt(entries, from);
+  if (iFoundFrom < 0) {
+    // There is no entry before "from" so insert at the beginning.
+    entries.splice(0, 0, new Producer.ExcludeEntry(from, true));
+    iNewFrom = 0;
+  }
+  else {
+    var foundFrom = entries[iFoundFrom];
+
+    if (!foundFrom.anyFollowsComponent_) {
+      if (foundFrom.component_.equals(from)) {
+        // There is already an entry with "from", so just set the "ANY" flag.
+        foundFrom.anyFollowsComponent_ = true;
+        iNewFrom = iFoundFrom;
+      }
+      else {
+        // Insert following the entry before "from".
+        entries.splice(iFoundFrom + 1, 0, new Producer.ExcludeEntry(from, true));
+        iNewFrom = iFoundFrom + 1;
+      }
+    }
+    else
+      // The entry before "from" already has an "ANY" flag, so do nothing.
+      iNewFrom = iFoundFrom;
+  }
+
+  // Remove intermediate entries since they are inside the range.
+  var iRemoveBegin = iNewFrom + 1;
+  var nRemoveNeeded = entries.length - iRemoveBegin;
+  entries.splice(iRemoveBegin, nRemoveNeeded);
+
+  Producer.setExcludeEntries(exclude, entries);
+};
+
+/**
+ * Exclude all components in the range ending at "to".
+ * @param {Exclude} exclude The Exclude object to update.
+ * @param {Name.Component} to The last component in the exclude range.
+ */
+Producer.excludeBefore = function(exclude, to)
+{
+  Producer.excludeRange(exclude, new Name.Component(), to);
+};
+
+/**
+ * Exclude all components in the range beginning at "from" and ending at "to".
+ * @param {Exclude} exclude The Exclude object to update.
+ * @param {Name.Component} from The first component in the exclude range.
+ * @param {Name.Component} to The last component in the exclude range.
+ */
+Producer.excludeRange = function(exclude, from, to)
+{
+  if (from.compare(to) >= 0) {
+    if (from.compare(to) == 0)
+      throw new Error
+        ("excludeRange: from == to. To exclude a single component, sue excludeOne.");
+    else
+      throw new Error
+        ("excludeRange: from must be less than to. Invalid range: [" +
+         from.toEscapedString() + ", " + to.toEscapedString() + "]");
+  }
+
+  var entries = Producer.getExcludeEntries(exclude);
+
+  var iNewFrom;
+  var iFoundFrom = Producer.findEntryBeforeOrAt(entries, from);
+  if (iFoundFrom < 0) {
+    // There is no entry before "from" so insert at the beginning.
+    entries.splice(0, 0, new Producer.ExcludeEntry(from, true));
+    iNewFrom = 0;
+  }
+  else {
+    var foundFrom = entries[iFoundFrom];
+
+    if (!foundFrom.anyFollowsComponent_) {
+      if (foundFrom.component_.equals(from)) {
+        // There is already an entry with "from", so just set the "ANY" flag.
+        foundFrom.anyFollowsComponent_ = true;
+        iNewFrom = iFoundFrom;
+      }
+      else {
+        // Insert following the entry before "from".
+        entries.splice(iFoundFrom + 1, 0, new Producer.ExcludeEntry(from, true));
+        iNewFrom = iFoundFrom + 1;
+      }
+    }
+    else
+      // The entry before "from" already has an "ANY" flag, so do nothing.
+      iNewFrom = iFoundFrom;
+  }
+
+  // We have at least one "from" before "to", so we know this will find an entry.
+  var iFoundTo = Producer.findEntryBeforeOrAt(entries, to);
+  var foundTo = entries[iFoundTo];
+  if (iFoundTo == iNewFrom)
+    // Insert the "to" immediately after the "from".
+    entries.splice(iNewFrom + 1, 0, new Producer.ExcludeEntry(to, false));
+  else {
+    var iRemoveEnd;
+    if (!foundTo.anyFollowsComponent_) {
+      if (foundTo.component_.equals(to))
+        // The "to" entry already exists. Remove up to it.
+        iRemoveEnd = iFoundTo;
+      else {
+        // Insert following the previous entry, which will be removed.
+        entries.splice(iFoundTo + 1, 0, new Producer.ExcludeEntry(to, false));
+        iRemoveEnd = iFoundTo + 1;
+      }
+    }
+    else
+      // "to" follows a component which is already followed by "ANY", meaning
+      // the new range now encompasses it, so remove the component.
+      iRemoveEnd = iFoundTo + 1;
+
+    // Remove intermediate entries since they are inside the range.
+    var iRemoveBegin = iNewFrom + 1;
+    var nRemoveNeeded = iRemoveEnd - iRemoveBegin;
+    entries.splice(iRemoveBegin, nRemoveNeeded);
+  }
+
+  Producer.setExcludeEntries(exclude, entries);
+};
+
+Producer.START_TIME_STAMP_INDEX = -2;
+Producer.END_TIME_STAMP_INDEX = -1;
+Producer.NO_LINK = new Link();
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/repetitive-interval https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Interval = require('./interval.js').Interval;
+
+/**
+ * A RepetitiveInterval is an advanced interval which can repeat and can be used
+ * to find a simple Interval that a time point falls in. Create a
+ * RepetitiveInterval with one of these forms:
+ * RepetitiveInterval() A RepetitiveInterval with one day duration, non-repeating..
+ * RepetitiveInterval(startDate, endDate, intervalStartHour, intervalEndHour, nRepeats, repeatUnit).
+ * RepetitiveInterval(repetitiveInterval).
+ * @param {number} startDate The start date as milliseconds since Jan 1, 1970 UTC.
+ * startDate must be earlier than or same as endDate. Or if repeatUnit is
+ * RepetitiveInterval.RepeatUnit.NONE, then it must equal endDate.
+ * @param {number} endDate The end date as milliseconds since Jan 1, 1970 UTC.
+ * @param {number} intervalStartHour The start hour in the day, from 0 to 23.
+ * intervalStartHour must be less than intervalEndHour.
+ * @param {number} intervalEndHour The end hour in the day from 1 to 24.
+ * @param {number} nRepeats (optional) Repeat the interval nRepeats repetitions,
+ * every unit, until endDate. If ommitted, use 0.
+ * @param {number} repeatUnit (optional) The unit of the repetition, from
+ * RepetitiveInterval.RepeatUnit. If ommitted, use NONE. If this is NONE or
+ * ommitted, then startDate must equal endDate.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var RepetitiveInterval = function RepetitiveInterval
+  (startDate, endDate, intervalStartHour, intervalEndHour, nRepeats, repeatUnit)
+{
+  if (typeof startDate === 'object' && startDate instanceof RepetitiveInterval) {
+    // Make a copy.
+    repetitiveInterval = startDate;
+
+    this.startDate_ = repetitiveInterval.startDate_;
+    this.endDate_ = repetitiveInterval.endDate_;
+    this.intervalStartHour_ = repetitiveInterval.intervalStartHour_;
+    this.intervalEndHour_ = repetitiveInterval.intervalEndHour_;
+    this.nRepeats_ = repetitiveInterval.nRepeats_;
+    this.repeatUnit_ = repetitiveInterval.repeatUnit_;
+  }
+  else if (typeof startDate === 'number') {
+    if (nRepeats == undefined)
+      nRepeats = 0;
+    if (repeatUnit == undefined)
+      repeatUnit = RepetitiveInterval.RepeatUnit.NONE;
+
+    this.startDate_ = RepetitiveInterval.toDateOnlyMilliseconds_(startDate);
+    this.endDate_ = RepetitiveInterval.toDateOnlyMilliseconds_(endDate);
+    this.intervalStartHour_ = Math.round(intervalStartHour);
+    this.intervalEndHour_ = Math.round(intervalEndHour);
+    this.nRepeats_ = Math.round(nRepeats);
+    this.repeatUnit_ = repeatUnit;
+
+    // Validate.
+    if (!(this.intervalStartHour_ < this.intervalEndHour_))
+      throw new Error("ReptitiveInterval: startHour must be less than endHour");
+    if (!(this.startDate_ <= this.endDate_))
+      throw new Error
+        ("ReptitiveInterval: startDate must be earlier than or same as endDate");
+    if (!(this.intervalStartHour_ >= 0))
+      throw new Error("ReptitiveInterval: intervalStartHour must be non-negative");
+    if (!(this.intervalEndHour_ >= 1 && this.intervalEndHour_ <= 24))
+      throw new Error("ReptitiveInterval: intervalEndHour must be from 1 to 24");
+    if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.NONE) {
+      if (!(this.startDate_ == this.endDate_))
+        throw new Error
+          ("ReptitiveInterval: With RepeatUnit.NONE, startDate must equal endDate");
+    }
+  }
+  else {
+    // The default constructor.
+    this.startDate_ = -Number.MAX_VALUE;
+    this.endDate_ = -Number.MAX_VALUE;
+    this.intervalStartHour_ = 0;
+    this.intervalEndHour_ = 24;
+    this.nRepeats_ = 0;
+    this.repeatUnit_ = RepetitiveInterval.RepeatUnit.NONE;
+  }
+};
+
+exports.RepetitiveInterval = RepetitiveInterval;
+
+RepetitiveInterval.RepeatUnit = {
+  NONE:  0,
+  DAY:   1,
+  MONTH: 2,
+  YEAR:  3
+};
+
+/**
+ * Get an interval that covers the time point. If there is no interval
+ * covering the time point, this returns false for isPositive and returns a
+ * negative interval.
+ * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
+ * @return {object} An associative array with fields
+ * (isPositive, interval) where
+ * isPositive is true if the returned interval is
+ * positive or false if negative, and interval is the Interval covering the time
+ * point or a negative interval if not found.
+ */
+RepetitiveInterval.prototype.getInterval = function(timePoint)
+{
+  var isPositive;
+  var startTime;
+  var endTime;
+
+  if (!this.hasIntervalOnDate_(timePoint)) {
+    // There is no interval on the date of timePoint.
+    startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);
+    endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
+      24 * RepetitiveInterval.MILLISECONDS_IN_HOUR;
+    isPositive = false;
+  }
+  else {
+    // There is an interval on the date of timePoint.
+    startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
+      this.intervalStartHour_ * RepetitiveInterval.MILLISECONDS_IN_HOUR;
+    endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
+      this.intervalEndHour_ * RepetitiveInterval.MILLISECONDS_IN_HOUR;
+
+    // check if in the time duration
+    if (timePoint < startTime) {
+      endTime = startTime;
+      startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);
+      isPositive = false;
+    }
+    else if (timePoint > endTime) {
+      startTime = endTime;
+      endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
+        RepetitiveInterval.MILLISECONDS_IN_DAY;
+      isPositive = false;
+    }
+    else
+      isPositive = true;
+  }
+
+  return { isPositive: isPositive, interval: new Interval(startTime, endTime) };
+};
+
+/**
+ * Compare this to the other RepetitiveInterval.
+ * @param {RepetitiveInterval} other The other RepetitiveInterval to compare to.
+ * @return {number} -1 if this is less than the other, 1 if greater and 0 if equal.
+ */
+RepetitiveInterval.prototype.compare = function(other)
+{
+  if (this.startDate_ < other.startDate_)
+    return -1;
+  if (this.startDate_ > other.startDate_)
+    return 1;
+
+  if (this.endDate_ < other.endDate_)
+    return -1;
+  if (this.endDate_ > other.endDate_)
+    return 1;
+
+  if (this.intervalStartHour_ < other.intervalStartHour_)
+    return -1;
+  if (this.intervalStartHour_ > other.intervalStartHour_)
+    return 1;
+
+  if (this.intervalEndHour_ < other.intervalEndHour_)
+    return -1;
+  if (this.intervalEndHour_ > other.intervalEndHour_)
+    return 1;
+
+  if (this.nRepeats_ < other.nRepeats_)
+    return -1;
+  if (this.nRepeats_ > other.nRepeats_)
+    return 1;
+
+  if (this.repeatUnit_ < other.repeatUnit_)
+    return -1;
+  if (this.repeatUnit_ > other.repeatUnit_)
+    return 1;
+
+  return 0;
+};
+
+/**
+ * Get the start date.
+ * @return {number} The start date as milliseconds since Jan 1, 1970 UTC.
+ */
+RepetitiveInterval.prototype.getStartDate = function()
+{
+  return this.startDate_;
+};
+
+/**
+ * Get the end date.
+ * @return {number} The end date as milliseconds since Jan 1, 1970 UTC.
+ */
+RepetitiveInterval.prototype.getEndDate = function()
+{
+  return this.endDate_;
+};
+
+/**
+ * Get the interval start hour.
+ * @return {number} The interval start hour.
+ */
+RepetitiveInterval.prototype.getIntervalStartHour = function()
+{
+  return this.intervalStartHour_;
+}
+
+/**
+ * Get the interval end hour.
+ * @return {number} The interval end hour.
+ */
+RepetitiveInterval.prototype.getIntervalEndHour = function()
+{
+  return this.intervalEndHour_;
+};
+
+/**
+ * Get the number of repeats.
+ * @return {number} The number of repeats.
+ */
+RepetitiveInterval.prototype.getNRepeats = function()
+{
+  return this.nRepeats_;
+};
+
+/**
+ * Get the repeat unit.
+ * @return {number} The repeat unit, from RepetitiveInterval.RepeatUnit.
+ */
+RepetitiveInterval.prototype.getRepeatUnit = function()
+{
+  return this.repeatUnit_;
+};
+
+/**
+ * Check if the date of the time point is in any interval.
+ * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
+ * @return {boolean} True if the date of the time point is in any interval.
+ */
+RepetitiveInterval.prototype.hasIntervalOnDate_ = function(timePoint)
+{
+  var timePointDateMilliseconds = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);
+
+  if (timePointDateMilliseconds < this.startDate_ ||
+      timePointDateMilliseconds > this.endDate_)
+    return false;
+
+  if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.NONE)
+    return true;
+  else if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.DAY) {
+    var durationDays = (timePointDateMilliseconds - this.startDate_) /
+                        RepetitiveInterval.MILLISECONDS_IN_DAY;
+    if (durationDays % this.nRepeats_ == 0)
+      return true;
+  }
+  else {
+    var timePointDate = new Date(timePointDateMilliseconds);
+    var startDate = new Date(this.startDate_);
+
+    if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.MONTH &&
+             timePointDate.getUTCDate() == startDate.getUTCDate()) {
+      var yearDifference =
+        timePointDate.getUTCFullYear() - startDate.getUTCFullYear();
+      var monthDifference = 12 * yearDifference +
+        timePointDate.getUTCMonth() - startDate.getUTCMonth();
+      if (monthDifference % this.nRepeats_ == 0)
+        return true;
+    }
+    else if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.YEAR &&
+             timePointDate.getUTCDate() == startDate.getUTCDate() &&
+             timePointDate.getUTCMonth() == startDate.getUTCMonth()) {
+      var difference = timePointDate.getUTCFullYear() - startDate.getUTCFullYear();
+      if (difference % this.nRepeats_ == 0)
+        return true;
+    }
+  }
+
+  return false;
+};
+
+/**
+ * Return a time point on the beginning of the date (without hours, minutes, etc.)
+ * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
+ * @return {number} A time point as milliseconds since Jan 1, 1970 UTC.
+ */
+RepetitiveInterval.toDateOnlyMilliseconds_ = function(timePoint)
+{
+  var result = Math.round(timePoint);
+  result -= result % RepetitiveInterval.MILLISECONDS_IN_DAY;
+  return result;
+};
+
+RepetitiveInterval.MILLISECONDS_IN_HOUR = 3600 * 1000;
+RepetitiveInterval.MILLISECONDS_IN_DAY = 24 * 3600 * 1000;
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-group-encrypt src/schedule https://github.com/named-data/ndn-group-encrypt
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Interval = require('./interval.js').Interval; /** @ignore */
+var RepetitiveInterval = require('./repetitive-interval.js').RepetitiveInterval; /** @ignore */
+var Tlv = require('../encoding/tlv/tlv.js').Tlv; /** @ignore */
+var TlvEncoder = require('../encoding/tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
+var TlvDecoder = require('../encoding/tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * Schedule is used to manage the times when a member can access data using two
+ * sets of RepetitiveInterval as follows. whiteIntervalList is an ordered
+ * set for the times a member is allowed to access to data, and
+ * blackIntervalList is for the times a member is not allowed.
+ * Create a Schedule with one of these forms:
+ * Schedule() A Schedule with empty whiteIntervalList and blackIntervalList.
+ * Schedule(schedule). A copy of the given schedule.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var Schedule = function Schedule(value)
+{
+  if (typeof value === 'object' && value instanceof Schedule) {
+    // Make a copy.
+    var schedule = value;
+
+    // RepetitiveInterval is immutable, so we don't need to make a deep copy.
+    this.whiteIntervalList_ = schedule.whiteIntervalList_.slice(0);
+    this.blackIntervalList_ = schedule.blackIntervalList_.slice(0);
+  }
+  else {
+    // The default constructor.
+    this.whiteIntervalList_ = [];
+    this.blackIntervalList_ = [];
+  }
+};
+
+exports.Schedule = Schedule;
+
+/**
+ * Add the repetitiveInterval to the whiteIntervalList.
+ * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to add.
+ * If the list already contains the same RepetitiveInterval, this does nothing.
+ * @return {Schedule} This Schedule so you can chain calls to add.
+ */
+Schedule.prototype.addWhiteInterval = function(repetitiveInterval)
+{
+  // RepetitiveInterval is immutable, so we don't need to make a copy.
+  Schedule.sortedSetAdd_(this.whiteIntervalList_, repetitiveInterval);
+  return this;
+};
+
+/**
+ * Add the repetitiveInterval to the blackIntervalList.
+ * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to add.
+ * If the list already contains the same RepetitiveInterval, this does nothing.
+ * @return {Schedule} This Schedule so you can chain calls to add.
+ */
+Schedule.prototype.addBlackInterval = function(repetitiveInterval)
+{
+  // RepetitiveInterval is immutable, so we don't need to make a copy.
+  Schedule.sortedSetAdd_(this.blackIntervalList_, repetitiveInterval);
+  return this;
+};
+
+/**
+ * Get the interval that covers the time stamp. This iterates over the two
+ * repetitive interval sets and find the shortest interval that allows a group
+ * member to access the data. If there is no interval covering the time stamp,
+ * this returns false for isPositive and a negative interval.
+ * @param {number} timeStamp The time stamp as milliseconds since Jan 1, 1970 UTC.
+ * @return {object} An associative array with fields
+ * (isPositive, interval) where
+ * isPositive is true if the returned interval is positive or false if negative,
+ * and interval is the Interval covering the time stamp, or a negative interval
+ * if not found.
+ */
+Schedule.prototype.getCoveringInterval = function(timeStamp)
+{
+  var blackPositiveResult = new Interval(true);
+  var whitePositiveResult = new Interval(true);
+
+  var blackNegativeResult = new Interval();
+  var whiteNegativeResult = new Interval();
+
+  // Get the black result.
+  Schedule.calculateIntervalResult_
+    (this.blackIntervalList_, timeStamp, blackPositiveResult, blackNegativeResult);
+
+  // If the black positive result is not empty, then isPositive must be false.
+  if (!blackPositiveResult.isEmpty())
+    return { isPositive: false, interval: blackPositiveResult };
+
+  // Get the whiteResult.
+  Schedule.calculateIntervalResult_
+    (this.whiteIntervalList_, timeStamp, whitePositiveResult, whiteNegativeResult);
+
+  if (whitePositiveResult.isEmpty() && !whiteNegativeResult.isValid()) {
+    // There is no white interval covering the time stamp.
+    // Return false and a 24-hour interval.
+    var timeStampDateOnly =
+      RepetitiveInterval.toDateOnlyMilliseconds_(timeStamp);
+    return { isPositive: false,
+             interval:  new Interval
+               (timeStampDateOnly,
+                timeStampDateOnly + RepetitiveInterval.MILLISECONDS_IN_DAY) };
+  }
+
+  if (!whitePositiveResult.isEmpty()) {
+    // There is white interval covering the time stamp.
+    // Return true and calculate the intersection.
+    if (blackNegativeResult.isValid())
+      return { isPositive: true,
+               interval: whitePositiveResult.intersectWith(blackNegativeResult) };
+    else
+      return  { isPositive: true, interval: whitePositiveResult };
+  }
+  else
+    // There is no white interval covering the time stamp.
+    // Return false.
+    return { isPositive: false, interval: whiteNegativeResult };
+};
+
+/**
+ * Encode this Schedule.
+ * @return {Blob} The encoded buffer.
+ */
+Schedule.prototype.wireEncode = function()
+{
+  // For now, don't use WireFormat and hardcode to use TLV since the encoding
+  // doesn't go out over the wire, only into the local SQL database.
+  var encoder = new TlvEncoder(256);
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  // Encode the blackIntervalList.
+  var saveLengthForList = encoder.getLength();
+  for (var i = this.blackIntervalList_.length - 1; i >= 0; i--)
+    Schedule.encodeRepetitiveInterval_(this.blackIntervalList_[i], encoder);
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_BlackIntervalList, encoder.getLength() - saveLengthForList);
+
+  // Encode the whiteIntervalList.
+  saveLengthForList = encoder.getLength();
+  for (var i = this.whiteIntervalList_.length - 1; i >= 0; i--)
+    Schedule.encodeRepetitiveInterval_(this.whiteIntervalList_[i], encoder);
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_WhiteIntervalList, encoder.getLength() - saveLengthForList);
+
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_Schedule, encoder.getLength() - saveLength);
+
+  return new Blob(encoder.getOutput(), false);
+};
+
+/**
+ * Decode the input and update this Schedule object.
+ * @param {Blob|Buffer} input The input buffer to decode. For Buffer, this reads
+ * from position() to limit(), but does not change the position.
+ * @throws DecodingException For invalid encoding.
+ */
+Schedule.prototype.wireDecode = function(input)
+{
+  // If input is a blob, get its buf().
+  var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
+    input.buf() : input;
+
+  // For now, don't use WireFormat and hardcode to use TLV since the encoding
+  // doesn't go out over the wire, only into the local SQL database.
+  var decoder = new TlvDecoder(decodeBuffer);
+
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_Schedule);
+
+  // Decode the whiteIntervalList.
+  this.whiteIntervalList_ = [];
+  var listEndOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_WhiteIntervalList);
+  while (decoder.getOffset() < listEndOffset)
+    Schedule.sortedSetAdd_
+      (this.whiteIntervalList_, Schedule.decodeRepetitiveInterval_(decoder));
+  decoder.finishNestedTlvs(listEndOffset);
+
+  // Decode the blackIntervalList.
+  this.blackIntervalList_ = [];
+  listEndOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_BlackIntervalList);
+  while (decoder.getOffset() < listEndOffset)
+    Schedule.sortedSetAdd_
+      (this.blackIntervalList_, Schedule.decodeRepetitiveInterval_(decoder));
+  decoder.finishNestedTlvs(listEndOffset);
+
+  decoder.finishNestedTlvs(endOffset);
+};
+
+/**
+ * Insert element into the list, sorted using element.compare(). If it is a
+ * duplicate of an existing list element, don't add it.
+ */
+Schedule.sortedSetAdd_ = function(list, element)
+{
+  // Find the index of the first element where it is not less than element.
+  var i = 0;
+  while (i < list.length) {
+    var comparison = list[i].compare(element);
+    if (comparison == 0)
+      // Don't add a duplicate.
+      return;
+    if (!(comparison < 0))
+      break;
+
+    ++i;
+  }
+
+  list.splice(i, 0, element);
+};
+
+/**
+ * Encode the RepetitiveInterval as NDN-TLV to the encoder.
+ * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to encode.
+ * @param {TlvEncoder} encoder The TlvEncoder to receive the encoding.
+ */
+Schedule.encodeRepetitiveInterval_ = function(repetitiveInterval, encoder)
+{
+  var saveLength = encoder.getLength();
+
+  // Encode backwards.
+  // The RepeatUnit enum has the same values as the encoding.
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_RepeatUnit, repetitiveInterval.getRepeatUnit());
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_NRepeats, repetitiveInterval.getNRepeats());
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_IntervalEndHour, repetitiveInterval.getIntervalEndHour());
+  encoder.writeNonNegativeIntegerTlv
+    (Tlv.Encrypt_IntervalStartHour, repetitiveInterval.getIntervalStartHour());
+  // Use Blob to convert the string to UTF8 encoding.
+  encoder.writeBlobTlv(Tlv.Encrypt_EndDate,
+    new Blob(Schedule.toIsoString(repetitiveInterval.getEndDate())).buf());
+  encoder.writeBlobTlv(Tlv.Encrypt_StartDate,
+    new Blob(Schedule.toIsoString(repetitiveInterval.getStartDate())).buf());
+
+  encoder.writeTypeAndLength
+    (Tlv.Encrypt_RepetitiveInterval, encoder.getLength() - saveLength);
+};
+
+/**
+ * Decode the input as an NDN-TLV RepetitiveInterval.
+ * @param {TlvDecoder} decoder The decoder with the input to decode.
+ * @return {RepetitiveInterval} A new RepetitiveInterval with the decoded result.
+ */
+Schedule.decodeRepetitiveInterval_ = function(decoder)
+{
+  var endOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_RepetitiveInterval);
+
+  // Use Blob to convert UTF8 to a string.
+  var startDate = Schedule.fromIsoString
+    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_StartDate), true).toString());
+  var endDate = Schedule.fromIsoString
+    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_EndDate), true).toString());
+  var startHour = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalStartHour);
+  var endHour = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalEndHour);
+  var nRepeats = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_NRepeats);
+
+  // The RepeatUnit enum has the same values as the encoding.
+  var repeatUnit = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_RepeatUnit);
+
+  decoder.finishNestedTlvs(endOffset);
+  return new RepetitiveInterval
+    (startDate, endDate, startHour, endHour, nRepeats, repeatUnit);
+};
+
+/**
+ * A helper function to calculate black interval results or white interval
+ * results.
+ * @param {Array} list The set of RepetitiveInterval, which can be the white
+ * list or the black list.
+ * @param {number} timeStamp The time stamp as milliseconds since Jan 1, 1970 UTC.
+ * @param {Interval} positiveResult The positive result which is updated.
+ * @param {Interval} negativeResult The negative result which is updated.
+ */
+Schedule.calculateIntervalResult_ = function
+  (list, timeStamp, positiveResult, negativeResult)
+{
+  for (var i = 0; i < list.length; ++i) {
+    var element = list[i];
+
+    var result = element.getInterval(timeStamp);
+    var tempInterval = result.interval;
+    if (result.isPositive == true)
+      positiveResult.unionWith(tempInterval);
+    else {
+      if (!negativeResult.isValid())
+        negativeResult.set(tempInterval);
+      else
+        negativeResult.intersectWith(tempInterval);
+    }
+  }
+};
+
+/**
+ * Convert a UNIX timestamp to ISO time representation with the "T" in the middle.
+ * @param {number} msSince1970 Timestamp as milliseconds since Jan 1, 1970 UTC.
+ * @return {string} The string representation.
+ */
+Schedule.toIsoString = function(msSince1970)
+{
+  var utcTime = new Date(Math.round(msSince1970));
+  return utcTime.getUTCFullYear() +
+         Schedule.to2DigitString(utcTime.getUTCMonth() + 1) +
+         Schedule.to2DigitString(utcTime.getUTCDate()) +
+         "T" +
+         Schedule.to2DigitString(utcTime.getUTCHours()) +
+         Schedule.to2DigitString(utcTime.getUTCMinutes()) +
+         Schedule.to2DigitString(utcTime.getUTCSeconds());
+};
+
+/**
+ * A private method to zero pad an integer to 2 digits.
+ * @param {number} x The number to pad.  Assume it is a non-negative integer.
+ * @return {string} The padded string.
+ */
+Schedule.to2DigitString = function(x)
+{
+  var result = x.toString();
+  return result.length === 1 ? "0" + result : result;
+};
+
+/**
+ * Convert an ISO time representation with the "T" in the middle to a UNIX
+ * timestamp.
+ * @param {string} timeString The ISO time representation.
+ * @return {number} The timestamp as milliseconds since Jan 1, 1970 UTC.
+ */
+Schedule.fromIsoString = function(timeString)
+{
+  if (timeString.length != 15 || timeString.substr(8, 1) != 'T')
+    throw new Error("fromIsoString: Format is not the expected yyyymmddThhmmss");
+
+  return Date.UTC
+    (parseInt(timeString.substr(0, 4)),
+     parseInt(timeString.substr(4, 2) - 1),
+     parseInt(timeString.substr(6, 2)),
+     parseInt(timeString.substr(9, 2)),
+     parseInt(timeString.substr(11, 2)),
+     parseInt(timeString.substr(13, 2)));
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Don't require modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbConsumerDb extends ConsumerDb to implement the storage of decryption
+ * keys for the consumer using the browser's IndexedDB service.
+ * Create an IndexedDbConsumerDb to use the given IndexedDB database name.
+ * @param {string} databaseName IndexedDB database name.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var IndexedDbConsumerDb = function IndexedDbConsumerDb(databaseName)
+{
+  ConsumerDb.call(this);
+
+  this.database = new Dexie(databaseName);
+  this.database.version(1).stores({
+    // "keyName" is the key name URI // string
+    //   (Note: In SQLite3, the key name is the TLV encoded bytes, but we can't
+    //   index on a byte array in IndexedDb.)
+    // "key" is the key bytes // Uint8Array
+    decryptionKeys: "keyName"
+  });
+  this.database.open();
+};
+
+IndexedDbConsumerDb.prototype = new ConsumerDb();
+IndexedDbConsumerDb.prototype.name = "IndexedDbConsumerDb";
+
+/**
+ * Get the key with keyName from the database.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a Blob with the encoded key (or an
+ * isNull Blob if cannot find the key with keyName), or that is
+ * rejected with ConsumerDb.Error for a database error.
+ */
+IndexedDbConsumerDb.prototype.getKeyPromise = function(keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.getKeyPromise is only supported for async")));
+
+  return this.database.decryptionKeys.get(keyName.toUri())
+  .then(function(decryptionKeysEntry) {
+    if (decryptionKeysEntry)
+      return Promise.resolve(new Blob(decryptionKeysEntry.key));
+    else
+      return Promise.resolve(new Blob());
+  })
+  .catch(function(ex) {
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.getKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Add the key with keyName and keyBlob to the database.
+ * @param {Name} keyName The key name.
+ * @param {Blob} keyBlob The encoded key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key is added, or that
+ * is rejected with ConsumerDb.Error if a key with the same keyName already
+ * exists, or other database error.
+ */
+IndexedDbConsumerDb.prototype.addKeyPromise = function(keyName, keyBlob, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.addKeyPromise is only supported for async")));
+
+  // Add rejects if the primary key already exists.
+  return this.database.decryptionKeys.add
+    ({ keyName: keyName.toUri(), key: keyBlob.buf() })
+  .catch(function(ex) {
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.addKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Delete the key with keyName from the database. If there is no key with
+ * keyName, do nothing.
+ * @param {Name} keyName The key name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key is deleted (or there
+ * is no such key), or that is rejected with ConsumerDb.Error for a database
+ * error.
+ */
+IndexedDbConsumerDb.prototype.deleteKeyPromise = function(keyName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.deleteKeyPromise is only supported for async")));
+
+  return this.database.decryptionKeys.delete(keyName.toUri())
+  .catch(function(ex) {
+    return Promise.reject(new ConsumerDb.Error(new Error
+      ("IndexedDbConsumerDb.deleteKeyPromise: Error: " + ex)));
+  });
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Don't require modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbGroupManagerDb extends GroupManagerDb to implement the storage of
+ * data used by the GroupManager using the browser's IndexedDB service.
+ * Create an IndexedDbGroupManagerDb to use the given IndexedDB database name.
+ * @param {string} databaseName IndexedDB database name.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var IndexedDbGroupManagerDb = function IndexedDbGroupManagerDb(databaseName)
+{
+  GroupManagerDb.call(this);
+
+  this.database = new Dexie(databaseName);
+  this.database.version(1).stores({
+    // "scheduleId" is the schedule ID, auto incremented // number
+    // "scheduleName" is the schedule name, unique // string
+    // "schedule" is the TLV-encoded schedule // Uint8Array
+    schedules: "++scheduleId, &scheduleName",
+
+    // "memberNameUri" is the member name URI // string
+    //   (Note: In SQLite3, the member name index is the TLV encoded bytes, but
+    //   we can't index on a byte array in IndexedDb.)
+    //   (Note: The SQLite3 table also has an auto-incremented member ID primary
+    //   key, but is not used so we omit it to simplify.)
+    // "memberName" is the TLV-encoded member name (same as memberNameUri // Uint8Array
+    // "scheduleId" is the schedule ID, linked to the schedules table // number
+    //   (Note: The SQLite3 table has a foreign key to the schedules table with
+    //   cascade update and delete, but we have to handle it manually.)
+    // "keyName" is the TLV-encoded key name // Uint8Array
+    // "publicKey" is the encoded key bytes // Uint8Array
+    members: "memberNameUri, scheduleId"
+  });
+  this.database.open();
+};
+
+IndexedDbGroupManagerDb.prototype = new GroupManagerDb();
+IndexedDbGroupManagerDb.prototype.name = "IndexedDbGroupManagerDb";
+
+////////////////////////////////////////////////////// Schedule management.
+
+/**
+ * Check if there is a schedule with the given name.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns true if there is a schedule (else
+ * false), or that is rejected with GroupManagerDb.Error for a database error.
+ */
+IndexedDbGroupManagerDb.prototype.hasSchedulePromise = function(name, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.hasSchedulePromise is only supported for async")));
+
+  return this.getScheduleIdPromise_(name)
+  .then(function(scheduleId) {
+    return Promise.resolve(scheduleId != -1);
+  });
+};
+
+/**
+ * List all the names of the schedules.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a new array of string with the names
+ * of all schedules, or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.listAllScheduleNamesPromise = function(useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.listAllScheduleNamesPromise is only supported for async")));
+
+  var list = [];
+  return this.database.schedules.each(function(entry) {
+    list.push(entry.scheduleName);
+  })
+  .then(function() {
+    return Promise.resolve(list);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.listAllScheduleNamesPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Get a schedule with the given name.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a new Schedule object, or that is
+ * rejected with GroupManagerDb.Error if the schedule does not exist or other
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.getSchedulePromise = function(name, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getSchedulePromise is only supported for async")));
+
+  var thisManager = this;
+  // Use getScheduleIdPromise_ to handle the search on the non-primary key.
+  return this.getScheduleIdPromise_(name)
+  .then(function(scheduleId) {
+    if (scheduleId != -1) {
+      return thisManager.database.schedules.get(scheduleId)
+      .then(function(entry) {
+        // We expect entry to be found, and don't expect an error decoding.
+        var schedule = new Schedule();
+        schedule.wireDecode(new Blob(entry.schedule, false));
+        return Promise.resolve(schedule);
+      })
+      .catch(function(ex) {
+        return Promise.reject(new GroupManagerDb.Error(new Error
+          ("IndexedDbGroupManagerDb.getSchedulePromise: Error: " + ex)));
+      });
+    }
+    else
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.getSchedulePromise: Cannot get the result from the database")));
+  });
+};
+
+/**
+ * For each member using the given schedule, get the name and public key DER
+ * of the member's key.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a new array of object (where
+ * "keyName" is the Name of the public key and "publicKey" is the Blob of the
+ * public key DER), or that is rejected with GroupManagerDb.Error for a database
+ * error. Note that the member's identity name is keyName.getPrefix(-1). If the
+ * schedule name is not found, the list is empty.
+ */
+IndexedDbGroupManagerDb.prototype.getScheduleMembersPromise = function
+  (name, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getScheduleMembersPromise is only supported for async")));
+
+  var list = [];
+  var thisManager = this;
+  // There is only one matching schedule ID, so we can just look it up instead
+  // of doing a more complicated join.
+  return this.getScheduleIdPromise_(name)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      // Return the empty list.
+      return Promise.resolve(list);
+
+    var onEntryError = null;
+    return thisManager.database.members.where("scheduleId").equals(scheduleId)
+    .each(function(entry) {
+      try {
+        var keyName = new Name();
+        keyName.wireDecode(new Blob(entry.keyName, false), TlvWireFormat.get());
+
+        list.push({ keyName: keyName, publicKey: new Blob(entry.publicKey, false) });
+      } catch (ex) {
+        // We don't expect this to happen.
+        onEntryError = new GroupManagerDb.Error(new Error
+          ("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error decoding name: " + ex));
+      }
+    })
+    .then(function() {
+      if (onEntryError)
+        // We got an error decoding.
+        return Promise.reject(onEntryError);
+      else
+        return Promise.resolve(list);
+    }, function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error: " + ex)));
+    });
+  });
+};
+
+/**
+ * Add a schedule with the given name.
+ * @param {string} name The name of the schedule. The name cannot be empty.
+ * @param {Schedule} schedule The Schedule to add.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the schedule is added, or that
+ * is rejected with GroupManagerDb.Error if a schedule with the same name
+ * already exists, if the name is empty, or other database error.
+ */
+IndexedDbGroupManagerDb.prototype.addSchedulePromise = function
+  (name, schedule, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.addSchedulePromise is only supported for async")));
+
+  if (name.length == 0)
+    return Promise.reject(new GroupManagerDb.Error
+      ("IndexedDbGroupManagerDb.addSchedulePromise: The schedule name cannot be empty"));
+
+  // Add rejects if the primary key already exists.
+  return this.database.schedules.add
+    ({ scheduleName: name, schedule: schedule.wireEncode().buf() })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.addContentKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Delete the schedule with the given name. Also delete members which use this
+ * schedule. If there is no schedule with the name, then do nothing.
+ * @param {string} name The name of the schedule.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the schedule is deleted (or
+ * there is no such schedule), or that is rejected with GroupManagerDb.Error for
+ * a database error.
+ */
+IndexedDbGroupManagerDb.prototype.deleteSchedulePromise = function
+  (name, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.deleteSchedulePromise is only supported for async")));
+
+  var scheduleId;
+  var thisManager = this;
+  return this.getScheduleIdPromise_(name)
+  .then(function(localScheduleId) {
+    scheduleId = localScheduleId;
+
+    // Get the members which use this schedule.
+    return thisManager.database.members.where("scheduleId").equals(scheduleId).toArray();
+  })
+  .then(function(membersEntries) {
+    // Delete the members.
+    var promises = membersEntries.map(function(entry) {
+      return thisManager.database.members.delete(entry.memberNameUri);
+    });
+    return Promise.all(promises);
+  })
+  .then(function() {
+    // Now delete the schedule.
+    return thisManager.database.schedules.delete(scheduleId);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.deleteSchedulePromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Rename a schedule with oldName to newName.
+ * @param {string} oldName The name of the schedule to be renamed.
+ * @param {string} newName The new name of the schedule. The name cannot be empty.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the schedule is renamed, or
+ * that is rejected with GroupManagerDb.Error if a schedule with newName already
+ * exists, if the schedule with oldName does not exist, if newName is empty, or
+ * other database error.
+ */
+IndexedDbGroupManagerDb.prototype.renameSchedulePromise = function
+  (oldName, newName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.renameSchedulePromise is only supported for async")));
+
+  if (newName.length == 0)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.renameSchedule: The schedule newName cannot be empty")));
+
+  var thisManager = this;
+  return this.getScheduleIdPromise_(oldName)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.renameSchedule: The schedule oldName does not exist")));
+
+    return thisManager.database.schedules.update
+      (scheduleId, { scheduleName: newName })
+    .catch(function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.renameSchedulePromise: Error: " + ex)));
+    });
+  });
+};
+
+/**
+ * Update the schedule with name and replace the old object with the given
+ * schedule. Otherwise, if no schedule with name exists, a new schedule
+ * with name and the given schedule will be added to database.
+ * @param {string} name The name of the schedule. The name cannot be empty.
+ * @param {Schedule} schedule The Schedule to update or add.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the schedule is updated, or
+ * that is rejected with GroupManagerDb.Error if the name is empty, or other
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.updateSchedulePromise = function
+  (name, schedule, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.updateSchedulePromise is only supported for async")));
+
+  var thisManager = this;
+  return this.getScheduleIdPromise_(name)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      return thisManager.addSchedulePromise(name, schedule);
+
+    return thisManager.database.schedules.update
+      (scheduleId, { schedule: schedule.wireEncode().buf() })
+    .catch(function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.updateSchedulePromise: Error: " + ex)));
+    });
+  });
+};
+
+////////////////////////////////////////////////////// Member management.
+
+/**
+ * Check if there is a member with the given identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns true if there is a member (else
+ * false), or that is rejected with GroupManagerDb.Error for a database error.
+ */
+IndexedDbGroupManagerDb.prototype.hasMemberPromise = function(identity, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.hasMemberPromise is only supported for async")));
+
+  return this.database.members.get(identity.toUri())
+  .then(function(entry) {
+    return Promise.resolve(entry != undefined);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.hasMemberPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * List all the members.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a new array of Name with the names
+ * of all members, or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.listAllMembersPromise = function(useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.listAllMembersPromise is only supported for async")));
+
+  var list = [];
+  var onEntryError = null;
+  return this.database.members.each(function(entry) {
+    try {
+      var identity = new Name();
+      identity.wireDecode(new Blob(entry.memberName, false), TlvWireFormat.get());
+      list.push(identity);
+    } catch (ex) {
+      // We don't expect this to happen.
+      onEntryError = new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.listAllMembersPromise: Error decoding name: " + ex));
+    }
+  })
+  .then(function() {
+    if (onEntryError)
+      // We got an error decoding.
+      return Promise.reject(onEntryError);
+    else
+      return Promise.resolve(list);
+  }, function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.listAllMembersPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Get the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns the string schedule name, or that is
+ * rejected with GroupManagerDb.Error if there's no member with the given
+ * identity name in the database, or other database error.
+ */
+IndexedDbGroupManagerDb.prototype.getMemberSchedulePromise = function
+  (identity, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getMemberSchedulePromise is only supported for async")));
+
+  var thisManager = this;
+  return this.database.members.get(identity.toUri())
+  .then(function(membersEntry) {
+    if (!membersEntry)
+      throw new Error("The member identity name does not exist in the database");
+
+    return thisManager.database.schedules.get(membersEntry.scheduleId);
+  })
+  .then(function(schedulesEntry) {
+    if (!schedulesEntry)
+      throw new Error
+        ("The schedule ID for the member identity name does not exist in the database");
+
+    return Promise.resolve(schedulesEntry.scheduleName);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: " + ex)));
+  });
+};
+
+/**
+ * Add a new member with the given key named keyName into a schedule named
+ * scheduleName. The member's identity name is keyName.getPrefix(-1).
+ * @param {string} scheduleName The schedule name.
+ * @param {Name} keyName The name of the key.
+ * @param {Blob} key A Blob of the public key DER.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the member is added, or that
+ * is rejected with GroupManagerDb.Error if there's no schedule named
+ * scheduleName, if the member's identity name already exists, or other database
+ * error.
+ */
+IndexedDbGroupManagerDb.prototype.addMemberPromise = function
+  (scheduleName, keyName, key, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.addMemberPromise is only supported for async")));
+
+  var thisManager = this;
+  return this.getScheduleIdPromise_(scheduleName)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.addMemberPromise: The schedule does not exist")));
+
+    // Needs to be changed in the future.
+    var memberName = keyName.getPrefix(-1);
+
+    // Add rejects if the primary key already exists.
+    return thisManager.database.members.add
+      ({ memberNameUri: memberName.toUri(),
+         memberName: memberName.wireEncode(TlvWireFormat.get()).buf(),
+         scheduleId: scheduleId,
+         keyName: keyName.wireEncode(TlvWireFormat.get()).buf(),
+         publicKey: key.buf() })
+    .catch(function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.addMemberPromise: Error: " + ex)));
+    });
+  });
+};
+
+/**
+ * Change the name of the schedule for the given member's identity name.
+ * @param {Name} identity The member's identity name.
+ * @param {string} scheduleName The new schedule name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the member is updated, or that
+ * is rejected with GroupManagerDb.Error if there's no member with the given
+ * identity name in the database, or there's no schedule named scheduleName, or
+ * other database error.
+ */
+IndexedDbGroupManagerDb.prototype.updateMemberSchedulePromise = function
+  (identity, scheduleName, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.updateMemberSchedulePromise is only supported for async")));
+
+  var thisManager = this;
+  return this.getScheduleIdPromise_(scheduleName)
+  .then(function(scheduleId) {
+    if (scheduleId == -1)
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.updateMemberSchedulePromise: The schedule does not exist")));
+
+    return thisManager.database.members.update
+      (identity.toUri(), { scheduleId: scheduleId })
+    .catch(function(ex) {
+      return Promise.reject(new GroupManagerDb.Error(new Error
+        ("IndexedDbGroupManagerDb.updateMemberSchedulePromise: Error: " + ex)));
+    });
+  });
+};
+
+/**
+ * Delete a member with the given identity name. If there is no member with
+ * the identity name, then do nothing.
+ * @param {Name} identity The member's identity name.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the member is deleted (or
+ * there is no such member), or that is rejected with GroupManagerDb.Error for a
+ * database error.
+ */
+IndexedDbGroupManagerDb.prototype.deleteMemberPromise = function
+  (identity, useSync)
+{
+  if (useSync)
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.deleteMemberPromise is only supported for async")));
+
+  return this.database.members.delete(identity.toUri())
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.deleteMemberPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Get the ID for the schedule.
+ * @param {string} name The schedule name.
+ * @return {Promise} A promise that returns the ID (or -1 if not found), or that
+ * is rejected with GroupManagerDb.Error for a database error.
+ */
+IndexedDbGroupManagerDb.prototype.getScheduleIdPromise_ = function(name)
+{
+  // The scheduleName is not the primary key, so use 'where' instead of 'get'.
+  var id = -1;
+  return this.database.schedules.where("scheduleName").equals(name)
+  .each(function(entry) {
+    id = entry.scheduleId;
+  })
+  .then(function() {
+    return Promise.resolve(id);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new GroupManagerDb.Error(new Error
+      ("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: " + ex)));
+  });
+};
+/**
+ * Copyright (C) 2015-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Don't require modules since this is meant for the browser, not Node.js.
+
+/**
+ * IndexedDbProducerDb extends ProducerDb to implement storage of keys for the
+ * producer using the browser's IndexedDB service. It contains one table that
+ * maps time slots (to the nearest hour) to the content key created for that
+ * time slot.
+ * Create an IndexedDbProducerDb to use the given IndexedDB database name.
+ * @param {string} databaseName IndexedDB database name.
+ * @note This class is an experimental feature. The API may change.
+ * @constructor
+ */
+var IndexedDbProducerDb = function IndexedDbProducerDb(databaseName)
+{
+  ProducerDb.call(this);
+
+  this.database = new Dexie(databaseName);
+  this.database.version(1).stores({
+    // "timeSlot" is the hour-based time slot as hours since Jan 1, 1970 UTC. // number
+    // "key" is the encoded key // Uint8Array
+    contentKeys: "timeSlot"
+  });
+  this.database.open();
+};
+
+IndexedDbProducerDb.prototype = new ProducerDb();
+IndexedDbProducerDb.prototype.name = "IndexedDbProducerDb";
+
+/**
+ * Check if a content key exists for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns true if there is a content key for
+ * timeSlot (else false), or that is rejected with ProducerDb.Error for a
+ * database error.
+ */
+IndexedDbProducerDb.prototype.hasContentKeyPromise = function(timeSlot, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.hasContentKeyPromise is only supported for async")));
+
+  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
+
+  return this.database.contentKeys.get(fixedTimeSlot)
+  .then(function(contentKeysEntry) {
+    return Promise.resolve(contentKeysEntry != undefined);
+  })
+  .catch(function(ex) {
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.hasContentKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Get the content key for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that returns a Blob with the encoded key, or that
+ * is rejected with ProducerDb.Error if there is no key covering timeSlot, or
+ * other database error
+ */
+IndexedDbProducerDb.prototype.getContentKeyPromise = function(timeSlot, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.getContentKeyPromise is only supported for async")));
+
+  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
+
+  return this.database.contentKeys.get(fixedTimeSlot)
+  .then(function(contentKeysEntry) {
+    if (contentKeysEntry)
+      return Promise.resolve(new Blob(contentKeysEntry.key));
+    else
+      return Promise.reject(new ProducerDb.Error(new Error
+        ("IndexedDbProducerDb.getContentKeyPromise: Cannot get the key from the database")));
+  }, function(ex) {
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.getContentKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Add key as the content key for the hour covering timeSlot.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {Blob} key The encoded key.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key is added, or that
+ * is rejected with ProducerDb.Error if a key for the same hour already exists
+ * in the database, or other database error.
+ */
+IndexedDbProducerDb.prototype.addContentKeyPromise = function
+  (timeSlot, key, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.addContentKeyPromise is only supported for async")));
+
+  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
+
+  // Add rejects if the primary key already exists.
+  return this.database.contentKeys.add
+    ({ timeSlot: fixedTimeSlot, key: key.buf() })
+  .catch(function(ex) {
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.addContentKeyPromise: Error: " + ex)));
+  });
+};
+
+/**
+ * Delete the content key for the hour covering timeSlot. If there is no key for
+ * the time slot, do nothing.
+ * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
+ * @param {boolean} useSync (optional) If true then return a rejected promise
+ * since this only supports async code.
+ * @return {Promise} A promise that fulfills when the key is deleted (or there
+ * is no such key), or that is rejected with ProducerDb.Error for a database
+ * error.
+ */
+IndexedDbProducerDb.prototype.deleteContentKeyPromise = function(timeSlot, useSync)
+{
+  if (useSync)
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.deleteContentKeyPromise is only supported for async")));
+
+  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
+
+  return this.database.contentKeys.delete(fixedTimeSlot)
+  .catch(function(ex) {
+    return Promise.reject(new ProducerDb.Error(new Error
+      ("IndexedDbProducerDb.deleteContentKeyPromise: Error: " + ex)));
+  });
+};
+/**
+ * This class represents the digest tree for chrono-sync2013.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Zhehao Wang, based on Jeff T.'s implementation in ndn-cpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DigestTree = require('./digest-tree.js').DigestTree; /** @ignore */
+var Interest = require('../interest.js').Interest; /** @ignore */
+var Data = require('../data.js').Data; /** @ignore */
+var Name = require('../name.js').Name; /** @ignore */
+var Blob = require('../util/blob.js').Blob; /** @ignore */
+var MemoryContentCache = require('../util/memory-content-cache.js').MemoryContentCache; /** @ignore */
+var SyncStateProto = require('./sync-state.js').SyncStateProto; /** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon;
+
+/**
+ * ChronoSync2013 implements the NDN ChronoSync protocol as described in the
+ * 2013 paper "Let's ChronoSync: Decentralized Dataset State Synchronization in
+ * Named Data Networking". http://named-data.net/publications/chronosync .
+ * @note The support for ChronoSync is experimental and the API is not finalized.
+ * See the API docs for more detail at
+ * http://named-data.net/doc/ndn-ccl-api/chrono-sync2013.html .
+ *
+ * Create a new ChronoSync2013 to communicate using the given face. Initialize
+ * the digest log with a digest of "00" and and empty content. Register the
+ * applicationBroadcastPrefix to receive interests for sync state messages and
+ * express an interest for the initial root digest "00".
+ * @param {function} onReceivedSyncState When ChronoSync receives a sync state message,
+ * this calls onReceivedSyncState(syncStates, isRecovery) where syncStates is the
+ * list of SyncState messages and isRecovery is true if this is the initial
+ * list of SyncState messages or from a recovery interest. (For example, if
+ * isRecovery is true, a chat application would not want to re-display all
+ * the associated chat messages.) The callback should send interests to fetch
+ * the application data for the sequence numbers in the sync state.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onInitialized This calls onInitialized() when the first sync data
+ * is received (or the interest times out because there are no other
+ * publishers yet).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {Name} applicationDataPrefix The prefix used by this application instance
+ * for application data. For example, "/my/local/prefix/ndnchat4/0K4wChff2v".
+ * This is used when sending a sync message for a new sequence number.
+ * In the sync message, this uses applicationDataPrefix.toUri().
+ * @param {Name} applicationBroadcastPrefix The broadcast name prefix including the
+ * application name. For example, "/ndn/broadcast/ChronoChat-0.3/ndnchat1".
+ * This makes a copy of the name.
+ * @param {int} sessionNo The session number used with the applicationDataPrefix in
+ * sync state messages.
+ * @param {Face} face The Face for calling registerPrefix and expressInterest. The
+ * Face object must remain valid for the life of this ChronoSync2013 object.
+ * @param {KeyChain} keyChain To sign a data packet containing a sync state message, this
+ * calls keyChain.sign(data, certificateName).
+ * @param {Name} certificateName The certificate name of the key to use for signing a
+ * data packet containing a sync state message.
+ * @param {Milliseconds} syncLifetime The interest lifetime in milliseconds for sending
+ * sync interests.
+ * @param {function} onRegisterFailed If failed to register the prefix to receive
+ * interests for the applicationBroadcastPrefix, this calls
+ * onRegisterFailed(applicationBroadcastPrefix).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @constructor
+ */
+var ChronoSync2013 = function ChronoSync2013
+  (onReceivedSyncState, onInitialized, applicationDataPrefix,
+   applicationBroadcastPrefix, sessionNo, face, keyChain, certificateName,
+   syncLifetime, onRegisterFailed)
+{
+  // assigning function pointers
+  this.onReceivedSyncState = onReceivedSyncState;
+  this.onInitialized = onInitialized;
+  this.applicationDataPrefixUri = applicationDataPrefix.toUri();
+  this.applicationBroadcastPrefix = applicationBroadcastPrefix;
+  this.session = sessionNo;
+  this.face = face;
+  this.keyChain = keyChain;
+  this.certificateName = certificateName;
+  this.sync_lifetime = syncLifetime;
+  this.usrseq = -1;
+
+  this.digest_tree = new DigestTree();
+  this.contentCache = new MemoryContentCache(face);
+
+  this.digest_log = new Array();
+  this.digest_log.push(new ChronoSync2013.DigestLogEntry("00",[]));
+
+  this.contentCache.registerPrefix
+    (this.applicationBroadcastPrefix, onRegisterFailed,
+     this.onInterest.bind(this));
+  this.enabled = true;
+
+  var interest = new Interest(this.applicationBroadcastPrefix);
+  interest.getName().append("00");
+
+  interest.setInterestLifetimeMilliseconds(1000);
+
+  var Sync;
+  try {
+    // Using protobuf.min.js in the browser.
+    Sync = dcodeIO.ProtoBuf.newBuilder().import(SyncStateProto).build("Sync");
+  }
+  catch (ex) {
+    // Using protobufjs in node.
+    Sync = require("protobufjs").newBuilder().import(SyncStateProto).build("Sync");
+  }
+  this.SyncStateMsg = Sync.SyncStateMsg;
+  this.SyncState = Sync.SyncState;
+
+  this.face.expressInterest(interest, this.onData.bind(this), this.initialTimeOut.bind(this));
+};
+
+exports.ChronoSync2013 = ChronoSync2013;
+
+ChronoSync2013.prototype.getProducerSequenceNo = function(dataPrefix, sessionNo)
+{
+  var index = this.digest_tree.find(dataPrefix, sessionNo);
+  if (index < 0)
+    return -1;
+  else
+    return this.digest_tree.get(index).getSequenceNo();
+};
+
+/**
+ * Increment the sequence number, create a sync message with the new sequence number,
+ * and publish a data packet where the name is applicationBroadcastPrefix + root
+ * digest of current digest tree. Then add the sync message to digest tree and digest
+ * log which creates a new root digest. Finally, express an interest for the next sync
+ * update with the name applicationBroadcastPrefix + the new root digest.
+ * After this, application should publish the content for the new sequence number.
+ * Get the new sequence number with getSequenceNo().
+ */
+ChronoSync2013.prototype.publishNextSequenceNo = function()
+{
+  this.usrseq ++;
+  var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
+                                 type:'UPDATE',
+                                 seqno:{
+                                   seq:this.usrseq,
+                                   session:this.session
+                                  }
+                                })];
+  var content_t = new this.SyncStateMsg({ss:content});
+  this.broadcastSyncState(this.digest_tree.getRoot(), content_t);
+
+  if (!this.update(content))
+    console.log("Warning: ChronoSync: update did not create a new digest log entry");
+
+  var interest = new Interest(this.applicationBroadcastPrefix);
+  interest.getName().append(this.digest_tree.getRoot());
+  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+
+  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
+};
+
+/**
+ * Get the sequence number of the latest data published by this application instance.
+ * @return {int} the sequence number
+ */
+ChronoSync2013.prototype.getSequenceNo = function()
+{
+  return this.usrseq;
+};
+
+// DigestLogEntry class
+
+ChronoSync2013.DigestLogEntry = function ChronoSync2013DisgestLogEntry(digest, data)
+{
+  this.digest = digest;
+  this.data = data;
+};
+
+ChronoSync2013.DigestLogEntry.prototype.getDigest = function()
+{
+  return this.digest;
+};
+
+ChronoSync2013.DigestLogEntry.prototype.getData = function()
+{
+  return this.data;
+};
+
+/**
+ * Unregister callbacks so that this does not respond to interests anymore.
+ * If you will dispose this ChronoSync2013 object while your application is
+ * still running, you should call shutdown() first.  After calling this, you
+ * should not call publishNextSequenceNo() again since the behavior will be
+ * undefined.
+ */
+ChronoSync2013.prototype.shutdown = function()
+{
+  this.enabled = false;
+  this.contentCache.unregisterAll();
+};
+
+// SyncState class
+/**
+ * A SyncState holds the values of a sync state message which is passed to the
+ * onReceivedSyncState callback which was given to the ChronoSyn2013
+ * constructor. Note: this has the same info as the Protobuf class
+ * Sync::SyncState, but we make a separate class so that we don't need the
+ * Protobuf definition in the ChronoSync API.
+ */
+ChronoSync2013.SyncState = function ChronoSync2013SyncState(dataPrefixUri, sessionNo, sequenceNo)
+{
+  this.dataPrefixUri_ = dataPrefixUri;
+  this.sessionNo_ = sessionNo;
+  this.sequenceNo_ = sequenceNo;
+};
+
+/**
+ * Get the application data prefix for this sync state message.
+ * @return The application data prefix as a Name URI string.
+ */
+ChronoSync2013.SyncState.prototype.getDataPrefix = function()
+{
+  return this.dataPrefixUri_;
+}
+
+/**
+ * Get the session number associated with the application data prefix for
+ * this sync state message.
+ * @return The session number.
+ */
+ChronoSync2013.SyncState.prototype.getSessionNo = function()
+{
+  return this.sessionNo_;
+}
+
+/**
+ * Get the sequence number for this sync state message.
+ * @return The sequence number.
+ */
+ChronoSync2013.SyncState.prototype.getSequenceNo = function()
+{
+  return this.sequenceNo_;
+}
+
+// Private methods for ChronoSync2013 class,
+/**
+ * Make a data packet with the syncMessage and with name applicationBroadcastPrefix_ + digest.
+ * Sign and send.
+ * @param {string} The root digest as a hex string for the data packet name.
+ * @param {SyncStateMsg} The syncMessage updates the digest tree state with the given digest.
+ */
+ChronoSync2013.prototype.broadcastSyncState = function(digest, syncMessage)
+{
+  var array = new Uint8Array(syncMessage.toArrayBuffer());
+  var data = new Data(this.applicationBroadcastPrefix);
+  data.getName().append(digest);
+  data.setContent(new Blob(array, false));
+  var thisChronoSync = this;
+  this.keyChain.sign(data, this.certificateName, function() {
+    thisChronoSync.contentCache.add(data);
+  });
+};
+
+/**
+ * Update the digest tree with the messages in content. If the digest tree root is not in
+ * the digest log, also add a log entry with the content.
+ * @param {SyncStates[]} The sync state messages
+ * @return {bool} True if added a digest log entry (because the updated digest tree root
+ * was not in the log), false if didn't add a log entry.
+ */
+ // Whatever's received by ondata, is pushed into digest log as its data directly
+ChronoSync2013.prototype.update = function(content)
+{
+  for (var i = 0; i < content.length; i++) {
+    if (content[i].type == 0) {
+      if (this.digest_tree.update(content[i].name, content[i].seqno.session, content[i].seqno.seq)) {
+        if (this.applicationDataPrefixUri == content[i].name)
+          this.usrseq = content[i].seqno.seq;
+      }
+    }
+  }
+
+  if (this.logfind(this.digest_tree.getRoot()) == -1) {
+    var newlog = new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(), content);
+    this.digest_log.push(newlog);
+    return true;
+  }
+  else
+    return false;
+};
+
+ChronoSync2013.prototype.logfind = function(digest)
+{
+  for (var i = 0; i < this.digest_log.length; i++) {
+    if(digest == this.digest_log[i].digest)
+      return i;
+  }
+  return -1;
+};
+
+/**
+ * Process the sync interest from the applicationBroadcastPrefix. If we can't
+ * satisfy the interest, add it to the pending interest table in
+ * this.contentCache so that a future call to contentCacheAdd may satisfy it.
+ */
+ChronoSync2013.prototype.onInterest = function
+  (prefix, interest, face, interestFilterId, filter)
+{
+  if (!this.enabled)
+    // Ignore callbacks after the application calls shutdown().
+    return;
+
+  //search if the digest is already exist in the digest log
+
+  var syncdigest = interest.getName().get(this.applicationBroadcastPrefix.size()).toEscapedString();
+  if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2) {
+    syncdigest = interest.getName().get(this.applicationBroadcastPrefix.size() + 1).toEscapedString();
+  }
+  if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2 || syncdigest == "00") {
+    this.processRecoveryInst(interest, syncdigest, face);
+  }
+  else {
+    this.contentCache.storePendingInterest(interest, face);
+
+    if (syncdigest != this.digest_tree.getRoot()) {
+      var index = this.logfind(syncdigest);
+      var content = [];
+      if(index == -1) {
+        var self = this;
+        // Are we sure that using a "/local/timeout" interest is the best future call approach?
+        var timeout = new Interest(new Name("/local/timeout"));
+        timeout.setInterestLifetimeMilliseconds(2000);
+        this.face.expressInterest
+          (timeout, this.dummyOnData,
+           this.judgeRecovery.bind(this, timeout, syncdigest, face));
+      }
+      else {
+        //common interest processing
+        this.processSyncInst(index, syncdigest, face);
+      }
+    }
+  }
+};
+
+/**
+ * Process sync/recovery data.
+ * @param {Interest}
+ * @param {Data}
+ */
+ChronoSync2013.prototype.onData = function(interest, co)
+{
+  if (!this.enabled)
+    // Ignore callbacks after the application calls shutdown().
+    return;
+
+  var arr = new Uint8Array(co.getContent().size());
+  arr.set(co.getContent().buf());
+  var content_t = this.SyncStateMsg.decode(arr.buffer);
+  var content = content_t.ss;
+
+  var isRecovery = false;
+
+  if (this.digest_tree.getRoot() == "00") {
+    isRecovery = true;
+    this.initialOndata(content);
+  }
+  else {
+    this.update(content);
+    if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2)
+      // Assume this is a recovery interest.
+      isRecovery = true;
+    else
+      isRecovery = false;
+  }
+
+  var syncStates = [];
+
+  for (var i = 0; i < content.length; i++) {
+    if (content[i].type == 0) {
+      syncStates.push(new ChronoSync2013.SyncState
+        (content[i].name, content[i].seqno.session, content[i].seqno.seq));
+    }
+  }
+
+  // Instead of using Protobuf, use our own definition of SyncStates to pass to onReceivedSyncState.
+  try {
+    this.onReceivedSyncState(syncStates, isRecovery);
+  } catch (ex) {
+    console.log("Error in onReceivedSyncState: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+
+  var n = new Name(this.applicationBroadcastPrefix);
+  n.append(this.digest_tree.getRoot());
+
+  var interest = new Interest(n);
+  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+
+  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
+};
+
+/**
+ * Interest variable not actually in use here
+ */
+ChronoSync2013.prototype.initialTimeOut = function(interest)
+{
+  if (!this.enabled)
+    // Ignore callbacks after the application calls shutdown().
+    return;
+
+  console.log("no other people");
+
+  this.usrseq++;
+  try {
+    this.onInitialized();
+  } catch (ex) {
+    console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
+  }
+  var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
+                                 type:'UPDATE',
+                                 seqno: {
+                                   seq:this.usrseq,
+                                   session:this.session
+                                 }
+                               })];
+  this.update(content);
+  var n = new Name(this.applicationBroadcastPrefix);
+  n.append(this.digest_tree.getRoot());
+  var retryInterest = new Interest(n);
+  retryInterest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+
+  this.face.expressInterest(retryInterest, this.onData.bind(this), this.syncTimeout.bind(this));
+};
+
+ChronoSync2013.prototype.processRecoveryInst = function(interest, syncdigest, face)
+{
+  if (this.logfind(syncdigest) != -1) {
+    var content = [];
+
+    for(var i = 0; i < this.digest_tree.digestnode.length; i++) {
+      content[i] = new this.SyncState({ name:this.digest_tree.digestnode[i].getDataPrefix(),
+                                   type:'UPDATE',
+                                   seqno:{
+                                     seq:this.digest_tree.digestnode[i].getSequenceNo(),
+                                     session:this.digest_tree.digestnode[i].getSessionNo()
+                                    }
+                                 });
+    }
+
+    if (content.length != 0) {
+      var content_t = new this.SyncStateMsg({ss:content});
+      var str = new Uint8Array(content_t.toArrayBuffer());
+      var co = new Data(interest.getName());
+      co.setContent(new Blob(str, false));
+      if (interest.getName().get(-1).toEscapedString() == "00")
+        // Limit the lifetime of replies to interest for "00" since they can be different.
+        co.getMetaInfo().setFreshnessPeriod(1000);
+
+      this.keyChain.sign(co, this.certificateName, function() {
+        try {
+          face.putData(co);
+        } catch (e) {
+          console.log(e.toString());
+        }
+      });
+    }
+  }
+};
+
+/**
+ * Common interest processing, using digest log to find the difference after syncdigest_t
+ * @return True if sent a data packet to satisfy the interest.
+ */
+ChronoSync2013.prototype.processSyncInst = function(index, syncdigest_t, face)
+{
+  var content = [];
+  var data_name = [];
+  var data_seq = [];
+  var data_ses = [];
+
+  for (var j = index + 1; j < this.digest_log.length; j++) {
+    var temp = this.digest_log[j].getData();
+    for (var i = 0 ; i < temp.length ; i++) {
+      if (temp[i].type != 0) {
+        continue;
+      }
+      if (this.digest_tree.find(temp[i].name, temp[i].seqno.session) != -1) {
+        var n = data_name.indexOf(temp[i].name);
+        if (n == -1) {
+          data_name.push(temp[i].name);
+          data_seq.push(temp[i].seqno.seq);
+          data_ses.push(temp[i].seqno.session);
+        }
+        else {
+          data_seq[n] = temp[i].seqno.seq;
+          data_ses[n] = temp[i].seqno.session;
+        }
+      }
+    }
+  }
+
+  for(var i = 0; i < data_name.length; i++) {
+    content[i] = new this.SyncState({ name:data_name[i],
+                                 type:'UPDATE',
+                                 seqno: {
+                                   seq:data_seq[i],
+                                   session:data_ses[i]
+                                 }
+                               });
+  }
+  if (content.length != 0) {
+    var content_t = new this.SyncStateMsg({ss:content});
+    var str = new Uint8Array(content_t.toArrayBuffer());
+    var n = new Name(this.prefix)
+    n.append(this.chatroom).append(syncdigest_t);
+
+    var co = new Data(n);
+    co.setContent(new Blob(str, false));
+    this.keyChain.sign(co, this.certificateName, function() {
+      try {
+        face.putData(co);
+      }
+      catch (e) {
+        console.log(e.toString());
+      }
+    });
+  }
+};
+
+/**
+ * Send recovery interset.
+ * @param {string} syncdigest_t
+ */
+ChronoSync2013.prototype.sendRecovery = function(syncdigest_t)
+{
+  var n = new Name(this.applicationBroadcastPrefix);
+  n.append("recovery").append(syncdigest_t);
+
+  var interest = new Interest(n);
+
+  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+
+  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
+};
+
+/**
+ * This is called by onInterest after a timeout to check if a recovery is needed.
+ * This method has an interest argument because we use it as the onTimeout for
+ * Face.expressInterest.
+ * @param {Interest}
+ * @param {string}
+ * @param {Face}
+ */
+ChronoSync2013.prototype.judgeRecovery = function(interest, syncdigest_t, face)
+{
+  //console.log("*** judgeRecovery interest " + interest.getName().toUri() + " times out. Digest: " + syncdigest_t + " ***");
+  var index = this.logfind(syncdigest_t);
+  if (index != -1) {
+    if (syncdigest_t != this.digest_tree.root)
+      this.processSyncInst(index, syncdigest_t, face);
+  }
+  else
+    this.sendRecovery(syncdigest_t);
+};
+
+ChronoSync2013.prototype.syncTimeout = function(interest)
+{
+  if (!this.enabled)
+    // Ignore callbacks after the application calls shutdown().
+    return;
+
+  var component = interest.getName().get(4).toEscapedString();
+  if (component == this.digest_tree.root) {
+    var n = new Name(interest.getName());
+    var newInterest = new Interest(n);
+
+    interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
+    this.face.expressInterest(newInterest, this.onData.bind(this), this.syncTimeout.bind(this));
+  }
+};
+
+ChronoSync2013.prototype.initialOndata = function(content)
+{
+  this.update(content);
+
+  var digest_t = this.digest_tree.getRoot();
+  for (var i = 0; i < content.length; i++) {
+    if (content[i].name == this.applicationDataPrefixUri && content[i].seqno.session == this.session) {
+      //if the user was an old comer, after add the static log he need to increase his seqno by 1
+      var content_t = [new this.SyncState({ name:this.applicationDataPrefixUri,
+                                       type:'UPDATE',
+                                       seqno: {
+                                         seq:content[i].seqno.seq + 1,
+                                         session:this.session
+                                       }
+                                     })];
+      if (this.update(content_t)) {
+        var newlog = new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(), content_t);
+        this.digest_log.push(newlog);
+        try {
+          this.onInitialized();
+        } catch (ex) {
+          console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+    }
+  }
+
+  var content_t;
+  if (this.usrseq >= 0) {
+    //send the data packet with new seqno back
+    content_t = new this.SyncState({ name:this.applicationDataPrefixUri,
+                                   type:'UPDATE',
+                                   seqno: {
+                                     seq:this.usrseq,
+                                     session:this.session
+                                   }
+                                 });
+  }
+  else
+    content_t = new this.SyncState({ name:this.applicationDataPrefixUri,
+                                   type:'UPDATE',
+                                   seqno: {
+                                     seq:0,
+                                     session:this.session
+                                   }
+                                 });
+  var content_tt = new this.SyncStateMsg({ss:content_t});
+  this.broadcastSyncState(digest_t, content_tt);
+
+  if (this.digest_tree.find(this.applicationDataPrefixUri, this.session) == -1) {
+    //the user haven't put himself in the digest tree
+    this.usrseq++;
+    var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
+                                   type:'UPDATE',
+                                   seqno: {
+                                     seq:this.usrseq,
+                                     session:this.session
+                                   }
+                                 })];
+    if (this.update(content)) {
+      try {
+        this.onInitialized();
+      } catch (ex) {
+        console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+  }
+};
+
+ChronoSync2013.prototype.dummyOnData = function(interest, data)
+{
+  console.log("*** dummyOnData called. ***");
+};/**
+ * This class represents the digest tree for chrono-sync2013.
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Zhehao Wang, based on Jeff T.'s implementation in ndn-cpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../crypto.js');
+
+/**
+ * @constructor
+ */
+var DigestTree = function DigestTree()
+{
+  this.root = "00";
+  this.digestnode = [];
+};
+
+exports.DigestTree = DigestTree;
+
+// The meaning of a session is explained here:
+// http://named-data.net/doc/ndn-ccl-api/chrono-sync2013.html
+// DigestTree.Node works with seqno_seq and seqno_session, without protobuf definition,
+DigestTree.Node = function DigestTreeNode(dataPrefix, seqno_session, seqno_seq)
+{
+  // In this context, this should mean DigestTree.Node instead
+  this.dataPrefix = dataPrefix;
+  this.seqno_session = seqno_session;
+  this.seqno_seq = seqno_seq;
+
+  this.recomputeDigest();
+};
+
+DigestTree.Node.prototype.getDataPrefix = function()
+{
+  return this.dataPrefix;
+};
+
+DigestTree.Node.prototype.getSessionNo = function()
+{
+  return this.seqno_session;
+};
+
+DigestTree.Node.prototype.getSequenceNo = function()
+{
+  return this.seqno_seq;
+};
+
+DigestTree.Node.prototype.getDigest = function()
+{
+  return this.digest;
+};
+
+DigestTree.Node.prototype.setSequenceNo = function(sequenceNo)
+{
+  this.seqno_seq = sequenceNo;
+  this.recomputeDigest();
+};
+
+// Using Node.JS buffer, as documented here http://nodejs.org/api/buffer.html.
+DigestTree.Node.prototype.Int32ToBuffer = function(value) {
+  var result = new Buffer(4);
+  for (var i = 0; i < 4; i++) {
+    result[i] = value % 256;
+    value = Math.floor(value / 256);
+  }
+  return result;
+}
+
+DigestTree.Node.prototype.recomputeDigest = function()
+{
+  var seqHash = Crypto.createHash('sha256');
+
+  seqHash.update(this.Int32ToBuffer(this.seqno_session));
+  seqHash.update(this.Int32ToBuffer(this.seqno_seq));
+
+  var digest_seq = seqHash.digest();
+
+  var nameHash = Crypto.createHash('sha256');
+  nameHash.update(this.dataPrefix);
+  var digest_name = nameHash.digest();
+
+  var hash = Crypto.createHash('sha256');
+  hash.update(digest_name);
+  hash.update(digest_seq);
+
+  this.digest = hash.digest('hex');
+};
+
+// Do the work of string and then sequence number compare
+DigestTree.Node.Compare = function(node1, node2)
+{
+  if (node1.dataPrefix != node2.dataPrefix)
+    return node1.dataPrefix < node2.dataPrefix;
+  return node1.seqno_session < node2.seqno_session;
+};
+
+/**
+ * Update the digest tree and recompute the root digest. If the combination of dataPrefix
+ * and sessionNo already exists in the tree then update its sequenceNo (only if the given
+ * sequenceNo is newer), otherwise add a new node.
+ * @param {string} The name prefix.
+ * @param {int} sessionNo The session number.
+ * @param {int} sequenceNo The sequence number.
+ * @return True if the digest tree is updated, false if not
+ */
+DigestTree.prototype.update = function(dataPrefix, sessionNo, sequenceNo)
+{
+  var n_index = this.find(dataPrefix, sessionNo);
+  if (n_index >= 0) {
+    if (this.digestnode[n_index].getSequenceNo() < sequenceNo)
+      this.digestnode[n_index].setSequenceNo(sequenceNo);
+    else
+      return false;
+  }
+  else {
+    var temp = new DigestTree.Node(dataPrefix, sessionNo, sequenceNo);
+    this.digestnode.push(temp);
+    this.digestnode.sort(this.sortNodes);
+  }
+  this.recomputeRoot();
+  return true;
+};
+
+// Need to confirm this sort works with the insertion in ndn-cpp.
+DigestTree.prototype.sortNodes = function()
+{
+  var temp;
+  for (var i = this.digestnode.length; i > 0; i--) {
+    for (var j = 0; j < i - 1; j++) {
+      if (this.digestnode[j].getDataPrefix() > this.digestnode[j + 1].getDataPrefix()) {
+        temp = this.digestnode[j];
+        this.digestnode[j] = this.digestnode[j + 1];
+        this.digestnode[j + 1] = temp;
+      }
+    }
+  }
+};
+
+DigestTree.prototype.sortNodes = function (node1, node2)
+{
+  if (node1.getDataPrefix() == node2.getDataPrefix() &&
+     node1.getSessionNo() == node2.getSessionNo())
+    return 0;
+
+  if ((node1.getDataPrefix() > node2.getDataPrefix()) ||
+     ((node1.getDataPrefix() == node2.getDataPrefix()) &&
+     (node1.getSessionNo() >node2.getSessionNo())))
+    return 1;
+  else
+    return -1;
+}
+
+DigestTree.prototype.find = function(dataPrefix, sessionNo)
+{
+  for (var i = 0; i < this.digestnode.length; ++i) {
+    if (this.digestnode[i].getDataPrefix() == dataPrefix &&
+        this.digestnode[i].getSessionNo() == sessionNo)
+      return i;
+  }
+  return -1;
+};
+
+DigestTree.prototype.size = function()
+{
+  return this.digestnode.size();
+};
+
+// Not really used
+DigestTree.prototype.get = function(i)
+{
+  return this.digestnode[i];
+};
+
+DigestTree.prototype.getRoot = function()
+{
+  return this.root;
+};
+
+DigestTree.prototype.recomputeRoot = function()
+{
+  var md = Crypto.createHash('sha256');
+  // The result of updateHex is related with the sequence of participants,
+  // I don't think that should be the case.
+  for (var i = 0; i < this.digestnode.length; i++) {
+    md.update(new Buffer(this.digestnode[i].digest, 'hex'));
+  }
+  this.root = md.digest('hex');
+};
+// Just define the SyncStateProto object. We do a Protobuf import dynamically
+// when we need it so that protobufjs is optional.
+var SyncStateProto = {
+    "package": "Sync",
+    "messages": [
+        {
+            "name": "SyncState",
+            "fields": [
+                {
+                    "rule": "required",
+                    "type": "string",
+                    "name": "name",
+                    "id": 1,
+                    "options": {}
+                },
+                {
+                    "rule": "required",
+                    "type": "ActionType",
+                    "name": "type",
+                    "id": 2,
+                    "options": {}
+                },
+                {
+                    "rule": "optional",
+                    "type": "SeqNo",
+                    "name": "seqno",
+                    "id": 3,
+                    "options": {}
+                }
+            ],
+            "enums": [
+                {
+                    "name": "ActionType",
+                    "values": [
+                        {
+                            "name": "UPDATE",
+                            "id": 0
+                        },
+                        {
+                            "name": "DELETE",
+                            "id": 1
+                        },
+                        {
+                            "name": "OTHER",
+                            "id": 2
+                        }
+                    ],
+                    "options": {}
+                }
+            ],
+            "messages": [
+                {
+                    "name": "SeqNo",
+                    "fields": [
+                        {
+                            "rule": "required",
+                            "type": "uint32",
+                            "name": "seq",
+                            "id": 1,
+                            "options": {}
+                        },
+                        {
+                            "rule": "required",
+                            "type": "uint32",
+                            "name": "session",
+                            "id": 2,
+                            "options": {}
+                        }
+                    ],
+                    "enums": [],
+                    "messages": [],
+                    "options": {}
+                }
+            ],
+            "options": {}
+        },
+        {
+            "name": "SyncStateMsg",
+            "fields": [
+                {
+                    "rule": "repeated",
+                    "type": "SyncState",
+                    "name": "ss",
+                    "id": 1,
+                    "options": {}
+                }
+            ],
+            "enums": [],
+            "messages": [],
+            "options": {}
+        }
+    ],
+    "enums": [],
+    "imports": [],
+    "options": {}
+};
+
+exports.SyncStateProto = SyncStateProto;
+/**
+ * Copyright (C) 2014-2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+// Use capitalized Crypto to not clash with the browser's crypto.subtle.
+/** @ignore */
+var Crypto = require('../crypto.js'); /** @ignore */
+var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
+var TlvEncoder = require('../encoding/tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
+var Blob = require('./blob.js').Blob;
+
+/**
+ * A CommandInterestGenerator keeps track of a timestamp and generates command
+ * interests according to the NFD Signed Command Interests protocol:
+ * http://redmine.named-data.net/projects/nfd/wiki/Command_Interests
+ *
+ * Create a new CommandInterestGenerator and initialize the timestamp to now.
+ * @constructor
+ */
+var CommandInterestGenerator = function CommandInterestGenerator()
+{
+  this.lastTimestamp = Math.round(new Date().getTime());
+};
+
+exports.CommandInterestGenerator = CommandInterestGenerator;
+
+/**
+ * Append a timestamp component and a random value component to interest's name.
+ * This ensures that the timestamp is greater than the timestamp used in the
+ * previous call. Then use keyChain to sign the interest which appends a
+ * SignatureInfo component and a component with the signature bits. If the
+ * interest lifetime is not set, this sets it.
+ * @param {Interest} interest The interest whose name is append with components.
+ * @param {KeyChain} keyChain The KeyChain for calling sign.
+ * @param {Name} certificateName The certificate name of the key to use for
+ * signing.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the SignatureInfo and to encode interest name for signing. If omitted, use
+ * WireFormat.getDefaultWireFormat().
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some crypto/database libraries only use a callback, so onComplete is
+ * required to use these.)
+ */
+CommandInterestGenerator.prototype.generate = function
+  (interest, keyChain, certificateName, wireFormat, onComplete)
+{
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ?
+    WireFormat.getDefaultWireFormat() : wireFormat;
+
+  var timestamp = Math.round(new Date().getTime());
+  while (timestamp <= this.lastTimestamp)
+    timestamp += 1.0;
+
+  // The timestamp is encoded as a TLV nonNegativeInteger.
+  var encoder = new TlvEncoder(8);
+  encoder.writeNonNegativeInteger(timestamp);
+  interest.getName().append(new Blob(encoder.getOutput(), false));
+
+  // The random value is a TLV nonNegativeInteger too, but we know it is 8
+  // bytes, so we don't need to call the nonNegativeInteger encoder.
+  interest.getName().append(new Blob(Crypto.randomBytes(8), false));
+
+  // Update the timestamp before calling async sign.
+  this.lastTimestamp = timestamp;
+
+  keyChain.sign(interest, certificateName, wireFormat, function() {
+    if (interest.getInterestLifetimeMilliseconds() == null ||
+        interest.getInterestLifetimeMilliseconds() < 0)
+      // The caller has not set the interest lifetime, so set it here.
+      interest.setInterestLifetimeMilliseconds(1000.0);
+
+    if (onComplete)
+      onComplete();
+  });
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * An InterestFilterTable is an internal class to hold a list of entries with
+ * an interest Filter and its OnInterestCallback.
+ * @constructor
+ */
+var InterestFilterTable = function InterestFilterTable()
+{
+  this.table_ = []; // of Entry
+};
+
+exports.InterestFilterTable = InterestFilterTable;
+
+/**
+ * InterestFilterTable.Entry holds an interestFilterId, an InterestFilter and
+ * the OnInterestCallback with its related Face.
+ * Create a new Entry with the given values.
+ * @param {number} interestFilterId The ID from getNextEntryId().
+ * @param {InterestFilter} filter The InterestFilter for this entry.
+ * @param {function} onInterest The callback to call.
+ * @param {Face} face The face on which was called registerPrefix or
+ * setInterestFilter which is passed to the onInterest callback.
+ * @constructor
+ */
+InterestFilterTable.Entry = function InterestFilterTableEntry
+  (interestFilterId, filter, onInterest, face)
+{
+  this.interestFilterId_ = interestFilterId;
+  this.filter_ = filter;
+  this.onInterest_ = onInterest;
+  this.face_ = face;
+};
+
+/**
+ * Get the interestFilterId given to the constructor.
+ * @return {number} The interestFilterId.
+ */
+InterestFilterTable.Entry.prototype.getInterestFilterId = function()
+{
+  return this.interestFilterId_;
+};
+
+/**
+ * Get the InterestFilter given to the constructor.
+ * @return {InterestFilter} The InterestFilter.
+ */
+InterestFilterTable.Entry.prototype.getFilter = function()
+{
+  return this.filter_;
+};
+
+/**
+ * Get the onInterest callback given to the constructor.
+ * @return {function} The onInterest callback.
+ */
+InterestFilterTable.Entry.prototype.getOnInterest = function()
+{
+  return this.onInterest_;
+};
+
+/**
+ * Get the Face given to the constructor.
+ * @return {Face} The Face.
+ */
+InterestFilterTable.Entry.prototype.getFace = function()
+{
+  return this.face_;
+};
+
+/**
+ * Add a new entry to the table.
+ * @param {number} interestFilterId The ID from Node.getNextEntryId().
+ * @param {InterestFilter} filter The InterestFilter for this entry.
+ * @param {function} onInterest The callback to call.
+ * @param {Face} face The face on which was called registerPrefix or
+ * setInterestFilter which is passed to the onInterest callback.
+ */
+InterestFilterTable.prototype.setInterestFilter = function
+  (interestFilterId, filter, onInterest, face)
+{
+  this.table_.push(new InterestFilterTable.Entry
+    (interestFilterId, filter, onInterest, face));
+};
+
+/**
+ * Find all entries from the interest filter table where the interest conforms
+ * to the entry's filter, and add to the matchedFilters list.
+ * @param {Interest} interest The interest which may match the filter in
+ * multiple entries.
+ * @param {Array<InterestFilterTable.Entry>} matchedFilters Add each matching
+ * InterestFilterTable.Entry from the interest filter table.  The caller should
+ * pass in an empty array.
+ */
+InterestFilterTable.prototype.getMatchedFilters = function
+  (interest, matchedFilters)
+{
+  for (var i = 0; i < this.table_.length; ++i) {
+    var entry = this.table_[i];
+    if (entry.getFilter().doesMatch(interest.getName()))
+      matchedFilters.push(entry);
+  }
+};
+
+/**
+ * Remove the interest filter entry which has the interestFilterId from the
+ * interest filter table. This does not affect another interest filter with a
+ * different interestFilterId, even if it has the same prefix name. If there is
+ * no entry with the interestFilterId, do nothing.
+ * @param {number} interestFilterId The ID returned from setInterestFilter.
+ */
+InterestFilterTable.prototype.unsetInterestFilter = function(interestFilterId)
+{
+  // Go backwards through the list so we can erase entries.
+  // Remove all entries even though interestFilterId should be unique.
+  var count = 0;
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    if (this.table_[i].getInterestFilterId() == interestFilterId) {
+      ++count;
+      this.table_.splice(i, 1);
+    }
+  }
+
+  if (count === 0)
+    if (LOG > 0) console.log
+      ("unsetInterestFilter: Didn't find interestFilterId " + interestFilterId);
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * A PendingInterestTable is an internal class to hold a list of pending
+ * interests with their callbacks.
+ * @constructor
+ */
+var PendingInterestTable = function PendingInterestTable()
+{
+  this.table_ = []; // of Entry
+  this.removeRequests_ = []; // of number
+};
+
+exports.PendingInterestTable = PendingInterestTable;
+
+/**
+ * PendingInterestTable.Entry holds the callbacks and other fields for an entry
+ * in the pending interest table.
+ * Create a new Entry with the given fields. Note: You should not call this
+ * directly but call PendingInterestTable.add.
+ * @constructor
+ */
+PendingInterestTable.Entry = function PendingInterestTableEntry
+  (pendingInterestId, interest, onData, onTimeout, onNetworkNack)
+{
+  this.pendingInterestId_ = pendingInterestId;
+  this.interest_ = interest;
+  this.onData_ = onData;
+  this.onTimeout_ = onTimeout;
+  this.onNetworkNack_ = onNetworkNack;
+  this.timerId_ = -1;
+};
+
+/**
+ * Get the pendingInterestId given to the constructor.
+ * @return {number} The pendingInterestId.
+ */
+PendingInterestTable.Entry.prototype.getPendingInterestId = function()
+{
+  return this.pendingInterestId_;
+};
+
+/**
+ * Get the interest given to the constructor (from Face.expressInterest).
+ * @return {Interest} The interest. NOTE: You must not change the interest
+ * object - if you need to change it then make a copy.
+ */
+PendingInterestTable.Entry.prototype.getInterest = function()
+{
+  return this.interest_;
+};
+
+/**
+ * Get the OnData callback given to the constructor.
+ * @return {function} The OnData callback.
+ */
+PendingInterestTable.Entry.prototype.getOnData = function()
+{
+  return this.onData_;
+};
+
+/**
+ * Get the OnNetworkNack callback given to the constructor.
+ * @return {function} The OnNetworkNack callback.
+ */
+PendingInterestTable.Entry.prototype.getOnNetworkNack = function()
+{
+  return this.onNetworkNack_;
+};
+
+/**
+* Call onTimeout_ (if defined). This ignores exceptions from the call to
+* onTimeout_.
+*/
+PendingInterestTable.Entry.prototype.callTimeout = function()
+{
+  if (this.onTimeout_) {
+    try {
+      this.onTimeout_(this.interest_);
+    } catch (ex) {
+      console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Call setTimeout(callback, milliseconds) and remember the timer ID. If the
+ * timer ID has already been set on a prevous call, do nothing.
+ */
+PendingInterestTable.Entry.prototype.setTimeout = function(callback, milliseconds)
+{
+  if (this.timerId_ !== -1)
+    // Already set a timeout.
+    return;
+  this.timerId_ = setTimeout(callback, milliseconds);
+};
+
+/**
+ * Clear the timeout timer and reset the timer ID.
+ */
+PendingInterestTable.Entry.prototype.clearTimeout = function()
+{
+  if (this.timerId_ !== -1) {
+    clearTimeout(this.timerId_);
+    this.timerId_ = -1;
+  }
+};
+
+/**
+ * Add a new entry to the pending interest table. Also set a timer to call the
+ * timeout. However, if removePendingInterest was already called with the
+ * pendingInterestId, don't add an entry and return null.
+ * @param {number} pendingInterestId
+ * @param {Interest} interestCopy
+ * @param {function} onData
+ * @param {function} onTimeout
+ * @param {function} onNetworkNack
+ * @return {PendingInterestTable.Entry} The new PendingInterestTable.Entry, or
+ * null if removePendingInterest was already called with the pendingInterestId.
+ */
+PendingInterestTable.prototype.add = function
+  (pendingInterestId, interestCopy, onData, onTimeout, onNetworkNack)
+{
+  var removeRequestIndex = this.removeRequests_.indexOf(pendingInterestId);
+  if (removeRequestIndex >= 0) {
+    // removePendingInterest was called with the pendingInterestId returned by
+    //   expressInterest before we got here, so don't add a PIT entry.
+    this.removeRequests_.splice(removeRequestIndex, 1);
+    return null;
+  }
+
+  var entry = new PendingInterestTable.Entry
+    (pendingInterestId, interestCopy, onData, onTimeout, onNetworkNack);
+  this.table_.push(entry);
+
+  // Set interest timer.
+  var timeoutMilliseconds = (interestCopy.getInterestLifetimeMilliseconds() || 4000);
+  var thisTable = this;
+  var timeoutCallback = function() {
+    if (LOG > 1) console.log("Interest time out: " + interestCopy.getName().toUri());
+
+    // Remove the entry from the table.
+    var index = thisTable.table_.indexOf(entry);
+    if (index >= 0)
+      thisTable.table_.splice(index, 1);
+
+    entry.callTimeout();
+  };
+
+  entry.setTimeout(timeoutCallback, timeoutMilliseconds);
+  return entry;
+};
+
+/**
+ * Find all entries from the pending interest table where data conforms to
+ * the entry's interest selectors, remove the entries from the table, and add to
+ * the entries list.
+ * @param {Data} data The incoming Data packet to find the interest for.
+ * @param {Array<PendingInterestTable.Entry>} entries Add matching
+ * PendingInterestTable.Entry from the pending interest table. The caller should
+ * pass in an empty array.
+ */
+PendingInterestTable.prototype.extractEntriesForExpressedInterest = function
+  (data, entries)
+{
+  // Go backwards through the list so we can erase entries.
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    var pendingInterest = this.table_[i];
+    if (pendingInterest.getInterest().matchesData(data)) {
+      pendingInterest.clearTimeout();
+      entries.push(pendingInterest);
+      this.table_.splice(i, 1);
+    }
+  }
+};
+
+/**
+ * Find all entries from the pending interest table where the OnNetworkNack
+ * callback is not null and the entry's interest is the same as the given
+ * interest, remove the entries from the table, and add to the entries list. 
+ * (We don't remove the entry if the OnNetworkNack callback is null so that
+ * OnTimeout will be called later.) The interests are the same if their default
+ * wire encoding is the same (which has everything including the name, nonce,
+ * link object and selectors).
+ * @param {Interest} interest The Interest to search for (typically from a Nack
+ * packet).
+ * @param {Array<PendingInterestTable.Entry>} entries Add matching
+ * PendingInterestTable.Entry from the pending interest table. The caller should
+ * pass in an empty array.
+ */
+PendingInterestTable.prototype.extractEntriesForNackInterest = function
+  (interest, entries)
+{
+  var encoding = interest.wireEncode();
+
+  // Go backwards through the list so we can erase entries.
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    var pendingInterest = this.table_[i];
+    if (pendingInterest.getOnNetworkNack() == null)
+      continue;
+
+    // wireEncode returns the encoding cached when the interest was sent (if
+    // it was the default wire encoding).
+    if (pendingInterest.getInterest().wireEncode().equals(encoding)) {
+      pendingInterest.clearTimeout();
+      entries.push(pendingInterest);
+      this.table_.splice(i, 1);
+    }
+  }
+};
+
+/**
+ * Remove the pending interest entry with the pendingInterestId from the pending
+ * interest table. This does not affect another pending interest with a
+ * different pendingInterestId, even if it has the same interest name.
+ * If there is no entry with the pendingInterestId, do nothing.
+ * @param {number} pendingInterestId The ID returned from expressInterest.
+ */
+PendingInterestTable.prototype.removePendingInterest = function
+  (pendingInterestId)
+{
+  if (pendingInterestId == null)
+    return;
+
+  // Go backwards through the list so we can erase entries.
+  // Remove all entries even though pendingInterestId should be unique.
+  var count = 0;
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    var entry = this.table_[i];
+    if (entry.getPendingInterestId() == pendingInterestId) {
+      entry.clearTimeout();
+      this.table_.splice(i, 1);
+      ++count;
+    }
+  }
+
+  if (count === 0)
+    if (LOG > 0) console.log
+      ("removePendingInterest: Didn't find pendingInterestId " + pendingInterestId);
+
+  if (count === 0) {
+    // The pendingInterestId was not found. Perhaps this has been called before
+    //   the callback in expressInterest can add to the PIT. Add this
+    //   removal request which will be checked before adding to the PIT.
+    if (this.removeRequests_.indexOf(pendingInterestId) < 0)
+      // Not already requested, so add the request.
+      this.removeRequests_.push(pendingInterestId);
+  }
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var LOG = require('../log.js').Log.LOG;
+
+/**
+ * A RegisteredPrefixTable is an internal class to hold a list of registered
+ * prefixes with information necessary to remove the registration later.
+ * @param {InterestFilterTable} interestFilterTable See removeRegisteredPrefix(),
+ * which may call interestFilterTable.unsetInterestFilter().
+ * @constructor
+ */
+var RegisteredPrefixTable = function RegisteredPrefixTable(interestFilterTable)
+{
+  this.interestFilterTable_ = interestFilterTable;
+  this.table_ = []; // of Entry
+  this.removeRequests_ = []; // of number
+};
+
+exports.RegisteredPrefixTable = RegisteredPrefixTable;
+
+/**
+ * Add a new entry to the table. However, if removeRegisteredPrefix was already
+ * called with the registeredPrefixId, don't add an entry and return false.
+ * @param {number} registeredPrefixId The ID from Node.getNextEntryId().
+ * @param {Name} prefix The name prefix.
+ * @param {number} relatedInterestFilterId (optional) The related
+ * interestFilterId for the filter set in the same registerPrefix operation. If
+ * omitted, set to 0.
+ * return {boolean} True if added an entry, false if removeRegisteredPrefix was
+ * already called with the registeredPrefixId.
+ */
+RegisteredPrefixTable.prototype.add = function
+  (registeredPrefixId, prefix, relatedInterestFilterId)
+{
+  var removeRequestIndex = this.removeRequests_.indexOf(registeredPrefixId);
+  if (removeRequestIndex >= 0) {
+    // removeRegisteredPrefix was called with the registeredPrefixId returned by
+    //   registerPrefix before we got here, so don't add a registered prefix
+    //   table entry.
+    this.removeRequests_.splice(removeRequestIndex, 1);
+    return false;
+  }
+
+  this.table_.push(new RegisteredPrefixTable._Entry
+    (registeredPrefixId, prefix, relatedInterestFilterId));
+  return true;
+};
+
+/**
+ * Remove the registered prefix entry with the registeredPrefixId from the
+ * registered prefix table. This does not affect another registered prefix with
+ * a different registeredPrefixId, even if it has the same prefix name. If an
+ * interest filter was automatically created by registerPrefix, also call
+ * interestFilterTable_.unsetInterestFilter to remove it.
+ * If there is no entry with the registeredPrefixId, do nothing.
+ * @param {number} registeredPrefixId The ID returned from registerPrefix.
+ */
+RegisteredPrefixTable.prototype.removeRegisteredPrefix = function
+  (registeredPrefixId)
+{
+  // Go backwards through the list so we can erase entries.
+  // Remove all entries even though registeredPrefixId should be unique.
+  var count = 0;
+  for (var i = this.table_.length - 1; i >= 0; --i) {
+    var entry = this.table_[i];
+    if (entry.getRegisteredPrefixId() == registeredPrefixId) {
+      ++count;
+
+      if (entry.getRelatedInterestFilterId() > 0)
+        // Remove the related interest filter.
+        this.interestFilterTable_.unsetInterestFilter
+          (entry.getRelatedInterestFilterId());
+
+      this.table_.splice(i, 1);
+    }
+  }
+
+  if (count === 0)
+    if (LOG > 0) console.log
+      ("removeRegisteredPrefix: Didn't find registeredPrefixId " + registeredPrefixId);
+
+  if (count === 0) {
+    // The registeredPrefixId was not found. Perhaps this has been called before
+    //   the callback in registerPrefix can add to the registered prefix table.
+    //   Add this removal request which will be checked before adding to the
+    //   registered prefix table.
+    if (this.removeRequests_.indexOf(registeredPrefixId) < 0)
+      // Not already requested, so add the request.
+      this.removeRequests_.push(registeredPrefixId);
+  }
+};
+
+/**
+ * RegisteredPrefixTable._Entry holds a registeredPrefixId and information
+ * necessary to remove the registration later. It optionally holds a related
+ * interestFilterId if the InterestFilter was set in the same registerPrefix
+ * operation.
+ * Create a RegisteredPrefixTable.Entry with the given values.
+ * @param {number} registeredPrefixId The ID from Node.getNextEntryId().
+ * @param {Name} prefix The name prefix.
+ * @param {number} relatedInterestFilterId (optional) The related
+ * interestFilterId for the filter set in the same registerPrefix operation. If
+ * omitted, set to 0.
+ * @constructor
+ */
+RegisteredPrefixTable._Entry = function RegisteredPrefixTableEntry
+  (registeredPrefixId, prefix, relatedInterestFilterId)
+{
+  this.registeredPrefixId_ = registeredPrefixId;
+  this.prefix_ = prefix;
+  this.relatedInterestFilterId_ = relatedInterestFilterId;
+};
+
+/**
+ * Get the registeredPrefixId given to the constructor.
+ * @return {number} The registeredPrefixId.
+ */
+RegisteredPrefixTable._Entry.prototype.getRegisteredPrefixId = function()
+{
+  return this.registeredPrefixId;
+};
+
+/**
+ * Get the name prefix given to the constructor.
+ * @return {Name} The name prefix.
+ */
+RegisteredPrefixTable._Entry.prototype.getPrefix = function()
+{
+  return this.prefix;
+};
+
+/**
+ * Get the related interestFilterId given to the constructor.
+ * @return {number} The related interestFilterId.
+ */
+RegisteredPrefixTable._Entry.prototype.getRelatedInterestFilterId = function()
+{
+  return this.relatedInterestFilterId;
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-cxx fields.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/fields.hpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/**
+ * IncomingFaceId represents the incoming face ID header field in an NDNLPv2 packet.
+ * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
+ * @constructor
+ */
+var IncomingFaceId = function IncomingFaceId()
+{
+  this.faceId_ = null;
+};
+
+exports.IncomingFaceId = IncomingFaceId;
+
+/**
+ * Get the incoming face ID value.
+ * @return {number} The face ID value.
+ */
+IncomingFaceId.prototype.getFaceId = function() { return this.faceId_; };
+
+/**
+ * Set the face ID value.
+ * @param {number} faceId The incoming face ID value.
+ */
+IncomingFaceId.prototype.setFaceId = function(faceId)
+{
+  this.faceId_ = faceId;
+};
+
+/**
+ * Get the first header field in lpPacket which is an IncomingFaceId. This is
+ * an internal method which the application normally would not use.
+ * @param {LpPacket} lpPacket The LpPacket with the header fields to search.
+ * @return {IncomingFaceId} The first IncomingFaceId header field, or null if
+ * not found.
+ */
+IncomingFaceId.getFirstHeader = function(lpPacket)
+{
+  for (var i = 0; i < lpPacket.countHeaderFields(); ++i) {
+    var field = lpPacket.getHeaderField(i);
+    if (field instanceof IncomingFaceId)
+      return field;
+  }
+
+  return null;
+};
+/**
+ * Copyright (C) 2016 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: From ndn-cxx packet.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/packet.hpp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var Blob = require('../util/blob.js').Blob;
+
+/**
+ * An LpPacket represents an NDNLPv2 packet including header fields an an
+ * optional fragment. This is an internal class which the application normally
+ * would not use.
+ * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
+ * @constructor
+ */
+var LpPacket = function LpPacket()
+{
+  this.headerFields_ = [];
+  this.fragmentWireEncoding_ = new Blob();
+};
+
+exports.LpPacket = LpPacket;
+
+/**
+ * Get the fragment wire encoding.
+ * @return {Blob} The wire encoding, or an isNull Blob if not specified.
+ */
+LpPacket.prototype.getFragmentWireEncoding = function()
+{
+  return this.fragmentWireEncoding_;
+};
+
+/**
+ * Get the number of header fields. This does not include the fragment.
+ * @return {number} The number of header fields.
+ */
+LpPacket.prototype.countHeaderFields = function()
+{ 
+  return this.headerFields_.length;
+};
+
+/**
+ * Get the header field at the given index.
+ * @param {number} index The index, starting from 0. It is an error if index is
+ * greater to or equal to countHeaderFields().
+ * @return {object} The header field at the index.
+ */
+LpPacket.prototype.getHeaderField = function(index)
+{ 
+  return this.headerFields_[index];
+};
+
+/**
+ * Remove all header fields and set the fragment to an isNull Blob.
+ */
+LpPacket.prototype.clear = function()
+{
+  this.headerFields_ = [];
+  this.fragmentWireEncoding_ = new Blob();
+};
+
+/**
+ * Set the fragment wire encoding.
+ * @param {Blob} fragmentWireEncoding The fragment wire encoding or an isNull
+ * Blob if not specified.
+ */
+LpPacket.prototype.setFragmentWireEncoding = function(fragmentWireEncoding)
+{
+  this.fragmentWireEncoding_ =
+    typeof fragmentWireEncoding === 'object' && fragmentWireEncoding instanceof Blob ?
+      fragmentWireEncoding : new Blob(fragmentWireEncoding);
+};
+
+/**
+ * Add a header field. To add the fragment, use setFragmentWireEncoding().
+ * @param {object} headerField The header field to add.
+ */
+LpPacket.prototype.addHeaderField = function(headerField)
+{ 
+  this.headerFields_.push(headerField);
+};
+/**
+ * This class represents the top-level object for communicating with an NDN host.
+ * Copyright (C) 2013-2016 Regents of the University of California.
+ * @author: Meki Cherkaoui, Jeff Thompson <jefft0@remap.ucla.edu>, Wentao Shang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * A copy of the GNU Lesser General Public License is in the file COPYING.
+ */
+
+/** @ignore */
+var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
+var Name = require('./name.js').Name; /** @ignore */
+var Interest = require('./interest.js').Interest; /** @ignore */
+var Data = require('./data.js').Data; /** @ignore */
+var ControlParameters = require('./control-parameters.js').ControlParameters; /** @ignore */
+var ControlResponse = require('./control-response.js').ControlResponse; /** @ignore */
+var InterestFilter = require('./interest-filter.js').InterestFilter; /** @ignore */
+var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
+var TlvWireFormat = require('./encoding/tlv-wire-format.js').TlvWireFormat; /** @ignore */
+var Tlv = require('./encoding/tlv/tlv.js').Tlv; /** @ignore */
+var TlvDecoder = require('./encoding/tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
+var ForwardingFlags = require('./forwarding-flags.js').ForwardingFlags; /** @ignore */
+var Transport = require('./transport/transport.js').Transport; /** @ignore */
+var TcpTransport = require('./transport/tcp-transport.js').TcpTransport; /** @ignore */
+var UnixTransport = require('./transport/unix-transport.js').UnixTransport; /** @ignore */
+var CommandInterestGenerator = require('./util/command-interest-generator.js').CommandInterestGenerator; /** @ignore */
+var Blob = require('./util/blob.js').Blob; /** @ignore */
+var NdnCommon = require('./util/ndn-common.js').NdnCommon; /** @ignore */
+var NetworkNack = require('./network-nack.js').NetworkNack; /** @ignore */
+var LpPacket = require('./lp/lp-packet.js').LpPacket; /** @ignore */
+var InterestFilterTable = require('./impl/interest-filter-table.js').InterestFilterTable; /** @ignore */
+var PendingInterestTable = require('./impl/pending-interest-table.js').PendingInterestTable; /** @ignore */
+var RegisteredPrefixTable = require('./impl/registered-prefix-table.js').RegisteredPrefixTable; /** @ignore */
+var fs = require('fs'); /** @ignore */
+var LOG = require('./log.js').Log.LOG;
+
+/**
+ * Create a new Face with the given settings.
+ * This throws an exception if Face.supported is false.
+ * There are two forms of the constructor.  The first form takes the transport and connectionInfo:
+ * Face(transport, connectionInfo).  The second form takes an optional settings object:
+ * Face([settings]).
+ * @constructor
+ * @param {Transport} transport An object of a subclass of Transport to use for
+ * communication.
+ * @param {Transport.ConnectionInfo} connectionInfo This must be a ConnectionInfo
+ * from the same subclass of Transport as transport. If omitted and transport is
+ * a new UnixTransport() then attempt to create to the Unix socket for the local
+ * forwarder.
+ * @param {Object} settings (optional) An associative array with the following defaults:
+ * {
+ *   getTransport: function() { return new WebSocketTransport(); }, // If in the browser.
+ *              OR function() { return new TcpTransport(); },       // If in Node.js.
+ *              // If getTransport creates a UnixTransport and connectionInfo is null,
+ *              // then connect to the local forwarder's Unix socket.
+ *   getConnectionInfo: transport.defaultGetConnectionInfo, // a function, on each call it returns a new Transport.ConnectionInfo or null if there are no more hosts.
+ *                                                          // If connectionInfo or host is not null, getConnectionInfo is ignored.
+ *   connectionInfo: null,
+ *   host: null, // If null and connectionInfo is null, use getConnectionInfo when connecting.
+ *               // However, if connectionInfo is not null, use it instead.
+ *   port: 9696, // If in the browser.
+ *      OR 6363, // If in Node.js.
+ *               // However, if connectionInfo is not null, use it instead.
+ *   onopen: function() { if (LOG > 3) console.log("NDN connection established."); },
+ *   onclose: function() { if (LOG > 3) console.log("NDN connection closed."); },
+ * }
+ */
+var Face = function Face(transportOrSettings, connectionInfo)
+{
+  if (!Face.supported)
+    throw new Error("The necessary JavaScript support is not available on this platform.");
+
+  var settings;
+  if (typeof transportOrSettings == 'object' && transportOrSettings instanceof Transport) {
+    this.getConnectionInfo = null;
+    this.transport = transportOrSettings;
+    this.connectionInfo = (connectionInfo || null);
+    // Use defaults for other settings.
+    settings = {};
+
+    if (this.connectionInfo == null) {
+      if (this.transport && this.transport.__proto__ &&
+          this.transport.__proto__.name == "UnixTransport") {
+        // Try to create the default connectionInfo for UnixTransport.
+        var filePath = Face.getUnixSocketFilePathForLocalhost();
+        if (filePath != null)
+          this.connectionInfo = new UnixTransport.ConnectionInfo(filePath);
+        else
+          console.log
+            ("Face constructor: Cannot determine the default Unix socket file path for UnixTransport");
+        if (LOG > 0)
+          console.log("Using " + this.connectionInfo.toString());
+      }
+    }
+  }
+  else {
+    settings = (transportOrSettings || {});
+    // For the browser, browserify-tcp-transport.js replaces TcpTransport with WebSocketTransport.
+    var getTransport = (settings.getTransport || function() { return new TcpTransport(); });
+    this.transport = getTransport();
+    this.getConnectionInfo = (settings.getConnectionInfo || this.transport.defaultGetConnectionInfo);
+
+    this.connectionInfo = (settings.connectionInfo || null);
+    if (this.connectionInfo == null) {
+      var host = (settings.host !== undefined ? settings.host : null);
+
+      if (this.transport && this.transport.__proto__ &&
+          this.transport.__proto__.name == "UnixTransport") {
+        // We are using UnixTransport on Node.js. There is no IP-style host and port.
+        if (host != null)
+          // Assume the host is the local Unix socket path.
+          this.connectionInfo = new UnixTransport.ConnectionInfo(host);
+        else {
+          // If getConnectionInfo is not null, it will be used instead so no
+          // need to set this.connectionInfo.
+          if (this.getConnectionInfo == null) {
+            var filePath = Face.getUnixSocketFilePathForLocalhost();
+            if (filePath != null)
+              this.connectionInfo = new UnixTransport.ConnectionInfo(filePath);
+            else
+              console.log
+                ("Face constructor: Cannot determine the default Unix socket file path for UnixTransport");
+          }
+        }
+      }
+      else {
+        if (host != null) {
+          if (typeof WebSocketTransport != 'undefined')
+            this.connectionInfo = new WebSocketTransport.ConnectionInfo
+              (host, settings.port || 9696);
+          else
+            this.connectionInfo = new TcpTransport.ConnectionInfo
+              (host, settings.port || 6363);
+        }
+      }
+    }
+  }
+
+  // Deprecated: Set this.host and this.port for backwards compatibility.
+  if (this.connectionInfo == null) {
+    this.host = null;
+    this.host = null;
+  }
+  else {
+    this.host = this.connectionInfo.host;
+    this.host = this.connectionInfo.port;
+  }
+
+  this.readyStatus = Face.UNOPEN;
+
+  // Event handler
+  this.onopen = (settings.onopen || function() { if (LOG > 3) console.log("Face connection established."); });
+  this.onclose = (settings.onclose || function() { if (LOG > 3) console.log("Face connection closed."); });
+  // This is used by reconnectAndExpressInterest.
+  this.onConnectedCallbacks = [];
+  this.commandKeyChain = null;
+  this.commandCertificateName = new Name();
+  this.commandInterestGenerator = new CommandInterestGenerator();
+  this.timeoutPrefix = new Name("/local/timeout");
+
+  this.pendingInterestTable_ = new PendingInterestTable();
+  this.interestFilterTable_ = new InterestFilterTable();
+  this.registeredPrefixTable_ = new RegisteredPrefixTable(this.interestFilterTable_);
+  this.lastEntryId = 0;
+};
+
+exports.Face = Face;
+
+Face.UNOPEN = 0;  // the Face is created but not opened yet
+Face.OPEN_REQUESTED = 1;  // requested to connect but onopen is not called.
+Face.OPENED = 2;  // connection to the forwarder opened
+Face.CLOSED = 3;  // connection to the forwarder closed
+
+TcpTransport.importFace(Face);
+
+/**
+ * If the forwarder's Unix socket file path exists, then return the file path.
+ * Otherwise return an empty string. This uses Node.js blocking file system
+ * utilities.
+ * @return The Unix socket file path to use, or an empty string.
+ */
+Face.getUnixSocketFilePathForLocalhost = function()
+{
+  var filePath = "/var/run/nfd.sock";
+  if (fs.existsSync(filePath))
+    return filePath;
+  else {
+    filePath = "/tmp/.ndnd.sock";
+    if (fs.existsSync(filePath))
+      return filePath;
+    else
+      return "";
+  }
+}
+
+/**
+ * Return true if necessary JavaScript support is available, else log an error and return false.
+ */
+Face.getSupported = function()
+{
+  try {
+    var dummy = new Buffer(1).slice(0, 1);
+  }
+  catch (ex) {
+    console.log("NDN not available: Buffer not supported. " + ex);
+    return false;
+  }
+
+  return true;
+};
+
+Face.supported = Face.getSupported();
+
+Face.prototype.createRoute = function(hostOrConnectionInfo, port)
+{
+  if (hostOrConnectionInfo instanceof Transport.ConnectionInfo)
+    this.connectionInfo = hostOrConnectionInfo;
+  else
+    this.connectionInfo = new TcpTransport.ConnectionInfo(hostOrConnectionInfo, port);
+
+  // Deprecated: Set this.host and this.port for backwards compatibility.
+  this.host = this.connectionInfo.host;
+  this.host = this.connectionInfo.port;
+};
+
+Face.prototype.close = function()
+{
+  if (this.readyStatus != Face.OPENED)
+    return;
+
+  this.readyStatus = Face.CLOSED;
+  this.transport.close();
+};
+
+/**
+ * An internal method to get the next unique entry ID for the pending interest
+ * table, interest filter table, etc. Most entry IDs are for the pending
+ * interest table (there usually are not many interest filter table entries) so
+ * we use a common pool to only have to have one method which is called by Face.
+ *
+ * @return {number} The next entry ID.
+ */
+Face.prototype.getNextEntryId = function()
+{
+  return ++this.lastEntryId;
+};
+
+/**
+ * Return a function that selects a host at random from hostList and returns
+ * makeConnectionInfo(host, port), and if no more hosts remain, return null.
+ * @param {Array<string>} hostList An array of host names.
+ * @param {number} port The port for the connection.
+ * @param {function} makeConnectionInfo This calls makeConnectionInfo(host, port)
+ * to make the Transport.ConnectionInfo. For example:
+ * function(host, port) { return new TcpTransport.ConnectionInfo(host, port); }
+ * @return {function} A function which returns a Transport.ConnectionInfo.
+ */
+Face.makeShuffledHostGetConnectionInfo = function(hostList, port, makeConnectionInfo)
+{
+  // Make a copy.
+  hostList = hostList.slice(0, hostList.length);
+  DataUtils.shuffle(hostList);
+
+  return function() {
+    if (hostList.length == 0)
+      return null;
+
+    return makeConnectionInfo(hostList.splice(0, 1)[0], port);
+  };
+};
+
+/**
+ * Send the interest through the transport, read the entire response and call 
+ * onData, onTimeout or onNetworkNack as described below.
+ * There are two forms of expressInterest. The first form takes the exact
+ * interest (including lifetime):
+ * expressInterest(interest, onData [, onTimeout] [, onNetworkNack] [, wireFormat]).
+ * The second form creates the interest from a name and optional interest template:
+ * expressInterest(name [, template], onData [, onTimeout] [, onNetworkNack] [, wireFormat]).
+ * @param {Interest} interest The Interest to send which includes the interest lifetime for the timeout.
+ * @param {function} onData When a matching data packet is received, this calls onData(interest, data) where
+ * interest is the interest given to expressInterest and data is the received
+ * Data object. NOTE: You must not change the interest object - if you need to
+ * change it then make a copy.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onTimeout (optional) If the interest times out according to the interest lifetime,
+ *   this calls onTimeout(interest) where:
+ *   interest is the interest given to expressInterest.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onNetworkNack (optional) When a network Nack packet for the
+ * interest is received and onNetworkNack is not null, this calls
+ * onNetworkNack(interest, networkNack) and does not call onTimeout. interest is
+ * the sent Interest and networkNack is the received NetworkNack. If
+ * onNetworkNack is supplied, then onTimeout must be supplied too. However, if a
+ * network Nack is received and onNetworkNack is null, do nothing and wait for
+ * the interest to time out. (Therefore, an application which does not yet
+ * process a network Nack reason treats a Nack the same as a timeout.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {Name} name The Name for the interest. (only used for the second form of expressInterest).
+ * @param {Interest} template (optional) If not omitted, copy the interest selectors from this Interest.
+ * If omitted, use a default interest lifetime. (only used for the second form of expressInterest).
+ * @param {WireFormat} (optional) A WireFormat object used to encode the message.
+ * If omitted, use WireFormat.getDefaultWireFormat().
+ * @return {number} The pending interest ID which can be used with removePendingInterest.
+ * @throws Error If the encoded interest size exceeds Face.getMaxNdnPacketSize().
+ */
+Face.prototype.expressInterest = function
+  (interestOrName, arg2, arg3, arg4, arg5, arg6)
+{
+  var interest;
+  if (typeof interestOrName === 'object' && interestOrName instanceof Interest)
+    // Just use a copy of the interest.
+    interest = new Interest(interestOrName);
+  else {
+    // The first argument is a name. Make the interest from the name and possible template.
+    if (arg2 && typeof arg2 === 'object' && arg2 instanceof Interest) {
+      var template = arg2;
+      // Copy the template.
+      interest = new Interest(template);
+      interest.setName(interestOrName);
+
+      // Shift the remaining args to be processed below.
+      arg2 = arg3;
+      arg3 = arg4;
+      arg4 = arg5;
+      arg5 = arg6;
+    }
+    else {
+      // No template.
+      interest = new Interest(interestOrName);
+      interest.setInterestLifetimeMilliseconds(4000);   // default interest timeout
+    }
+  }
+
+  var onData = arg2;
+  var onTimeout;
+  var onNetworkNack;
+  var wireFormat;
+  // arg3,       arg4,          arg5 may be:
+  // OnTimeout,  OnNetworkNack, WireFormat
+  // OnTimeout,  OnNetworkNack, null
+  // OnTimeout,  WireFormat,    null
+  // OnTimeout,  null,          null
+  // WireFormat, null,          null
+  // null,       null,          null
+  if (typeof arg3 === "function")
+    onTimeout = arg3;
+  else
+    onTimeout = function() {};
+
+  if (typeof arg4 === "function")
+    onNetworkNack = arg4;
+  else
+    onNetworkNack = null;
+
+  if (arg3 instanceof WireFormat)
+    wireFormat = arg3;
+  else if (arg4 instanceof WireFormat)
+    wireFormat = arg4;
+  else if (arg5 instanceof WireFormat)
+    wireFormat = arg5;
+  else
+    wireFormat = WireFormat.getDefaultWireFormat();
+
+  var pendingInterestId = this.getNextEntryId();
+
+  // Set the nonce in our copy of the Interest so it is saved in the PIT.
+  interest.setNonce(Face.nonceTemplate_);
+  interest.refreshNonce();
+
+  if (this.connectionInfo == null) {
+    if (this.getConnectionInfo == null)
+      console.log('ERROR: connectionInfo is NOT SET');
+    else {
+      var thisFace = this;
+      this.connectAndExecute(function() {
+        thisFace.reconnectAndExpressInterest
+          (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
+           wireFormat);
+      });
+    }
+  }
+  else
+    this.reconnectAndExpressInterest
+      (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat);
+
+  return pendingInterestId;
+};
+
+/**
  * If the host and port are different than the ones in this.transport, then call
  *   this.transport.connect to change the connection (or connect for the first time).
  * Then call expressInterestHelper.
  */
-NDN.prototype.reconnectAndExpressInterest = function(interest, closure) {
-    if (this.transport.connectedHost != this.host || this.transport.connectedPort != this.port) {
-        var thisNDN = this;
-        this.transport.connect(thisNDN, function() { thisNDN.expressInterestHelper(interest, closure); });
-    }
-    else
-        this.expressInterestHelper(interest, closure);
-};
+Face.prototype.reconnectAndExpressInterest = function
+  (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat)
+{
+  var thisFace = this;
+  if (!this.connectionInfo.equals(this.transport.connectionInfo) || this.readyStatus === Face.UNOPEN) {
+    this.readyStatus = Face.OPEN_REQUESTED;
+    this.onConnectedCallbacks.push
+      (function() {
+        thisFace.expressInterestHelper
+          (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
+           wireFormat);
+      });
 
-/*
- * Do the work of reconnectAndExpressInterest once we know we are connected.  Set the PITTable and call
- *   this.transport.send to send the interest.
- */
-NDN.prototype.expressInterestHelper = function(interest, closure) {
-    var binaryInterest = encodeToBinaryInterest(interest);
-    var thisNDN = this;
-	//TODO: check local content store first
-	if (closure != null) {
-		var pitEntry = new PITEntry(interest, closure);
-        // TODO: This needs to be a single thread-safe transaction on a global object.
-		NDN.PITTable.push(pitEntry);
-		closure.pitEntry = pitEntry;
+    this.transport.connect
+     (this.connectionInfo, this,
+      function() {
+        thisFace.readyStatus = Face.OPENED;
 
-        // Set interest timer.
-        var timeoutMilliseconds = (interest.interestLifetime || 4000);
-        var timeoutCallback = function() {
-			if (LOG > 3) console.log("Interest time out: " + interest.name.to_uri());
-
-			// Remove PIT entry from NDN.PITTable, even if we add it again later to re-express
-            //   the interest because we don't want to match it in the mean time.
-            // TODO: Make this a thread-safe operation on the global PITTable.
-			var index = NDN.PITTable.indexOf(pitEntry);
-			if (index >= 0)
-	            NDN.PITTable.splice(index, 1);
-
-			// Raise closure callback
-			if (closure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,
-                  new UpcallInfo(thisNDN, interest, 0, null)) == Closure.RESULT_REEXPRESS) {
-			    if (LOG > 3) console.log("Re-express interest: " + interest.name.to_uri());
-                pitEntry.timerID = setTimeout(timeoutCallback, timeoutMilliseconds);
-                NDN.PITTable.push(pitEntry);
-                thisNDN.transport.send(binaryInterest);
-            }
-		};
-		pitEntry.timerID = setTimeout(timeoutCallback, timeoutMilliseconds);
-	}
-
-	this.transport.send(binaryInterest);
-};
-
-NDN.prototype.registerPrefix = function(name, closure, flag) {
-    var thisNDN = this;
-    var onConnected = function() {
-    	if (thisNDN.ndndid == null) {
-            // Fetch ndndid first, then register.
-            var interest = new Interest(NDN.ndndIdFetcher);
-    		interest.interestLifetime = 4000; // milliseconds
-            if (LOG>3) console.log('Expressing interest for ndndid from ndnd.');
-            thisNDN.reconnectAndExpressInterest
-               (interest, new NDN.FetchNdndidClosure(thisNDN, name, closure, flag));
+        // Execute each action requested while the connection was opening.
+        while (thisFace.onConnectedCallbacks.length > 0) {
+          try {
+            thisFace.onConnectedCallbacks.shift()();
+          } catch (ex) {
+            console.log("Face.reconnectAndExpressInterest: ignoring exception from onConnectedCallbacks: " + ex);
+          }
         }
-        else
-            thisNDN.registerPrefixHelper(name, closure, flag);
-    };
 
-	if (this.host == null || this.port == null) {
-        if (this.getHostAndPort == null)
-            console.log('ERROR: host OR port NOT SET');
-        else
-            this.connectAndExecute(onConnected);
-    }
+        if (thisFace.onopen)
+          // Call Face.onopen after success
+          thisFace.onopen();
+      },
+      function() { thisFace.closeByTransport(); });
+  }
+  else {
+    if (this.readyStatus === Face.OPEN_REQUESTED)
+      // The connection is still opening, so add to the interests to express.
+      this.onConnectedCallbacks.push
+        (function() {
+          thisFace.expressInterestHelper
+            (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
+             wireFormat);
+        });
+    else if (this.readyStatus === Face.OPENED)
+      this.expressInterestHelper
+        (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
+         wireFormat);
     else
-        onConnected();
+      throw new Error
+        ("reconnectAndExpressInterest: unexpected connection is not opened");
+  }
 };
 
-/*
- * This is a closure to receive the ContentObject for NDN.ndndIdFetcher and call
- *   registerPrefixHelper(name, callerClosure, flag).
+/**
+ * Do the work of reconnectAndExpressInterest once we know we are connected.
+ * Add the PendingInterest and call this.transport.send to send the interest.
  */
-NDN.FetchNdndidClosure = function FetchNdndidClosure(ndn, name, callerClosure, flag) {
-    // Inherit from Closure.
-    Closure.call(this);
+Face.prototype.expressInterestHelper = function
+  (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat)
+{
+  if (this.pendingInterestTable_.add
+      (pendingInterestId, interest, onData, onTimeout, onNetworkNack) == null)
+    // removePendingInterest was already called with the pendingInterestId.
+    return;
 
-    this.ndn = ndn;
-    this.name = name;
-    this.callerClosure = callerClosure;
-    this.flag = flag;
+  // Special case: For timeoutPrefix we don't actually send the interest.
+  if (!this.timeoutPrefix.match(interest.getName())) {
+    var binaryInterest = interest.wireEncode(wireFormat);
+    if (binaryInterest.size() > Face.getMaxNdnPacketSize())
+      throw new Error
+        ("The encoded interest size exceeds the maximum limit getMaxNdnPacketSize()");
+
+    this.transport.send(binaryInterest.buf());
+  }
 };
 
-NDN.FetchNdndidClosure.prototype.upcall = function(kind, upcallInfo) {
-    if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
-        console.log("Timeout while requesting the ndndid.  Cannot registerPrefix for " +
-            this.name.to_uri() + " .");
-        return Closure.RESULT_OK;
-    }
-    if (!(kind == Closure.UPCALL_CONTENT ||
-          kind == Closure.UPCALL_CONTENT_UNVERIFIED))
-        // The upcall is not for us.
-        return Closure.RESULT_ERR;
+/**
+ * Remove the pending interest entry with the pendingInterestId from the pending
+ * interest table. This does not affect another pending interest with a
+ * different pendingInterestId, even if it has the same interest name.
+ * If there is no entry with the pendingInterestId, do nothing.
+ * @param {number} pendingInterestId The ID returned from expressInterest.
+ */
+Face.prototype.removePendingInterest = function(pendingInterestId)
+{
+  this.pendingInterestTable_.removePendingInterest(pendingInterestId);
+};
 
-    var co = upcallInfo.contentObject;
-    if (!co.signedInfo || !co.signedInfo.publisher
-		|| !co.signedInfo.publisher.publisherPublicKeyDigest)
-        console.log
-          ("ContentObject doesn't have a publisherPublicKeyDigest. Cannot set ndndid and registerPrefix for "
-           + this.name.to_uri() + " .");
+/**
+ * Set the KeyChain and certificate name used to sign command interests (e.g.
+ * for registerPrefix).
+ * @param {KeyChain} keyChain The KeyChain object for signing interests, which
+ * must remain valid for the life of this Face. You must create the KeyChain
+ * object and pass it in. You can create a default KeyChain for your system with
+ * the default KeyChain constructor.
+ * @param {Name} certificateName The certificate name for signing interests.
+ * This makes a copy of the Name. You can get the default certificate name with
+ * keyChain.getDefaultCertificateName() .
+ */
+Face.prototype.setCommandSigningInfo = function(keyChain, certificateName)
+{
+  this.commandKeyChain = keyChain;
+  this.commandCertificateName = new Name(certificateName);
+};
+
+/**
+ * Set the certificate name used to sign command interest (e.g. for
+ * registerPrefix), using the KeyChain that was set with setCommandSigningInfo.
+ * @param {Name} certificateName The certificate name for signing interest. This
+ * makes a copy of the Name.
+ */
+Face.prototype.setCommandCertificateName = function(certificateName)
+{
+  this.commandCertificateName = new Name(certificateName);
+};
+
+/**
+ * Append a timestamp component and a random value component to interest's name.
+ * Then use the keyChain and certificateName from setCommandSigningInfo to sign
+ * the interest. If the interest lifetime is not set, this sets it.
+ * @note This method is an experimental feature. See the API docs for more
+ * detail at
+ * http://named-data.net/doc/ndn-ccl-api/face.html#face-makecommandinterest-method .
+ * @param {Interest} interest The interest whose name is appended with
+ * components.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the SignatureInfo and to encode the interest name for signing.  If omitted,
+ * use WireFormat.getDefaultWireFormat().
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * If omitted, block until complete. (Some crypto/database libraries only use a
+ * callback, so onComplete is required to use these.)
+ */
+Face.prototype.makeCommandInterest = function(interest, wireFormat, onComplete)
+{
+  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
+  wireFormat = (typeof wireFormat === "function" || !wireFormat) ?
+                 WireFormat.getDefaultWireFormat() : wireFormat;
+  this.nodeMakeCommandInterest
+    (interest, this.commandKeyChain, this.commandCertificateName, wireFormat,
+     onComplete);
+};
+
+/**
+ * Append a timestamp component and a random value component to interest's name.
+ * Then use the keyChain and certificateName from setCommandSigningInfo to sign
+ * the interest. If the interest lifetime is not set, this sets it.
+ * @param {Interest} interest The interest whose name is appended with
+ * components.
+ * @param {KeyChain} keyChain The KeyChain for calling sign.
+ * @param {Name} certificateName The certificate name of the key to use for
+ * signing.
+ * @param {WireFormat} wireFormat A WireFormat object used to encode
+ * the SignatureInfo and to encode the interest name for signing.
+ * @param {function} onComplete (optional) This calls onComplete() when complete.
+ * (Some crypto/database libraries only use a callback, so onComplete is
+ * required to use these.)
+ */
+Face.prototype.nodeMakeCommandInterest = function
+  (interest, keyChain, certificateName, wireFormat, onComplete)
+{
+  this.commandInterestGenerator.generate
+    (interest, keyChain, certificateName, wireFormat, onComplete);
+};
+
+/**
+ * Register prefix with the connected NDN hub and call onInterest when a
+ * matching interest is received. To register a prefix with NFD, you must
+ * first call setCommandSigningInfo.
+ * This uses the form:
+ * @param {Name} prefix The Name prefix.
+ * @param {function} onInterest (optional) If not null, this creates an interest
+ * filter from prefix so that when an Interest is received which matches the
+ * filter, this calls
+ * onInterest(prefix, interest, face, interestFilterId, filter).
+ * NOTE: You must not change the prefix object - if you need to change it then
+ * make a copy. If onInterest is null, it is ignored and you must call
+ * setInterestFilter.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onRegisterFailed If register prefix fails for any reason,
+ * this calls onRegisterFailed(prefix) where:
+ *   prefix is the prefix given to registerPrefix.
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {function} onRegisterSuccess (optional) When this receives a success
+ * message, this calls onRegisterSuccess(prefix, registeredPrefixId) where
+ * prefix is the prefix given to registerPrefix and registeredPrefixId is
+ * the value retured by registerPrefix. If onRegisterSuccess is null or omitted,
+ * this does not use it. (The onRegisterSuccess parameter comes after
+ * onRegisterFailed because it can be null or omitted, unlike onRegisterFailed.)
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
+ * @param {ForwardingFlags} flags (optional) The ForwardingFlags object for
+ * finer control of which interests are forward to the application. If omitted,
+ * use the default flags defined by the default ForwardingFlags constructor.
+ * @return {number} The registered prefix ID which can be used with
+ * removeRegisteredPrefix.
+ */
+Face.prototype.registerPrefix = function
+  (prefix, onInterest, onRegisterFailed, onRegisterSuccess, flags, wireFormat)
+{
+  // Temporarlity reassign to resolve the different overloaded forms.
+  var arg4 = onRegisterSuccess;
+  var arg5 = flags;
+  var arg6 = wireFormat;
+  // arg4, arg5, arg6 may be:
+  // OnRegisterSuccess, ForwardingFlags, WireFormat
+  // OnRegisterSuccess, ForwardingFlags, null
+  // OnRegisterSuccess, WireFormat,      null
+  // OnRegisterSuccess, null,            null
+  // ForwardingFlags,   WireFormat,      null
+  // ForwardingFlags,   null,            null
+  // WireFormat,        null,            null
+  // null,              null,            null
+  if (typeof arg4 === "function")
+    onRegisterSuccess = arg4;
+  else
+    onRegisterSuccess = null;
+
+  if (arg4 instanceof ForwardingFlags)
+    flags = arg4;
+  else if (arg5 instanceof ForwardingFlags)
+    flags = arg5;
+  else
+    flags = new ForwardingFlags();
+
+  if (arg4 instanceof WireFormat)
+    wireFormat = arg4;
+  else if (arg5 instanceof WireFormat)
+    wireFormat = arg5;
+  else if (arg6 instanceof WireFormat)
+    wireFormat = arg6;
+  else
+    wireFormat = WireFormat.getDefaultWireFormat();
+
+  if (!onRegisterFailed)
+    onRegisterFailed = function() {};
+
+  var registeredPrefixId = this.getNextEntryId();
+  var thisFace = this;
+  var onConnected = function() {
+    thisFace.nfdRegisterPrefix
+      (registeredPrefixId, prefix, onInterest, flags, onRegisterFailed,
+       onRegisterSuccess, thisFace.commandKeyChain,
+       thisFace.commandCertificateName, wireFormat);
+  };
+
+  if (this.connectionInfo == null) {
+    if (this.getConnectionInfo == null)
+      console.log('ERROR: connectionInfo is NOT SET');
+    else
+      this.connectAndExecute(onConnected);
+  }
+  else
+    onConnected();
+
+  return registeredPrefixId;
+};
+
+/**
+ * Get the practical limit of the size of a network-layer packet. If a packet
+ * is larger than this, the library or application MAY drop it.
+ * @return {number} The maximum NDN packet size.
+ */
+Face.getMaxNdnPacketSize = function() { return NdnCommon.MAX_NDN_PACKET_SIZE; };
+
+/**
+ * A RegisterResponse has onData to receive the response Data packet from the
+ * register prefix interest sent to the connected NDN hub. If this gets a bad
+ * response or onTimeout is called, then call onRegisterFailed.
+ */
+Face.RegisterResponse = function RegisterResponse
+  (prefix, onRegisterFailed, onRegisterSuccess, registeredPrefixId, parent,
+   onInterest)
+{
+  this.prefix = prefix;
+  this.onRegisterFailed = onRegisterFailed;
+  this.onRegisterSuccess= onRegisterSuccess;
+  this.registeredPrefixId = registeredPrefixId;
+  this.parent = parent;
+  this.onInterest = onInterest;
+};
+
+Face.RegisterResponse.prototype.onData = function(interest, responseData)
+{
+  // Decode responseData.getContent() and check for a success code.
+  var controlResponse = new ControlResponse();
+  try {
+    controlResponse.wireDecode(responseData.getContent(), TlvWireFormat.get());
+  }
+  catch (e) {
+    // Error decoding the ControlResponse.
+    if (LOG > 0)
+      console.log("Register prefix failed: Error decoding the NFD response: " + e);
+    if (this.onRegisterFailed) {
+      try {
+        this.onRegisterFailed(this.prefix);
+      } catch (ex) {
+        console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+    return;
+  }
+
+  // Status code 200 is "OK".
+  if (controlResponse.getStatusCode() != 200) {
+    if (LOG > 0)
+      console.log("Register prefix failed: Expected NFD status code 200, got: " +
+                  controlResponse.getStatusCode());
+    if (this.onRegisterFailed) {
+      try {
+        this.onRegisterFailed(this.prefix);
+      } catch (ex) {
+        console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+    return;
+  }
+
+  // Success, so we can add to the registered prefix table.
+  if (this.registeredPrefixId != 0) {
+    var interestFilterId = 0;
+    if (this.onInterest != null)
+      // registerPrefix was called with the "combined" form that includes the
+      // callback, so add an InterestFilterEntry.
+      interestFilterId = this.parent.setInterestFilter
+        (new InterestFilter(this.prefix), this.onInterest);
+
+    if (!this.parent.registeredPrefixTable_.add
+        (this.registeredPrefixId, this.prefix, interestFilterId)) {
+      // removeRegisteredPrefix was already called with the registeredPrefixId.
+      if (interestFilterId > 0)
+        // Remove the related interest filter we just added.
+        this.parent.unsetInterestFilter(interestFilterId);
+
+      return;
+    }
+  }
+
+  if (LOG > 2)
+    console.log("Register prefix succeeded with the NFD forwarder for prefix " +
+                this.prefix.toUri());
+  if (this.onRegisterSuccess != null) {
+    try {
+      this.onRegisterSuccess(this.prefix, this.registeredPrefixId);
+    } catch (ex) {
+      console.log("Error in onRegisterSuccess: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * We timed out waiting for the response.
+ */
+Face.RegisterResponse.prototype.onTimeout = function(interest)
+{
+  if (LOG > 2)
+    console.log("Timeout for NFD register prefix command.");
+  if (this.onRegisterFailed) {
+    try {
+      this.onRegisterFailed(this.prefix);
+    } catch (ex) {
+      console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+    }
+  }
+};
+
+/**
+ * Do the work of registerPrefix to register with NFD.
+ * @param {number} registeredPrefixId The Face.getNextEntryId() which
+ * registerPrefix got so it could return it to the caller. If this is 0, then
+ * don't add to registeredPrefixTable (assuming it has already been done).
+ * @param {Name} prefix
+ * @param {function} onInterest
+ * @param {ForwardingFlags} flags
+ * @param {function} onRegisterFailed
+ * @param {function} onRegisterSuccess
+ * @param {KeyChain} commandKeyChain
+ * @param {Name} commandCertificateName
+ * @param {WireFormat} wireFormat
+ */
+Face.prototype.nfdRegisterPrefix = function
+  (registeredPrefixId, prefix, onInterest, flags, onRegisterFailed,
+   onRegisterSuccess, commandKeyChain, commandCertificateName, wireFormat)
+{
+  if (commandKeyChain == null)
+      throw new Error
+        ("registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo.");
+  if (commandCertificateName.size() == 0)
+      throw new Error
+        ("registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo.");
+
+  var controlParameters = new ControlParameters();
+  controlParameters.setName(prefix);
+  controlParameters.setForwardingFlags(flags);
+
+  // Make the callback for this.isLocal().
+  var thisFace = this;
+  var onIsLocalResult = function(isLocal) {
+    var commandInterest = new Interest();
+    if (isLocal) {
+      commandInterest.setName(new Name("/localhost/nfd/rib/register"));
+      // The interest is answered by the local host, so set a short timeout.
+      commandInterest.setInterestLifetimeMilliseconds(2000.0);
+    }
     else {
-		if (LOG>3) console.log('Got ndndid from ndnd.');
-		this.ndn.ndndid = co.signedInfo.publisher.publisherPublicKeyDigest;
-		if (LOG>3) console.log(this.ndn.ndndid);
+      commandInterest.setName(new Name("/localhop/nfd/rib/register"));
+      // The host is remote, so set a longer timeout.
+      commandInterest.setInterestLifetimeMilliseconds(4000.0);
+    }
+    // NFD only accepts TlvWireFormat packets.
+    commandInterest.getName().append
+      (controlParameters.wireEncode(TlvWireFormat.get()));
+    thisFace.nodeMakeCommandInterest
+      (commandInterest, commandKeyChain, commandCertificateName,
+       TlvWireFormat.get(), function() {
+      // Send the registration interest.
+      var response = new Face.RegisterResponse
+         (prefix, onRegisterFailed, onRegisterSuccess, registeredPrefixId,
+          thisFace, onInterest);
+      thisFace.reconnectAndExpressInterest
+        (null, commandInterest, response.onData.bind(response),
+         response.onTimeout.bind(response), null, wireFormat);
+    });
+  };
 
-        this.ndn.registerPrefixHelper(this.name, this.callerClosure, this.flag);
-	}
-
-    return Closure.RESULT_OK;
+  this.isLocal
+    (onIsLocalResult,
+     function(message) {
+       if (LOG > 0)
+         console.log("Error in Transport.isLocal: " + message);
+       if (onRegisterFailed) {
+         try {
+           onRegisterFailed(prefix);
+         } catch (ex) {
+           console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
+         }
+       }
+     });
 };
 
-/*
- * Do the work of registerPrefix once we know we are connected with a ndndid.
+/**
+ * Remove the registered prefix entry with the registeredPrefixId from the
+ * registered prefix table. This does not affect another registered prefix with
+ * a different registeredPrefixId, even if it has the same prefix name. If an
+ * interest filter was automatically created by registerPrefix, also remove it.
+ * If there is no entry with the registeredPrefixId, do nothing.
+ *
+ * @param {number} registeredPrefixId The ID returned from registerPrefix.
  */
-NDN.prototype.registerPrefixHelper = function(name, closure, flag) {
-	var fe = new ForwardingEntry('selfreg', name, null, null, 3, 2147483647);
-	var bytes = encodeForwardingEntry(fe);
-
-	var si = new SignedInfo();
-	si.setFields();
-
-	var co = new ContentObject(new Name(), si, bytes, new Signature());
-	co.sign();
-	var coBinary = encodeToBinaryContentObject(co);
-
-	//var nodename = unescape('%00%88%E2%F4%9C%91%16%16%D6%21%8E%A0c%95%A5%A6r%11%E0%A0%82%89%A6%A9%85%AB%D6%E2%065%DB%AF');
-	var nodename = this.ndndid;
-	var interestName = new Name(['ndnx', nodename, 'selfreg', coBinary]);
-
-	var interest = new Interest(interestName);
-	interest.scope = 1;
-	if (LOG > 3) console.log('Send Interest registration packet.');
-
-    var csEntry = new CSEntry(name.getName(), closure);
-	NDN.CSTable.push(csEntry);
-
-    this.transport.send(encodeToBinaryInterest(interest));
+Face.prototype.removeRegisteredPrefix = function(registeredPrefixId)
+{
+  this.registeredPrefixTable_.removeRegisteredPrefix(registeredPrefixId);
 };
 
-/*
- * This is called when an entire binary XML element is received, such as a ContentObject or Interest.
- * Look up in the PITTable and call the closure callback.
+/**
+ * Add an entry to the local interest filter table to call the onInterest
+ * callback for a matching incoming Interest. This method only modifies the
+ * library's local callback table and does not register the prefix with the
+ * forwarder. It will always succeed. To register a prefix with the forwarder,
+ * use registerPrefix. There are two forms of setInterestFilter.
+ * The first form uses the exact given InterestFilter:
+ * setInterestFilter(filter, onInterest).
+ * The second form creates an InterestFilter from the given prefix Name:
+ * setInterestFilter(prefix, onInterest).
+ * @param {InterestFilter} filter The InterestFilter with a prefix and optional
+ * regex filter used to match the name of an incoming Interest. This makes a
+ * copy of filter.
+ * @param {Name} prefix The Name prefix used to match the name of an incoming
+ * Interest.
+ * @param {function} onInterest When an Interest is received which matches the
+ * filter, this calls onInterest(prefix, interest, face, interestFilterId, filter).
+ * NOTE: The library will log any exceptions thrown by this callback, but for
+ * better error handling the callback should catch and properly handle any
+ * exceptions.
  */
-NDN.prototype.onReceivedElement = function(element) {
-    if (LOG>3) console.log('Complete element received. Length ' + element.length + '. Start decoding.');
-	var decoder = new BinaryXMLDecoder(element);
-	// Dispatch according to packet type
-	if (decoder.peekStartElement(NDNProtocolDTags.Interest)) {  // Interest packet
-		if (LOG > 3) console.log('Interest packet received.');
-
-		var interest = new Interest();
-		interest.from_ndnb(decoder);
-		if (LOG > 3) console.log(interest);
-		var nameStr = escape(interest.name.getName());
-		if (LOG > 3) console.log(nameStr);
-
-		var entry = getEntryForRegisteredPrefix(nameStr);
-		if (entry != null) {
-			//console.log(entry);
-			var info = new UpcallInfo(this, interest, 0, null);
-			var ret = entry.closure.upcall(Closure.UPCALL_INTEREST, info);
-			if (ret == Closure.RESULT_INTEREST_CONSUMED && info.contentObject != null)
-				this.transport.send(encodeToBinaryContentObject(info.contentObject));
-		}
-	} else if (decoder.peekStartElement(NDNProtocolDTags.ContentObject)) {  // Content packet
-		if (LOG > 3) console.log('ContentObject packet received.');
-
-		var co = new ContentObject();
-		co.from_ndnb(decoder);
-
-		var pitEntry = NDN.getEntryForExpressedInterest(co.name);
-		if (pitEntry != null) {
-			// Cancel interest timer
-			clearTimeout(pitEntry.timerID);
-
-			// Remove PIT entry from NDN.PITTable
-			var index = NDN.PITTable.indexOf(pitEntry);
-			if (index >= 0)
-				NDN.PITTable.splice(index, 1);
-
-			var currentClosure = pitEntry.closure;
-
-			if (this.verify == false) {
-				// Pass content up without verifying the signature
-				currentClosure.upcall(Closure.UPCALL_CONTENT_UNVERIFIED, new UpcallInfo(this, pitEntry.interest, 0, co));
-				return;
-			}
-
-			// Key verification
-
-			// Recursive key fetching & verification closure
-			var KeyFetchClosure = function KeyFetchClosure(content, closure, key, sig, wit) {
-				this.contentObject = content;  // unverified content object
-				this.closure = closure;  // closure corresponding to the contentObject
-				this.keyName = key;  // name of current key to be fetched
-				this.sigHex = sig;  // hex signature string to be verified
-				this.witness = wit;
-
-				Closure.call(this);
-			};
-
-            var thisNDN = this;
-			KeyFetchClosure.prototype.upcall = function(kind, upcallInfo) {
-				if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
-					console.log("In KeyFetchClosure.upcall: interest time out.");
-					console.log(this.keyName.contentName.getName());
-				} else if (kind == Closure.UPCALL_CONTENT) {
-					//console.log("In KeyFetchClosure.upcall: signature verification passed");
-
-					var rsakey = decodeSubjectPublicKeyInfo(upcallInfo.contentObject.content);
-					var verified = rsakey.verifyByteArray(this.contentObject.rawSignatureData, this.witness, this.sigHex);
-
-					var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-					//console.log("raise encapsulated closure");
-					this.closure.upcall(flag, new UpcallInfo(thisNDN, null, 0, this.contentObject));
-
-					// Store key in cache
-					var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
-					NDN.addKeyEntry(keyEntry);
-					//console.log(NDN.KeyStore);
-				} else if (kind == Closure.UPCALL_CONTENT_BAD) {
-					console.log("In KeyFetchClosure.upcall: signature verification failed");
-				}
-			};
-
-			if (co.signedInfo && co.signedInfo.locator && co.signature) {
-				if (LOG > 3) console.log("Key verification...");
-				var sigHex = DataUtils.toHex(co.signature.signature).toLowerCase();
-
-				var wit = null;
-				if (co.signature.Witness != null) {
-					wit = new Witness();
-					wit.decode(co.signature.Witness);
-				}
-
-				var keylocator = co.signedInfo.locator;
-				if (keylocator.type == KeyLocatorType.KEYNAME) {
-					if (LOG > 3) console.log("KeyLocator contains KEYNAME");
-					//var keyname = keylocator.keyName.contentName.getName();
-					//console.log(nameStr);
-					//console.log(keyname);
-
-					if (keylocator.keyName.contentName.match(co.name)) {
-						if (LOG > 3) console.log("Content is key itself");
-
-						var rsakey = decodeSubjectPublicKeyInfo(co.content);
-						var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
-						var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-
-						currentClosure.upcall(flag, new UpcallInfo(this, pitEntry.interest, 0, co));
-
-						// SWT: We don't need to store key here since the same key will be
-						//      stored again in the closure.
-						//var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
-						//NDN.addKeyEntry(keyEntry);
-						//console.log(NDN.KeyStore);
-					} else {
-						// Check local key store
-						var keyEntry = NDN.getKeyByName(keylocator.keyName);
-						if (keyEntry) {
-							// Key found, verify now
-							if (LOG > 3) console.log("Local key cache hit");
-							var rsakey = keyEntry.rsaKey;
-							var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
-							var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-
-							// Raise callback
-							currentClosure.upcall(flag, new UpcallInfo(this, pitEntry.interest, 0, co));
-						} else {
-							// Not found, fetch now
-							if (LOG > 3) console.log("Fetch key according to keylocator");
-							var nextClosure = new KeyFetchClosure(co, currentClosure, keylocator.keyName, sigHex, wit);
-							this.expressInterest(keylocator.keyName.contentName.getPrefix(4), nextClosure);
-						}
-					}
-				} else if (keylocator.type == KeyLocatorType.KEY) {
-					if (LOG > 3) console.log("Keylocator contains KEY");
-
-					var rsakey = decodeSubjectPublicKeyInfo(co.signedInfo.locator.publicKey);
-					var verified = rsakey.verifyByteArray(co.rawSignatureData, wit, sigHex);
-
-					var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
-					// Raise callback
-					currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(this, pitEntry.interest, 0, co));
-
-					// Since KeyLocator does not contain key name for this key,
-					// we have no way to store it as a key entry in KeyStore.
-				} else {
-					var cert = keylocator.certificate;
-					console.log("KeyLocator contains CERT");
-					console.log(cert);
-
-					// TODO: verify certificate
-				}
-			}
-		}
-	} else
-		console.log('Incoming packet is not Interest or ContentObject. Discard now.');
+Face.prototype.setInterestFilter = function(filterOrPrefix, onInterest)
+{
+  var interestFilterId = this.getNextEntryId();
+  this.interestFilterTable_.setInterestFilter
+    (interestFilterId, new InterestFilter(filterOrPrefix), onInterest, this);
+  return interestFilterId;
 };
 
-/*
- * Assume this.getHostAndPort is not null.  This is called when this.host is null or its host
- *   is not alive.  Get a host and port, connect, then execute onConnected().
+/**
+ * Remove the interest filter entry which has the interestFilterId from the
+ * interest filter table. This does not affect another interest filter with a
+ * different interestFilterId, even if it has the same prefix name. If there is
+ * no entry with the interestFilterId, do nothing.
+ * @param {number} interestFilterId The ID returned from setInterestFilter.
  */
-NDN.prototype.connectAndExecute = function(onConnected) {
-    var hostAndPort = this.getHostAndPort();
-    if (hostAndPort == null) {
-        console.log('ERROR: No more hosts from getHostAndPort');
-        this.host = null;
+Face.prototype.unsetInterestFilter = function(interestFilterId)
+{
+  this.interestFilterTable_.unsetInterestFilter(interestFilterId);
+};
+
+/**
+ * The OnInterest callback calls this to put a Data packet which satisfies an
+ * Interest.
+ * @param {Data} data The Data packet which satisfies the interest.
+ * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
+ * the Data packet. If omitted, use WireFormat.getDefaultWireFormat().
+ * @throws Error If the encoded Data packet size exceeds getMaxNdnPacketSize().
+ */
+Face.prototype.putData = function(data, wireFormat)
+{
+  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
+
+  var encoding = data.wireEncode(wireFormat);
+  if (encoding.size() > Face.getMaxNdnPacketSize())
+    throw new Error
+      ("The encoded Data packet size exceeds the maximum limit getMaxNdnPacketSize()");
+
+  this.transport.send(encoding.buf());
+};
+
+/**
+ * Send the encoded packet out through the transport.
+ * @param {Buffer} encoding The Buffer with the encoded packet to send.
+ * @throws Error If the encoded packet size exceeds getMaxNdnPacketSize().
+ */
+Face.prototype.send = function(encoding)
+{
+  if (encoding.length > Face.getMaxNdnPacketSize())
+    throw new Error
+      ("The encoded packet size exceeds the maximum limit getMaxNdnPacketSize()");
+
+  this.transport.send(encoding);
+};
+
+/**
+ * Check if the face is local based on the current connection through the
+ * Transport; some Transport may cause network I/O (e.g. an IP host name lookup).
+ * @param {function} onResult On success, this calls onResult(isLocal) where
+ * isLocal is true if the host is local, false if not. We use callbacks because
+ * this may need to do network I/O (e.g. an IP host name lookup).
+ * @param {function} onError On failure for DNS lookup or other error, this
+ * calls onError(message) where message is an error string.
+ */
+Face.prototype.isLocal = function(onResult, onError)
+{
+  // TODO: How to call transport.isLocal when this.connectionInfo is null? (This
+  // happens when the application does not supply a host but relies on the
+  // getConnectionInfo function to select a host.) For now return true to keep
+  // the same behavior from before we added Transport.isLocal.
+  if (this.connectionInfo == null)
+    onResult(false);
+  else
+    this.transport.isLocal(this.connectionInfo, onResult, onError);
+};
+
+/**
+ * This is called when an entire element is received, such as a Data or Interest.
+ */
+Face.prototype.onReceivedElement = function(element)
+{
+  if (LOG > 3) console.log('Complete element received. Length ' + element.length + '. Start decoding.');
+
+  var lpPacket = null;
+  if (element[0] == Tlv.LpPacket_LpPacket) {
+    // Decode the LpPacket and replace element with the fragment.
+    lpPacket = new LpPacket();
+    // Set copy false so that the fragment is a slice which will be copied below.
+    // The header fields are all integers and don't need to be copied.
+    TlvWireFormat.get().decodeLpPacket(lpPacket, element, false);
+    element = lpPacket.getFragmentWireEncoding().buf();
+  }
+
+  // First, decode as Interest or Data.
+  var interest = null;
+  var data = null;
+  if (element[0] == Tlv.Interest || element[0] == Tlv.Data) {
+    var decoder = new TlvDecoder (element);
+    if (decoder.peekType(Tlv.Interest, element.length)) {
+      interest = new Interest();
+      interest.wireDecode(element, TlvWireFormat.get());
+
+      if (lpPacket != null)
+        interest.setLpPacket(lpPacket);
+    }
+    else if (decoder.peekType(Tlv.Data, element.length)) {
+      data = new Data();
+      data.wireDecode(element, TlvWireFormat.get());
+
+      if (lpPacket != null)
+        data.setLpPacket(lpPacket);
+    }
+  }
+
+  if (lpPacket !== null) {
+    // We have decoded the fragment, so remove the wire encoding to save memory.
+    lpPacket.setFragmentWireEncoding(new Blob());
+
+    var networkNack = NetworkNack.getFirstHeader(lpPacket);
+    if (networkNack != null) {
+      if (interest == null)
+        // We got a Nack but not for an Interest, so drop the packet.
         return;
+
+      var pitEntries = [];
+      this.pendingInterestTable_.extractEntriesForNackInterest(interest, pitEntries);
+      for (var i = 0; i < pitEntries.length; ++i) {
+        var pendingInterest = pitEntries[i];
+        try {
+          pendingInterest.getOnNetworkNack()(pendingInterest.getInterest(), networkNack);
+        } catch (ex) {
+          console.log("Error in onNetworkNack: " + NdnCommon.getErrorWithStackTrace(ex));
+        }
+      }
+
+      // We have processed the network Nack packet.
+      return;
     }
+  }
 
-    if (hostAndPort.host == this.host && hostAndPort.port == this.port) {
-        console.log('ERROR: The host returned by getHostAndPort is not alive: ' +
-                this.host + ":" + this.port);
-        return;
+  // Now process as Interest or Data.
+  if (interest !== null) {
+    if (LOG > 3) console.log('Interest packet received.');
+
+    // Call all interest filter callbacks which match.
+    var matchedFilters = [];
+    this.interestFilterTable_.getMatchedFilters(interest, matchedFilters);
+    for (var i = 0; i < matchedFilters.length; ++i) {
+      var entry = matchedFilters[i];
+      if (LOG > 3)
+        console.log("Found interest filter for " + interest.getName().toUri());
+      try {
+        entry.getOnInterest()
+          (entry.getFilter().getPrefix(), interest, this,
+           entry.getInterestFilterId(), entry.getFilter());
+      } catch (ex) {
+        console.log("Error in onInterest: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
     }
+  }
+  else if (data !== null) {
+    if (LOG > 3) console.log('Data packet received.');
 
-    this.host = hostAndPort.host;
-    this.port = hostAndPort.port;
-    if (LOG>3) console.log("Connect: trying host from getHostAndPort: " + this.host);
-
-    // Fetch any content.
-    var interest = new Interest(new Name("/"));
-	interest.interestLifetime = 4000; // milliseconds
-
-    var thisNDN = this;
-	var timerID = setTimeout(function() {
-        if (LOG>3) console.log("Connect: timeout waiting for host " + thisNDN.host);
-        // Try again.
-        thisNDN.connectAndExecute(onConnected);
-	}, 3000);
-
-    this.reconnectAndExpressInterest
-        (interest, new NDN.ConnectClosure(this, onConnected, timerID));
+    var pendingInterests = [];
+    this.pendingInterestTable_.extractEntriesForExpressedInterest
+      (data, pendingInterests);
+    // Process each matching PIT entry (if any).
+    for (var i = 0; i < pendingInterests.length; ++i) {
+      var pendingInterest = pendingInterests[i];
+      try {
+        pendingInterest.getOnData()(pendingInterest.getInterest(), data);
+      } catch (ex) {
+        console.log("Error in onData: " + NdnCommon.getErrorWithStackTrace(ex));
+      }
+    }
+  }
 };
 
-NDN.ConnectClosure = function ConnectClosure(ndn, onConnected, timerID) {
-    // Inherit from Closure.
-    Closure.call(this);
-
-    this.ndn = ndn;
-    this.onConnected = onConnected;
-    this.timerID = timerID;
-};
-
-NDN.ConnectClosure.prototype.upcall = function(kind, upcallInfo) {
-    if (!(kind == Closure.UPCALL_CONTENT ||
-          kind == Closure.UPCALL_CONTENT_UNVERIFIED))
-        // The upcall is not for us.
-        return Closure.RESULT_ERR;
-
-    // The host is alive, so cancel the timeout and continue with onConnected().
-    clearTimeout(this.timerID);
-
-    // Call NDN.onopen after success
-	this.ndn.readyStatus = NDN.OPENED;
-	this.ndn.onopen();
-
-    this.onConnected();
-
-    return Closure.RESULT_OK;
-};
-
-/*
- * A BinaryXmlElementReader lets you call onReceivedData multiple times which uses a
- *   BinaryXMLStructureDecoder to detect the end of a binary XML element and calls
- *   elementListener.onReceivedElement(element) with the element.
- * This handles the case where a single call to onReceivedData may contain multiple elements.
+/**
+ * Assume this.getConnectionInfo is not null.  This is called when
+ * this.connectionInfo is null or its host is not alive.
+ * Get a connectionInfo, connect, then execute onConnected().
  */
-var BinaryXmlElementReader = function BinaryXmlElementReader(elementListener) {
-    this.elementListener = elementListener;
-	this.dataParts = [];
-    this.structureDecoder = new BinaryXMLStructureDecoder();
+Face.prototype.connectAndExecute = function(onConnected)
+{
+  var connectionInfo = this.getConnectionInfo();
+  if (connectionInfo == null) {
+    console.log('ERROR: No more connectionInfo from getConnectionInfo');
+    this.connectionInfo = null;
+    // Deprecated: Set this.host and this.port for backwards compatibility.
+    this.host = null;
+    this.host = null;
+
+    return;
+  }
+
+  if (connectionInfo.equals(this.connectionInfo)) {
+    console.log
+      ('ERROR: The host returned by getConnectionInfo is not alive: ' +
+       this.connectionInfo.toString());
+    return;
+  }
+
+  this.connectionInfo = connectionInfo;
+  if (LOG>0) console.log("connectAndExecute: trying host from getConnectionInfo: " +
+                         this.connectionInfo.toString());
+  // Deprecated: Set this.host and this.port for backwards compatibility.
+  this.host = this.connectionInfo.host;
+  this.host = this.connectionInfo.port;
+
+  // Fetch any content.
+  var interest = new Interest(new Name("/"));
+  interest.setInterestLifetimeMilliseconds(4000);
+
+  var thisFace = this;
+  var timerID = setTimeout(function() {
+    if (LOG>0) console.log("connectAndExecute: timeout waiting for host " + thisFace.host);
+      // Try again.
+      thisFace.connectAndExecute(onConnected);
+  }, 3000);
+
+  this.reconnectAndExpressInterest
+    (null, interest,
+     function(localInterest, localData) {
+        // The host is alive, so cancel the timeout and continue with onConnected().
+        clearTimeout(timerID);
+
+        if (LOG>0)
+          console.log("connectAndExecute: connected to host " + thisFace.host);
+        onConnected();
+     },
+     function(localInterest) { /* Ignore timeout */ },
+     null, WireFormat.getDefaultWireFormat());
 };
 
-BinaryXmlElementReader.prototype.onReceivedData = function(/* Uint8Array */ rawData) {
-    // Process multiple objects in the data.
-    while(true) {
-        // Scan the input to check if a whole ndnb object has been read.
-        this.structureDecoder.seek(0);
-        if (this.structureDecoder.findElementEnd(rawData)) {
-            // Got the remainder of an object.  Report to the caller.
-            this.dataParts.push(rawData.subarray(0, this.structureDecoder.offset));
-            var element = DataUtils.concatArrays(this.dataParts);
-            this.dataParts = [];
-            try {
-                this.elementListener.onReceivedElement(element);
-            } catch (ex) {
-                console.log("BinaryXmlElementReader: ignoring exception from onReceivedElement: " + ex);
-            }
+/**
+ * This is called by the Transport when the connection is closed by the remote host.
+ */
+Face.prototype.closeByTransport = function()
+{
+  this.readyStatus = Face.CLOSED;
+  this.onclose();
+};
 
-            // Need to read a new object.
-            rawData = rawData.subarray(this.structureDecoder.offset, rawData.length);
-            this.structureDecoder = new BinaryXMLStructureDecoder();
-            if (rawData.length == 0)
-                // No more data in the packet.
-                return;
-
-            // else loop back to decode.
-        }
-        else {
-            // Save for a later call to concatArrays so that we only copy data once.
-            this.dataParts.push(rawData);
-			if (LOG>3) console.log('Incomplete packet received. Length ' + rawData.length + '. Wait for more input.');
-            return;
-        }
-    }
-}
\ No newline at end of file
+Face.nonceTemplate_ = new Blob(new Buffer(4), false);
+(function(n,t,i){"use strict";function s(n,t){return typeof t!="object"&&(t=t()),Object.keys(t).forEach(function(i){n[i]=t[i]}),n}function y(n){return{from:function(t){return n.prototype=Object.create(t.prototype),n.prototype.constructor=n,{extend:function(i){s(n.prototype,typeof i!="object"?i(t.prototype):i)}}}}}function p(n,t){return t(n)}function u(n,t){function cr(){w.on("versionchange",function(){w.close();w.on("error").fire(new g("Database version changed by other database connection."))})}function di(n){this._cfg={version:n,storesSource:null,dbschema:{},tables:{},contentUpgrade:null};this.stores({})}function lr(n,t,i,u){var e,f,s,h,l,c;if(n===0)Object.keys(st).forEach(function(n){gi(t,n,st[n].primKey,st[n].indexes)}),e=w._createTransaction(yt,ui,st),e.idbtrans=t,e.idbtrans.onerror=o(i,["populating database"]),e.on("error").subscribe(i),r.newPSD(function(){r.PSD.trans=e;try{w.on("populate").fire(e)}catch(n){u.onerror=t.onerror=function(n){n.preventDefault()};try{t.abort()}catch(f){}t.db.close();i(n)}});else{if(f=[],s=ri.filter(function(t){return t._cfg.version===n})[0],!s)throw new g("Dexie specification of currently installed DB version is missing");st=w._dbSchema=s._cfg.dbschema;h=!1;l=ri.filter(function(t){return t._cfg.version>n});l.forEach(function(n){var e=st,r=n._cfg.dbschema,u;fr(e,t);fr(r,t);st=w._dbSchema=r;u=ar(e,r);u.add.forEach(function(n){f.push(function(t,i){gi(t,n[0],n[1].primKey,n[1].indexes);i()})});u.change.forEach(function(n){if(n.recreate)throw new g("Not yet support for changing primary key");else f.push(function(t,i){var r=t.objectStore(n.name);n.add.forEach(function(n){nr(r,n)});n.change.forEach(function(n){r.deleteIndex(n.name);nr(r,n)});n.del.forEach(function(n){r.deleteIndex(n)});i()})});n._cfg.contentUpgrade&&f.push(function(t,u){var f,e;h=!0;f=w._createTransaction(yt,[].slice.call(t.db.objectStoreNames,0),r);f.idbtrans=t;e=0;f._promise=p(f._promise,function(n){return function(t,i,r){function f(n){return function(){n.apply(this,arguments);--e==0&&u()}}return++e,n.call(this,t,function(n,t){arguments[0]=f(n);arguments[1]=f(t);i.apply(this,arguments)},r)}});t.onerror=o(i,["running upgrader function for version",n._cfg.version]);f.on("error").subscribe(i);n._cfg.contentUpgrade(f);e===0&&u()});h&&dr()||f.push(function(n,t){yr(r,n);t()})});c=function(){try{f.length?f.shift()(t,c):vr(st,t)}catch(n){u.onerror=t.onerror=function(n){n.preventDefault()};try{t.abort()}catch(r){}t.db.close();i(n)}};c()}}function ar(n,t){var f={del:[],add:[],change:[]},r,e,o,i,c,s,u,l,h;for(r in n)t[r]||f.del.push(r);for(r in t)if(e=n[r],o=t[r],e)if(i={name:r,def:t[r],recreate:!1,del:[],add:[],change:[]},e.primKey.src!==o.primKey.src)i.recreate=!0,f.change.push(i);else{c=e.indexes.reduce(function(n,t){return n[t.name]=t,n},{});s=o.indexes.reduce(function(n,t){return n[t.name]=t,n},{});for(u in c)s[u]||i.del.push(u);for(u in s)l=c[u],h=s[u],l?l.src!==h.src&&i.change.push(h):i.add.push(h);(i.recreate||i.del.length>0||i.add.length>0||i.change.length>0)&&f.change.push(i)}else f.add.push([r,o]);return f}function gi(n,t,i,r){var u=n.db.createObjectStore(t,i.keyPath?{keyPath:i.keyPath,autoIncrement:i.auto}:{autoIncrement:i.auto});return r.forEach(function(n){nr(u,n)}),u}function vr(n,t){Object.keys(n).forEach(function(i){t.db.objectStoreNames.contains(i)||gi(t,i,n[i].primKey,n[i].indexes)})}function yr(n,t){for(var u,r=0;r<t.db.objectStoreNames.length;++r)u=t.db.objectStoreNames[r],(n[u]===null||n[u]===i)&&t.db.deleteObjectStore(u)}function nr(n,t){n.createIndex(t.name,t.keyPath,{unique:t.unique,multiEntry:t.multi})}function pr(n,t){throw new g("Table "+t[0]+" not part of transaction. Original Scope Function Source: "+u.Promise.PSD.trans.scopeFunc.toString());}function ei(n,t,i,r){this.name=n;this.schema=i;this.hook=ni[n]?ni[n].hook:v(null,{creating:[at,f],reading:[lt,nt],updating:[vt,f],deleting:[wt,f]});this._tpf=t;this._collClass=r||li}function tr(n,t,i,r){ei.call(this,n,t,i,r||rr)}function ir(n,t,i,r){function o(n,t,i,r){return s._promise(n,i,r)}var s=this,f,u,e;for(this.db=w,this.mode=n,this.storeNames=t,this.idbtrans=null,this.on=v(this,["complete","error"],"abort"),this._reculock=0,this._blockedFuncs=[],this._psd=null,this.active=!0,this._dbschema=i,r&&(this.parent=r),this._tpf=o,this.tables=Object.create(ki),f=t.length-1;f!==-1;--f)u=t[f],e=w._tableFactory(n,i[u],o),this.tables[u]=e,this[u]||(this[u]=e)}function ci(n,t,i){this._ctx={table:n,index:t===":id"?null:t,collClass:n._collClass,or:i}}function li(n,t){var r=null,u=null,i;if(t)try{r=t()}catch(f){u=f}i=n._ctx;this._ctx={table:i.table,index:i.index,isPrimKey:!i.index||i.table.schema.primKey.keyPath&&i.index===i.table.schema.primKey.name,range:r,op:"openCursor",dir:"next",unique:"",algorithm:null,filter:null,isMatch:null,offset:0,limit:Infinity,error:u,or:i.or}}function rr(){li.apply(this,arguments)}function wr(n,t){return n._cfg.version-t._cfg.version}function ur(n,t,i,u,f,e){i.forEach(function(i){var o=w._tableFactory(u,f[i],t);n.forEach(function(n){n[i]||(e?Object.defineProperty(n,i,{configurable:!0,enumerable:!0,get:function(){var n=r.PSD&&r.PSD.trans;return n&&n.db===w?n.tables[i]:o}}):n[i]=o)})})}function br(n){n.forEach(function(n){for(var t in n)n[t]instanceof ei&&delete n[t]})}function pi(n,t,i,u,f,e){var s=r.PSD;e=e||nt;n.onerror||(n.onerror=o(f));n.onsuccess=t?k(function(){var r=n.result,o;r?(o=function(){r.continue()},t(r,function(n){o=n},u,f)&&i(e(r.value),r,function(n){o=n}),o()):u()},f,s):k(function(){var t=n.result,r;t?(r=function(){t.continue()},i(e(t.value),t,function(n){r=n}),r()):u()},f,s)}function kr(n){var t=[];return n.split(",").forEach(function(n){n=n.trim();var i=n.replace("&","").replace("++","").replace("*",""),r=i.indexOf("[")!==0?i:n.substring(n.indexOf("[")+1,n.indexOf("]")).split("+");t.push(new a(i,r||null,n.indexOf("&")!==-1,n.indexOf("*")!==-1,n.indexOf("++")!==-1,Array.isArray(r),r.indexOf(".")!==-1))}),t}function wi(n,t){return n<t?-1:n>t?1:0}function or(n,t){return n<t?1:n>t?-1:0}function sr(n){return function(t,i){for(var r=0,u;;){if(u=n(t[r],i[r]),u!==0)return u;if(++r,r===t.length||r===i.length)return n(t.length,i.length)}}}function bi(n,t){return n?t?function(){return n.apply(this,arguments)&&t.apply(this,arguments)}:n:t}function dr(){return navigator.userAgent.indexOf("Trident")>=0||navigator.userAgent.indexOf("MSIE")>=0}function gr(){if(w.verno=et.version/10,w._dbSchema=st={},ui=[].slice.call(et.objectStoreNames,0),ui.length!==0){var n=et.transaction(ft(ui),"readonly");ui.forEach(function(t){for(var u,s,r=n.objectStore(t),i=r.keyPath,f=i&&typeof i=="string"&&i.indexOf(".")!==-1,h=new a(i,i||"",!1,!1,!!r.autoIncrement,i&&typeof i!="string",f),o=[],e=0;e<r.indexNames.length;++e)u=r.index(r.indexNames[e]),i=u.keyPath,f=i&&typeof i=="string"&&i.indexOf(".")!==-1,s=new a(u.name,i,!!u.unique,!!u.multiEntry,!1,i&&typeof i!="string",f),o.push(s);st[t]=new ut(t,h,o,{})});ur([ni],w._transPromiseFactory,Object.keys(st),yt,st)}}function fr(n,t){for(var i,r,u,o,s=t.db.objectStoreNames,f=0;f<s.length;++f)for(i=s[f],r=t.objectStore(i),u=0;u<r.indexNames.length;++u){var h=r.indexNames[u],e=r.index(h).keyPath,c=typeof e=="string"?e:"["+[].slice.call(e).join("+")+"]";n[i]&&(o=n[i].idxByName[c],o&&(o.name=h))}}var hr=t&&t.addons||u.addons,oi=u.dependencies,ai=oi.indexedDB,kt=oi.IDBKeyRange,nu=oi.IDBTransaction,tu=oi.DOMError,yi=oi.TypeError,g=oi.Error,st=this._dbSchema={},ri=[],ui=[],ni={},ki={},et=null,si=!0,fi=null,vi=!1,ti="readonly",yt="readwrite",w=this,ii=[],hi=!1,er=!!ct();this.version=function(n){if(et)throw new g("Cannot add version when database is open");this.verno=Math.max(this.verno,n);var t=ri.filter(function(t){return t._cfg.version===n})[0];return t?t:(t=new di(n),ri.push(t),ri.sort(wr),t)};s(di.prototype,{stores:function(n){var i,t;return this._cfg.storesSource=this._cfg.storesSource?s(this._cfg.storesSource,n):n,i={},ri.forEach(function(n){s(i,n._cfg.storesSource)}),t=this._cfg.dbschema={},this._parseStoresSpec(i,t),st=w._dbSchema=t,br([ni,w,ki]),ur([ki],pr,Object.keys(t),yt,t),ur([ni,w,this._cfg.tables],w._transPromiseFactory,Object.keys(t),yt,t,!0),ui=Object.keys(t),this},upgrade:function(n){var t=this;return e(function(){n(w._createTransaction(yt,Object.keys(t._cfg.dbschema),t._cfg.dbschema))}),this._cfg.contentUpgrade=n,this},_parseStoresSpec:function(n,t){Object.keys(n).forEach(function(i){if(n[i]!==null){var u={},f=kr(n[i]),r=f.shift();if(r.multi)throw new g("Primary key cannot be multi-valued");r.keyPath&&r.auto&&h(u,r.keyPath,0);f.forEach(function(n){if(n.auto)throw new g("Only primary key can be marked as autoIncrement (++)");if(!n.keyPath)throw new g("Index must have a name and cannot be an empty string");h(u,n.keyPath,n.compound?n.keyPath.map(function(){return""}):"")});t[i]=new ut(i,r,f,u)}})}});this._allTables=ni;this._tableFactory=function(n,t,i){return n===ti?new ei(t.name,i,t,li):new tr(t.name,i,t)};this._createTransaction=function(n,t,i,r){return new ir(n,t,i,r)};this._transPromiseFactory=function(n,t,i){var f,u;return!si||r.PSD&&r.PSD.letThrough?(u=w._createTransaction(n,t,st),u._promise(n,function(n,t){u.error(function(n){w.on("error").fire(n)});i(function(t){u.complete(function(){n(t)})},t,u)})):f=new r(function(r,u){ii.push({resume:function(){var e=w._transPromiseFactory(n,t,i);f.onuncatched=e.onuncatched;e.then(r,u)}})})};this._whenReady=function(n){return si&&(!r.PSD||!r.PSD.letThrough)?new r(function(t,i){e(function(){new r(function(){n(t,i)})});ii.push({resume:function(){n(t,i)}})}):new r(n)};this.verno=0;this.open=function(){return new r(function(t,i){function f(n){try{u.transaction.abort()}catch(t){}vi=!1;fi=n;si=!1;i(fi);ii.forEach(function(n){n.resume()});ii=[]}if(et||vi)throw new g("Database already opened or being opened");var u,e=!1;try{if(fi=null,vi=!0,ri.length===0&&(hi=!0),!ai)throw new g("indexedDB API not found. If using IE10+, make sure to run your code on a server URL (not locally). If using Safari, make sure to include indexedDB polyfill.");u=hi?ai.open(n):ai.open(n,Math.round(w.verno*10));u.onerror=o(f,["opening database",n]);u.onblocked=function(n){w.on("blocked").fire(n)};u.onupgradeneeded=k(function(t){var i,r;hi&&!w._allowEmptyDB?(u.onerror=function(n){n.preventDefault()},u.transaction.abort(),u.result.close(),i=ai.deleteDatabase(n),i.onsuccess=i.onerror=function(){f(new g("Database '"+n+"' doesnt exist"))}):(t.oldVersion===0&&(e=!0),u.transaction.onerror=o(f),r=t.oldVersion>Math.pow(2,62)?0:t.oldVersion,lr(r/10,u.transaction,f,u))},f);u.onsuccess=k(function(){vi=!1;et=u.result;hi?gr():et.objectStoreNames.length>0&&fr(st,et.transaction(ft(et.objectStoreNames),ti));et.onversionchange=w.on("versionchange").fire;er||rt(function(t){if(t.indexOf(n)===-1)return t.push(n)});r.newPSD(function(){function i(){si=!1;ii.forEach(function(n){n.resume()});ii=[];t()}r.PSD.letThrough=!0;try{var n=w.on.ready.fire();n&&typeof n.then=="function"?n.then(i,function(n){et.close();et=null;f(n)}):b(i)}catch(u){f(u)}})},f)}catch(s){f(s)}})};this.close=function(){et&&(et.close(),et=null,si=!0,fi=null)};this.delete=function(){var t=arguments;return new r(function(i,r){function u(){w.close();var t=ai.deleteDatabase(n);t.onsuccess=function(){er||rt(function(t){var i=t.indexOf(n);if(i>=0)return t.splice(i,1)});i()};t.onerror=o(r,["deleting",n]);t.onblocked=function(){w.on("blocked").fire()}}if(t.length>0)throw new g("Arguments not allowed in db.delete()");vi?ii.push({resume:u}):u()})};this.backendDB=function(){return et};this.isOpen=function(){return et!==null};this.hasFailed=function(){return fi!==null};this.dynamicallyOpened=function(){return hi};this.name=n;Object.defineProperty(this,"tables",{get:function(){return Object.keys(ni).map(function(n){return ni[n]})}});this.on=v(this,"error","populate","blocked",{ready:[bt,f],versionchange:[pt,f]});this.on.ready.subscribe=p(this.on.ready.subscribe,function(n){return function(t,i){function r(){return i||w.on.ready.unsubscribe(r),t.apply(this,arguments)}n.call(this,r);w.isOpen()&&(si?ii.push({resume:r}):r())}});e(function(){w.on("populate").fire(w._createTransaction(yt,ui,st));w.on("error").fire(new g)});this.transaction=function(n,t,i){function s(t,e){var s=null,c,a,h;try{if(f)throw f;s=w._createTransaction(n,o,st,u);c=o.map(function(n){return s.tables[n]});c.push(s);h=0;r.newPSD(function(){r.PSD.trans=s;s.scopeFunc=i;u&&(s.idbtrans=u.idbtrans,s._promise=p(s._promise,function(n){return function(t,i,u){function f(n){return function(t){var i;return r._rootExec(function(){i=n(t);r._tickFinalize(function(){--h==0&&s.active&&(s.active=!1,s.on.complete.fire())})}),i}}return++h,n.call(this,t,function(n,t,r){return i(f(n),f(t),r)},u)}}));s.complete(function(){t(a)});s.error(function(n){s.idbtrans&&(s.idbtrans.onerror=ht);try{s.abort()}catch(i){}u&&(u.active=!1,u.on.error.fire(n));var t=e(n);u||t||w.on.error.fire(n)});r._rootExec(function(){a=i.apply(s,c)})});(!s.idbtrans||u&&h===0)&&s._nop()}catch(l){s&&s.idbtrans&&(s.idbtrans.onerror=ht);s&&s.abort();u&&u.on.error.fire(l);b(function(){e(l)||w.on("error").fire(l)})}}var u,e;t=[].slice.call(arguments,1,arguments.length-1);i=arguments[arguments.length-1];u=r.PSD&&r.PSD.trans;u&&u.db===w&&n.indexOf("!")===-1||(u=null);e=n.indexOf("?")!==-1;n=n.replace("!","").replace("?","");var h=Array.isArray(t[0])?t.reduce(function(n,t){return n.concat(t)}):t,f=null,o=h.map(function(n){return typeof n=="string"?n:(n instanceof ei||(f=f||new yi("Invalid type. Arguments following mode must be instances of Table or String")),n.name)});return n=="r"||n==ti?n=ti:n=="rw"||n==yt?n=yt:f=new g("Invalid transaction mode: "+n),u&&(f||(u&&u.mode===ti&&n===yt&&(e?u=null:f=f||new g("Cannot enter a sub-transaction with READWRITE mode when parent transaction is READONLY")),u&&o.forEach(function(n){u.tables.hasOwnProperty(n)||(e?u=null:f=f||new g("Table "+n+" not included in parent transaction. Parent Transaction function: "+u.scopeFunc.toString()))}))),u?u._promise(n,s,"lock"):w._whenReady(s)};this.table=function(n){if(!hi&&!ni.hasOwnProperty(n))throw new g("Table does not exist");return ni[n]};s(ei.prototype,function(){function n(){throw new g("Current Transaction is READONLY");}return{_trans:function(n,t,i){return this._tpf(n,[this.name],t,i)},_idbstore:function(n,t,i){var r=this;return this._tpf(n,[this.name],function(n,i,u){t(n,i,u.idbtrans.objectStore(r.name),u)},i)},get:function(n,t){var i=this;return e(function(){t(i.schema.instanceTemplate)}),this._idbstore(ti,function(t,r,u){var f=u.get(n);f.onerror=o(r,["getting",n,"from",i.name]);f.onsuccess=function(){t(i.hook.reading.fire(f.result))}}).then(t)},where:function(n){return new ci(this,n)},count:function(n){return this.toCollection().count(n)},offset:function(n){return this.toCollection().offset(n)},limit:function(n){return this.toCollection().limit(n)},reverse:function(){return this.toCollection().reverse()},filter:function(n){return this.toCollection().and(n)},each:function(n){var t=this;return e(function(){n(t.schema.instanceTemplate)}),this._idbstore(ti,function(i,r,u){var f=u.openCursor();f.onerror=o(r,["calling","Table.each()","on",t.name]);pi(f,null,n,i,r,t.hook.reading.fire)})},toArray:function(n){var t=this;return e(function(){n([t.schema.instanceTemplate])}),this._idbstore(ti,function(n,i,r){var u=[],f=r.openCursor();f.onerror=o(i,["calling","Table.toArray()","on",t.name]);pi(f,null,function(n){u.push(n)},function(){n(u)},i,t.hook.reading.fire)}).then(n)},orderBy:function(n){return new this._collClass(new ci(this,n))},toCollection:function(){return new this._collClass(new ci(this))},mapToClass:function(n,t){var i,r;return this.schema.mappedClass=n,i=Object.create(n.prototype),this.schema.primKey.keyPath&&(h(i,this.schema.primKey.keyPath,this.schema.primKey.auto?0:""),ot(n.prototype,this.schema.primKey.keyPath)),t&&it(i,t),this.schema.instanceTemplate=i,r=Object.setPrototypeOf?function(t){return t?(Object.setPrototypeOf(t,n.prototype),t):t}:function(t){var r,i;if(!t)return t;r=Object.create(n.prototype);for(i in t)t.hasOwnProperty(i)&&(r[i]=t[i]);return r},this.schema.readHook&&this.hook.reading.unsubscribe(this.schema.readHook),this.schema.readHook=r,this.hook("reading",r),n},defineClass:function(n){return this.mapToClass(u.defineClass(n),n)},add:n,put:n,"delete":n,clear:n,update:n}});y(tr).from(ei).extend(function(){return{add:function(n,t){var u=this,r=this.hook.creating.fire;return this._idbstore(yt,function(e,s,l,a){var v={},w,y,p;r!==f&&(w=t||(l.keyPath?c(n,l.keyPath):i),y=r.call(v,w,n,a),w===i&&y!==i&&(l.keyPath?h(n,l.keyPath,y):t=y));p=t?l.add(n,t):l.add(n);p.onerror=o(function(n){if(v.onerror)v.onerror(n);return s(n)},["adding",n,"into",u.name]);p.onsuccess=function(t){var i=l.keyPath;if(i&&h(n,i,t.target.result),v.onsuccess)v.onsuccess(t.target.result);e(p.result)}})},put:function(n,t){var r=this,u=this.hook.creating.fire,e=this.hook.updating.fire;return u!==f||e!==f?this._trans(yt,function(u,f,e){var o=t||r.schema.primKey.keyPath&&c(n,r.schema.primKey.keyPath);o===i?e.tables[r.name].add(n).then(u,f):(e._lock(),n=l(n),e.tables[r.name].where(":id").equals(o).modify(function(){this.value=n}).then(function(i){return i===0?e.tables[r.name].add(n,t):o}).finally(function(){e._unlock()}).then(u,f))}):this._idbstore(yt,function(i,u,f){var e=t?f.put(n,t):f.put(n);e.onerror=o(u,["putting",n,"into",r.name]);e.onsuccess=function(t){var r=f.keyPath;r&&h(n,r,t.target.result);i(e.result)}})},"delete":function(n){return this.hook.deleting.subscribers.length?this.where(":id").equals(n).delete():this._idbstore(yt,function(t,i,r){var u=r.delete(n);u.onerror=o(i,["deleting",n,"from",r.name]);u.onsuccess=function(){t(u.result)}})},clear:function(){return this.hook.deleting.subscribers.length?this.toCollection().delete():this._idbstore(yt,function(n,t,i){var r=i.clear();r.onerror=o(t,["clearing",i.name]);r.onsuccess=function(){n(r.result)}})},update:function(n,t){if(typeof t!="object"||Array.isArray(t))throw new g("db.update(keyOrObject, modifications). modifications must be an object.");if(typeof n!="object"||Array.isArray(n))return this.where(":id").equals(n).modify(t);Object.keys(t).forEach(function(i){h(n,i,t[i])});var u=c(n,this.schema.primKey.keyPath);return u===i&&r.reject(new g("Object does not contain its primary key")),this.where(":id").equals(u).modify(t)}}});s(ir.prototype,{_lock:function(){return++this._reculock,this._reculock===1&&r.PSD&&(r.PSD.lockOwnerFor=this),this},_unlock:function(){if(--this._reculock==0)for(r.PSD&&(r.PSD.lockOwnerFor=null);this._blockedFuncs.length>0&&!this._locked();){var n=this._blockedFuncs.shift();try{n()}catch(t){}}return this},_locked:function(){return this._reculock&&(!r.PSD||r.PSD.lockOwnerFor!==this)},_nop:function(n){this.tables[this.storeNames[0]].get(0).then(n)},_promise:function(n,t,i){var f=this;return r.newPSD(function(){var e;return f._locked()?e=new r(function(r,u){f._blockedFuncs.push(function(){f._promise(n,t,i).then(r,u)})}):(e=f.active?new r(function(r,e){if(!f.idbtrans&&n){if(!et)throw fi?new g("Database not open. Following error in populate, ready or upgrade function made Dexie.open() fail: "+fi):new g("Database not open");var o=f.idbtrans=et.transaction(ft(f.storeNames),f.mode);o.onerror=function(n){f.on("error").fire(n&&n.target.error);n.preventDefault();f.abort()};o.onabort=function(n){f.active=!1;f.on("abort").fire(n)};o.oncomplete=function(n){f.active=!1;f.on("complete").fire(n)}}i&&f._lock();try{t(r,e,f)}catch(s){u.ignoreTransaction(function(){f.on("error").fire(s)});f.abort();e(s)}}):r.reject(gt(new g("Transaction is inactive. Original Scope Function Source: "+f.scopeFunc.toString()))),f.active&&i&&e.finally(function(){f._unlock()})),e.onuncatched=function(n){u.ignoreTransaction(function(){f.on("error").fire(n)});f.abort()},e})},complete:function(n){return this.on("complete",n)},error:function(n){return this.on("error",n)},abort:function(){if(this.idbtrans&&this.active)try{this.active=!1;this.idbtrans.abort();this.on.error.fire(new g("Transaction Aborted"))}catch(n){}},table:function(n){if(!this.tables.hasOwnProperty(n))throw new g("Table "+n+" not in transaction");return this.tables[n]}});s(ci.prototype,function(){function n(n,t){try{throw t;}catch(i){n._ctx.error=i}return n}function i(n){return Array.prototype.slice.call(n.length===1&&Array.isArray(n[0])?n[0]:n)}function r(n){return n==="next"?function(n){return n.toUpperCase()}:function(n){return n.toLowerCase()}}function u(n){return n==="next"?function(n){return n.toLowerCase()}:function(n){return n.toUpperCase()}}function f(n,t,i,r,u,f){for(var h,s=Math.min(n.length,r.length),o=-1,e=0;e<s;++e){if(h=t[e],h!==r[e])return u(n[e],i[e])<0?n.substr(0,e)+i[e]+i.substr(e+1):u(n[e],r[e])<0?n.substr(0,e)+r[e]+i.substr(e+1):o>=0?n.substr(0,o)+t[o]+i.substr(o+1):null;u(n[e],h)<0&&(o=e)}return s<r.length&&f==="next"?n+i.substr(n.length):s<n.length&&f==="prev"?n.substr(0,i.length):o<0?null:n.substr(0,o)+r[o]+i.substr(o+1)}function t(n,t,i){function a(n){s=r(n);e=u(n);h=n==="next"?wi:or;c=s(i);o=e(i);l=n}var s,e,h,c,o,l;a("next");n._ondirectionchange=function(n){a(n)};n._addAlgorithm(function(n,i,r){var u=n.key,s,a;return typeof u!="string"?!1:(s=e(u),t(s,o)?(i(function(){n.continue()}),!0):(a=f(u,s,c,o,h,l),a?i(function(){n.continue(a)}):i(r),!1))})}return{between:function(n,t,i,r){return(i=i!==!1,r=r===!0,n>t||n===t&&(i||r)&&!(i&&r))?new this._ctx.collClass(this,function(){return kt.only(n)}).limit(0):new this._ctx.collClass(this,function(){return kt.bound(n,t,!i,!r)})},equals:function(n){return new this._ctx.collClass(this,function(){return kt.only(n)})},above:function(n){return new this._ctx.collClass(this,function(){return kt.lowerBound(n,!0)})},aboveOrEqual:function(n){return new this._ctx.collClass(this,function(){return kt.lowerBound(n)})},below:function(n){return new this._ctx.collClass(this,function(){return kt.upperBound(n,!0)})},belowOrEqual:function(n){return new this._ctx.collClass(this,function(){return kt.upperBound(n)})},startsWith:function(t){return typeof t!="string"?n(new this._ctx.collClass(this),new yi("String expected")):this.between(t,t+String.fromCharCode(65535),!0,!0)},startsWithIgnoreCase:function(i){if(typeof i!="string")return n(new this._ctx.collClass(this),new yi("String expected"));if(i==="")return this.startsWith(i);var r=new this._ctx.collClass(this,function(){return kt.bound(i.toUpperCase(),i.toLowerCase()+String.fromCharCode(65535))});return t(r,function(n,t){return n.indexOf(t)===0},i),r._ondirectionchange=function(){n(r,new g("reverse() not supported with WhereClause.startsWithIgnoreCase()"))},r},equalsIgnoreCase:function(i){if(typeof i!="string")return n(new this._ctx.collClass(this),new yi("String expected"));var r=new this._ctx.collClass(this,function(){return kt.bound(i.toUpperCase(),i.toLowerCase())});return t(r,function(n,t){return n===t},i),r},anyOf:function(){var f=this._ctx,e=f.table.schema,o=f.index?e.idxByName[f.index]:e.primKey,s=o&&o.compound,n=i(arguments),t=s?sr(wi):wi,u,r;return(n.sort(t),n.length===0)?new this._ctx.collClass(this,function(){return kt.only("")}).limit(0):(u=new this._ctx.collClass(this,function(){return kt.bound(n[0],n[n.length-1])}),u._ondirectionchange=function(i){t=i==="next"?wi:or;s&&(t=sr(t));n.sort(t)},r=0,u._addAlgorithm(function(i,u,f){for(var e=i.key;t(e,n[r])>0;)if(++r,r===n.length)return u(f),!1;return t(e,n[r])===0?(u(function(){i.continue()}),!0):(u(function(){i.continue(n[r])}),!1)}),u)}}});s(li.prototype,function(){function t(n,t){n.filter=bi(n.filter,t)}function f(n,t){n.isMatch=bi(n.isMatch,t)}function r(n,t){if(n.isPrimKey)return t;var i=n.table.schema.idxByName[n.index];if(!i)throw new g("KeyPath "+n.index+" on object store "+t.name+" is not indexed");return n.isPrimKey?t:t.index(i.name)}function u(n,t){return r(n,t)[n.op](n.range||null,n.dir+n.unique)}function i(n,t,i,r,f){n.or?function(){function e(){++c==2&&i()}function h(n,i,u){if(!o||o(i,u,e,r)){var f=i.primaryKey.toString();s.hasOwnProperty(f)||(s[f]=!0,t(n,i,u))}}var o=n.filter,s={},l=n.table.schema.primKey.keyPath,c=0;n.or._iterate(h,e,r,f);pi(u(n,f),n.algorithm,h,e,r,n.table.hook.reading.fire)}():pi(u(n,f),bi(n.algorithm,n.filter),t,i,r,n.table.hook.reading.fire)}function n(n){return n.table.schema.instanceTemplate}return{_read:function(n,t){var i=this._ctx;return i.error?i.table._trans(null,function(n,t){t(i.error)}):i.table._idbstore(ti,n).then(t)},_write:function(n){var t=this._ctx;return t.error?t.table._trans(null,function(n,i){i(t.error)}):t.table._idbstore(yt,n,"locked")},_addAlgorithm:function(n){var t=this._ctx;t.algorithm=bi(t.algorithm,n)},_iterate:function(n,t,r,u){return i(this._ctx,n,t,r,u)},each:function(t){var r=this._ctx;return e(function(){t(n(r))}),this._read(function(n,u,f){i(r,t,n,u,f)})},count:function(n){var f,t,u;return e(function(){n(0)}),f=this,t=this._ctx,t.filter||t.algorithm||t.or?(u=0,this._read(function(n,r,f){i(t,function(){return++u,!1},function(){n(u)},r,f)},n)):this._read(function(n,i,u){var e=r(t,u),s=t.range?e.count(t.range):e.count();s.onerror=o(i,["calling","count()","on",f.name]);s.onsuccess=function(i){n(Math.min(i.target.result,Math.max(0,t.limit-t.offset)))}},n)},sortBy:function(t,i){function u(n,t){return t?u(n[r[t]],t-1):n[h]}function c(n,t){var i=u(n,o),r=u(t,o);return i<r?-f:i>r?f:0}var s=this._ctx,f;e(function(){i([n(s)])});var r=t.split(".").reverse(),h=r[0],o=r.length-1;return f=this._ctx.dir==="next"?1:-1,this.toArray(function(n){return n.sort(c)}).then(i)},toArray:function(t){var r=this._ctx;return e(function(){t([n(r)])}),this._read(function(n,t,u){var f=[];i(r,function(n){f.push(n)},function(){n(f)},t,u)},t)},offset:function(n){var i=this._ctx;return n<=0?this:(i.offset+=n,i.or||i.algorithm||i.filter?t(i,function(){return--n<0}):t(i,function(t,i){return n===0?!0:n===1?(--n,!1):(i(function(){t.advance(n);n=0}),!1)}),this)},limit:function(n){return this._ctx.limit=Math.min(this._ctx.limit,n),t(this._ctx,function(t,i,r){return--n<=0&&i(r),n>=0}),this},until:function(i,r){var u=this._ctx;return e(function(){i(n(u))}),t(this._ctx,function(n,t,u){return i(n.value)?(t(u),r):!0}),this},first:function(t){var i=this;return e(function(){t(n(i._ctx))}),this.limit(1).toArray(function(n){return n[0]}).then(t)},last:function(n){return this.reverse().first(n)},and:function(i){var r=this;return e(function(){i(n(r._ctx))}),t(this._ctx,function(n){return i(n.value)}),f(this._ctx,i),this},or:function(n){return new ci(this._ctx.table,n,this)},reverse:function(){return this._ctx.dir=this._ctx.dir==="prev"?"next":"prev",this._ondirectionchange&&this._ondirectionchange(this._ctx.dir),this},desc:function(){return this.reverse()},eachKey:function(t){var i=this,r=this._ctx;return e(function(){t(n(i._ctx)[i._ctx.index])}),r.isPrimKey||(r.op="openKeyCursor"),this.each(function(n,i){t(i.key,i)})},eachUniqueKey:function(n){return this._ctx.unique="unique",this.eachKey(n)},keys:function(t){var u,i,r;return e(function(){t([n(i)[u._ctx.index]])}),u=this,i=this._ctx,i.isPrimKey||(i.op="openKeyCursor"),r=[],this.each(function(n,t){r.push(t.key)}).then(function(){return r}).then(t)},uniqueKeys:function(n){return this._ctx.unique="unique",this.keys(n)},firstKey:function(n){var t=this;return this.limit(1).keys(function(n){return n[0]}).then(n)},lastKey:function(n){return this.reverse().firstKey(n)},distinct:function(){var n={};return t(this._ctx,function(t){var i=t.primaryKey.toString(),r=n.hasOwnProperty(i);return n[i]=!0,!r}),this}}});y(rr).from(li).extend({modify:function(n){var a=this,t=this._ctx,r=t.table.hook,i=r.updating.fire,u=r.deleting.fire;return e(function(){typeof n=="function"&&n.call({value:t.table.schema.instanceTemplate},t.table.schema.instanceTemplate)}),this._write(function(r,e,v,y){function st(n,i){var r,u,f;if(et=i.primaryKey,r={primKey:i.primaryKey,value:n},w.call(r,n)!==!1)u=!r.hasOwnProperty("value"),f=u?i.delete():i.update(r.value),++ut,f.onerror=o(function(n){if(p.push(n),nt.push(r.primKey),r.onerror)r.onerror(n);return it(),!0},u?["deleting",n,"from",t.table.name]:["modifying",n,"on",t.table.name]),f.onsuccess=function(){if(r.onsuccess)r.onsuccess(r.value);++b;it()};else if(r.onsuccess)r.onsuccess(r.value)}function ot(n){return n&&(p.push(n),nt.push(et)),e(new d("Error modifying one or more objects",p,b,nt))}function it(){ft&&b+p.length===ut&&(p.length>0?ot():r(b))}var w,k,rt,g;typeof n=="function"?w=i===f&&u===f?n:function(t){var f=l(t),e,r;if(n.call(this,t)===!1)return!1;this.hasOwnProperty("value")?(e=dt(f,this.value),r=i.call(this,e,this.primKey,f,y),r&&(t=this.value,Object.keys(r).forEach(function(n){h(t,n,r[n])}))):u.call(this,this.primKey,t,y)}:i===f?(k=Object.keys(n),rt=k.length,w=function(t){for(var i,u,f=!1,r=0;r<rt;++r)i=k[r],u=n[i],c(t,i)!==u&&(h(t,i,u),f=!0);return f}):(g=n,n=tt(g),w=function(t){var u=!1,r=i.call(this,n,this.primKey,l(t),y);return r&&s(n,r),Object.keys(n).forEach(function(i){var r=n[i];c(t,i)!==r&&(h(t,i,r),u=!0)}),r&&(n=tt(g)),u});var ut=0,b=0,ft=!1,p=[],nt=[],et=null;a._iterate(st,function(){ft=!0;it()},ot,v)})},"delete":function(){return this.modify(function(){delete this.value})}});s(this,{Collection:li,Table:ei,Transaction:ir,Version:di,WhereClause:ci,WriteableCollection:rr,WriteableTable:tr});cr();hr.forEach(function(n){n(w)})}function f(){}function nt(n){return n}function lt(n,t){return n===nt?t:function(i){return t(n(i))}}function w(n,t){return function(){n.apply(this,arguments);t.apply(this,arguments)}}function at(n,t){return n===f?t:function(){var f=n.apply(this,arguments),r,u,e;return f!==i&&(arguments[0]=f),r=this.onsuccess,u=this.onerror,delete this.onsuccess,delete this.onerror,e=t.apply(this,arguments),r&&(this.onsuccess=this.onsuccess?w(r,this.onsuccess):r),u&&(this.onerror=this.onerror?w(u,this.onerror):u),e!==i?e:f}}function vt(n,t){return n===f?t:function(){var r=n.apply(this,arguments),f,e,u;return r!==i&&s(arguments[0],r),f=this.onsuccess,e=this.onerror,delete this.onsuccess,delete this.onerror,u=t.apply(this,arguments),f&&(this.onsuccess=this.onsuccess?w(f,this.onsuccess):f),e&&(this.onerror=this.onerror?w(e,this.onerror):e),r===i?u===i?i:u:u===i?r:s(r,u)}}function yt(n,t){return n===f?t:function(){return n.apply(this,arguments)===!1?!1:t.apply(this,arguments)}}function pt(n,t){return n===f?t:function(){return t.apply(this,arguments)===!1?!1:n.apply(this,arguments)}}function wt(n,t){return n===f?t:function(){n.apply(this,arguments);t.apply(this,arguments)}}function bt(n,t){return n===f?t:function(){var i=n.apply(this,arguments),r,u;return i&&typeof i.then=="function"?(r=this,u=arguments,i.then(function(){return t.apply(r,u)})):t.apply(this,arguments)}}function v(t){function i(n,t,i){if(Array.isArray(n))return c(n);if(typeof n=="object")return h(n);t||(t=yt);i||(i=f);var r={subscribers:[],fire:i,subscribe:function(n){r.subscribers.push(n);r.fire=t(r.fire,n)},unsubscribe:function(n){r.subscribers=r.subscribers.filter(function(t){return t!==n});r.fire=r.subscribers.reduce(t,i)}};return u[n]=e[n]=r,r}function h(t){Object.keys(t).forEach(function(r){var f=t[r],u;if(Array.isArray(f))i(r,t[r][0],t[r][1]);else if(f==="asap")u=i(r,null,function(){var t=arguments;u.subscribers.forEach(function(i){b(function(){i.apply(n,t)})})}),u.subscribe=function(n){u.subscribers.indexOf(n)===-1&&u.subscribers.push(n)},u.unsubscribe=function(n){var t=u.subscribers.indexOf(n);t!==-1&&u.subscribers.splice(t,1)};else throw new Error("Invalid event config");})}function c(n){function r(){if(t)return!1;t=!0}var t=!1;n.forEach(function(n){i(n).subscribe(r)})}var o=arguments,u={},e=function(n,i){if(i){var f=[].slice.call(arguments,1),r=u[n];return r.subscribe.apply(r,f),t}if(typeof n=="string")return u[n]},r,s;for(e.addEventType=i,r=1,s=o.length;r<s;++r)i(o[r]);return e}function kt(n){if(!n)throw new Error("Assertion failed");}function b(t){n.setImmediate?setImmediate(t):setTimeout(t,0)}function et(n){var t=setTimeout(n,1e3);clearTimeout(t)}function k(n,t,i){return function(){var u=r.PSD;r.PSD=i;try{n.apply(this,arguments)}catch(f){t(f)}finally{r.PSD=u}}}function c(n,t){var f,r,o,s,u,e;if(n.hasOwnProperty(t))return n[t];if(!t)return n;if(typeof t!="string"){for(f=[],r=0,o=t.length;r<o;++r)s=c(n,t[r]),f.push(s);return f}return(u=t.indexOf("."),u!==-1)?(e=n[t.substr(0,u)],e===i?i:c(e,t.substr(u+1))):i}function h(n,t,r){var u,c,e,f,s,o;if(n&&t!==i)if(typeof t!="string"&&"length"in t)for(kt(typeof r!="string"&&"length"in r),u=0,c=t.length;u<c;++u)h(n,t[u],r[u]);else e=t.indexOf("."),e!==-1?(f=t.substr(0,e),s=t.substr(e+1),s===""?r===i?delete n[f]:n[f]=r:(o=n[f],o||(o=n[f]={}),h(o,s,r))):r===i?delete n[t]:n[t]=r}function ot(n,t){h(n,t,i)}function tt(n){var i={};for(var t in n)n.hasOwnProperty(t)&&(i[t]=n[t]);return i}function l(n){var t,i,u,r;if(!n||typeof n!="object")return n;if(Array.isArray(n))for(t=[],i=0,u=n.length;i<u;++i)t.push(l(n[i]));else if(n instanceof Date)t=new Date,t.setTime(n.getTime());else{t=n.constructor?Object.create(n.constructor.prototype):{};for(r in n)n.hasOwnProperty(r)&&(t[r]=l(n[r]))}return t}function dt(n,t){var u={};for(var r in n)n.hasOwnProperty(r)&&(t.hasOwnProperty(r)?n[r]!==t[r]&&JSON.stringify(n[r])!=JSON.stringify(t[r])&&(u[r]=t[r]):u[r]=i);for(r in t)t.hasOwnProperty(r)&&!n.hasOwnProperty(r)&&(u[r]=t[r]);return u}function st(n){if(typeof n=="function")return new n;if(Array.isArray(n))return[st(n[0])];if(n&&typeof n=="object"){var t={};return it(t,n),t}return n}function it(n,t){Object.keys(t).forEach(function(i){var r=st(t[i]);n[i]=r})}function o(n,t){return function(i){var r=i&&i.target.error||new Error,u;return t&&(u=" occurred when "+t.map(function(n){switch(typeof n){case"function":return n();case"string":return n;default:return JSON.stringify(n)}}).join(" "),r.name?r.toString=function(){return r.name+u+(r.message?". "+r.message:"")}:r=r+u),n(r),i&&(i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault()),!1}}function gt(n){try{throw n;}catch(t){return t}}function ht(n){n.preventDefault()}function rt(n){var t,i=u.dependencies.localStorage;if(!i)return n([]);try{t=JSON.parse(i.getItem("Dexie.DatabaseNames")||"[]")}catch(r){t=[]}n(t)&&i.setItem("Dexie.DatabaseNames",JSON.stringify(t))}function a(n,t,i,r,u,f,e){this.name=n;this.keyPath=t;this.unique=i;this.multi=r;this.auto=u;this.compound=f;this.dotted=e;var o=typeof t=="string"?t:t&&"["+[].join.call(t,"+")+"]";this.src=(i?"&":"")+(r?"*":"")+(u?"++":"")+o}function ut(n,t,i,r){this.name=n;this.primKey=t||new a;this.indexes=i||[new a];this.instanceTemplate=r;this.mappedClass=null;this.idxByName=i.reduce(function(n,t){return n[t.name]=t,n},{})}function d(n,t,i,r){this.name="ModifyError";this.failures=t;this.failedKeys=r;this.successCount=i;this.message=t.join("\n")}function ft(n){return n.length===1?n[0]:n}function ct(){var n=u.dependencies.indexedDB,t=n&&(n.getDatabaseNames||n.webkitGetDatabaseNames);return t&&t.bind(n)}var r=function(){function y(n){u.push([n,a.call(arguments,1)])}function p(){var r=u,t,f,i;for(u=[],t=0,f=r.length;t<f;++t)i=r[t],i[0].apply(n,i[1])}function t(n){if(typeof this!="object")throw new TypeError("Promises must be constructed via new");if(typeof n!="function")throw new TypeError("not a function");this._state=null;this._value=null;this._deferreds=[];this._catched=!1;var r=this,u=!0;this._PSD=t.PSD;try{k(this,n,function(n){u?i(c,r,n):c(r,n)},function(n){return u?(i(s,r,n),!1):s(r,n)})}finally{u=!1}}function o(n,f){var s,o,l,a,b,c;if(n._state===null){n._deferreds.push(f);return}if(s=n._state?f.onFulfilled:f.onRejected,s===null)return(n._state?f.resolve:f.reject)(n._value);l=r;r=!1;i=y;try{a=t.PSD;t.PSD=n._PSD;o=s(n._value);n._state||o&&typeof o.then=="function"&&o._state===!1||w(n);f.resolve(o)}catch(v){if(b=f.reject(v),!b&&n.onuncatched)try{n.onuncatched(v)}catch(v){}}finally{if(t.PSD=a,l){do{while(u.length>0)p();if(c=e.pop(),c)try{c()}catch(v){}}while(e.length>0||u.length>0);i=h;r=!0}}}function d(n){var f=r,t;r=!1;i=y;try{n()}finally{if(f){do{while(u.length>0)p();if(t=e.pop(),t)try{t()}catch(o){}}while(e.length>0||u.length>0);i=h;r=!0}}}function w(n){n._catched=!0;n._parent&&w(n._parent)}function c(n,i){var r=t.PSD;t.PSD=n._PSD;try{if(i===n)throw new TypeError("A promise cannot be resolved with itself.");if(i&&(typeof i=="object"||typeof i=="function")&&typeof i.then=="function"){k(n,function(n,t){i.then(n,t)},function(t){c(n,t)},function(t){s(n,t)});return}n._state=!0;n._value=i;b.call(n)}catch(u){s(u)}finally{t.PSD=r}}function s(n,i){var r=t.PSD;if(t.PSD=n._PSD,n._state=!1,n._value=i,b.call(n),!n._catched)try{if(n.onuncatched)n.onuncatched(n._value);t.on.error.fire(n._value)}catch(u){}return t.PSD=r,n._catched}function b(){for(var n=0,t=this._deferreds.length;n<t;n++)o(this,this._deferreds[n]);this._deferreds=[]}function l(n,t,i,r){this.onFulfilled=typeof n=="function"?n:null;this.onRejected=typeof t=="function"?t:null;this.resolve=i;this.reject=r}function k(n,t,i,r){var u=!1;try{t(function(n){u||(u=!0,i(n))},function(t){return u?n._catched:(u=!0,r(t))})}catch(f){return u?void 0:r(f)}}var a=[].slice,h=typeof setImmediate=="undefined"?function(t){var i=arguments;setTimeout(function(){t.apply(n,a.call(i,1))},0)}:setImmediate,i=h,r=!0,u=[],e=[];return t.on=v(null,"error"),t.all=function(){var n=Array.prototype.slice.call(arguments.length===1&&Array.isArray(arguments[0])?arguments[0]:arguments);return new t(function(t,i){function f(r,e){try{if(e&&(typeof e=="object"||typeof e=="function")){var o=e.then;if(typeof o=="function"){o.call(e,function(n){f(r,n)},i);return}}n[r]=e;--u==0&&t(n)}catch(s){i(s)}}var u,r;if(n.length===0)return t([]);for(u=n.length,r=0;r<n.length;r++)f(r,n[r])})},t.prototype.then=function(n,r){var f=this,u=new t(function(t,u){f._state===null?o(f,new l(n,r,t,u)):i(o,f,new l(n,r,t,u))});return u._PSD=this._PSD,u.onuncatched=this.onuncatched,u._parent=this,u},t.prototype._then=function(n,t){o(this,new l(n,t,f,f))},t.prototype["catch"]=function(n){if(arguments.length===1)return this.then(null,n);var i=arguments[0],r=arguments[1];return typeof i=="function"?this.then(null,function(n){return n instanceof i?r(n):t.reject(n)}):this.then(null,function(n){return n&&n.name===i?r(n):t.reject(n)})},t.prototype["finally"]=function(n){return this.then(function(t){return n(),t},function(i){return n(),t.reject(i)})},t.prototype.onuncatched=null,t.resolve=function(n){var i=new t(function(){});return i._state=!0,i._value=n,i},t.reject=function(n){var i=new t(function(){});return i._state=!1,i._value=n,i},t.race=function(n){return new t(function(t,i){n.map(function(n){n.then(t,i)})})},t.PSD=null,t.newPSD=function(n){var i=t.PSD;t.PSD=i?Object.create(i):{};try{return n()}finally{t.PSD=i}},t._rootExec=d,t._tickFinalize=function(n){if(r)throw new Error("Not in a virtual tick");e.push(n)},t}(),e=function(){},g;y(d).from(Error);u.delete=function(n){var t=new u(n),i=t.delete();return i.onblocked=function(n){t.on("blocked",n);return this},i};u.getDatabaseNames=function(n){return new r(function(n,t){var r=ct(),i;r?(i=r(),i.onsuccess=function(t){n([].slice.call(t.target.result,0))},i.onerror=o(t)):rt(function(t){return n(t),!1})}).then(n)};u.defineClass=function(n){function t(n){n&&s(this,n)}return it(t.prototype,n),t};u.ignoreTransaction=function(n){return r.newPSD(function(){return r.PSD.trans=null,n()})};u.spawn=function(){return n.console&&console.warn("Dexie.spawn() is deprecated. Use Dexie.ignoreTransaction() instead."),u.ignoreTransaction.apply(this,arguments)};u.vip=function(n){return r.newPSD(function(){return r.PSD.letThrough=!0,n()})};Object.defineProperty(u,"currentTransaction",{get:function(){return r.PSD&&r.PSD.trans||null}});u.Promise=r;u.derive=y;u.extend=s;u.override=p;u.events=v;u.getByKeyPath=c;u.setByKeyPath=h;u.delByKeyPath=ot;u.shallowClone=tt;u.deepClone=l;u.addons=[];u.fakeAutoComplete=e;u.asap=b;u.ModifyError=d;u.MultiModifyError=d;u.IndexSpec=a;u.TableSchema=ut;g=n.idbModules&&n.idbModules.shimIndexedDB?n.idbModules:{};u.dependencies={indexedDB:g.shimIndexedDB||n.indexedDB||n.mozIndexedDB||n.webkitIndexedDB||n.msIndexedDB,IDBKeyRange:g.IDBKeyRange||n.IDBKeyRange||n.webkitIDBKeyRange,IDBTransaction:g.IDBTransaction||n.IDBTransaction||n.webkitIDBTransaction,Error:n.Error||String,SyntaxError:n.SyntaxError||String,TypeError:n.TypeError||String,DOMError:n.DOMError||String,localStorage:(typeof chrome!="undefined"&&chrome!==null?chrome.storage:void 0)!=null?null:n.localStorage};u.version=1.1;t("Dexie",u);et(function(){e=et})}).apply(null,typeof define=="function"&&define.amd?[self||window,function(n,t){define(n,function(){return t})}]:typeof global!="undefined"&&typeof module!="undefined"&&module.exports?[global,function(n,t){module.exports=t}]:[self||window,function(n,t){(self||window)[n]=t}]);
+//# sourceMappingURL=Dexie.min.js.map
diff --git a/gui/html/js/ndn-js.min.js b/gui/html/js/ndn-js.min.js
index 092e995..c73b511 100644
--- a/gui/html/js/ndn-js.min.js
+++ b/gui/html/js/ndn-js.min.js
@@ -1,224 +1,165 @@
-var Closure=function(){this.ndn_data=null;this.ndn_data_dirty=!1};Closure.RESULT_ERR=-1;Closure.RESULT_OK=0;Closure.RESULT_REEXPRESS=1;Closure.RESULT_INTEREST_CONSUMED=2;Closure.RESULT_VERIFY=3;Closure.RESULT_FETCHKEY=4;Closure.UPCALL_FINAL=0;Closure.UPCALL_INTEREST=1;Closure.UPCALL_CONSUMED_INTEREST=2;Closure.UPCALL_CONTENT=3;Closure.UPCALL_INTEREST_TIMED_OUT=4;Closure.UPCALL_CONTENT_UNVERIFIED=5;Closure.UPCALL_CONTENT_BAD=6;Closure.prototype.upcall=function(){return Closure.RESULT_OK};
-var UpcallInfo=function(a,b,c,d){this.ndn=a;this.interest=b;this.matchedComps=c;this.contentObject=d};UpcallInfo.prototype.toString=function(){var a="ndn = "+this.ndn,a=a+("\nInterest = "+this.interest),a=a+("\nmatchedComps = "+this.matchedComps);return a+="\nContentObject: "+this.contentObject};
-var WebSocketTransport=function(){if(!WebSocket)throw Error("WebSocket support is not available on this platform.");this.elementReader=this.connectedPort=this.connectedHost=this.ws=null;this.defaultGetHostAndPort=NDN.makeShuffledGetHostAndPort(["A.ws.ndn.ucla.edu","B.ws.ndn.ucla.edu","C.ws.ndn.ucla.edu","D.ws.ndn.ucla.edu","E.ws.ndn.ucla.edu"],9696)};
-WebSocketTransport.prototype.connect=function(a,b){null!=this.ws&&delete this.ws;this.ws=new WebSocket("ws://"+a.host+":"+a.port);0<LOG&&console.log("ws connection created.");this.connectedHost=a.host;this.connectedPort=a.port;this.ws.binaryType="arraybuffer";this.elementReader=new BinaryXmlElementReader(a);var c=this;this.ws.onmessage=function(a){a=a.data;if(null==a||void 0==a||""==a)console.log("INVALID ANSWER");else if(a instanceof ArrayBuffer){a=new Uint8Array(a);3<LOG&&console.log("BINARY RESPONSE IS "+
-DataUtils.toHex(a));try{c.elementReader.onReceivedData(a)}catch(b){console.log("NDN.ws.onmessage exception: "+b)}}};this.ws.onopen=function(a){3<LOG&&console.log(a);3<LOG&&console.log("ws.onopen: WebSocket connection opened.");3<LOG&&console.log("ws.onopen: ReadyState: "+this.readyState);b()};this.ws.onerror=function(a){console.log("ws.onerror: ReadyState: "+this.readyState);console.log(a);console.log("ws.onerror: WebSocket error: "+a.data)};this.ws.onclose=function(){console.log("ws.onclose: WebSocket connection closed.");
-c.ws=null;a.readyStatus=NDN.CLOSED;a.onclose()}};WebSocketTransport.prototype.send=function(a){if(null!=this.ws){var b=new Uint8Array(a.length);b.set(a);this.ws.send(b.buffer);3<LOG&&console.log("ws.send() returned.")}else console.log("WebSocket connection is not established.")};
-var NDNProtocolDTags={Any:13,Name:14,Component:15,Certificate:16,Collection:17,CompleteName:18,Content:19,SignedInfo:20,ContentDigest:21,ContentHash:22,Count:24,Header:25,Interest:26,Key:27,KeyLocator:28,KeyName:29,Length:30,Link:31,LinkAuthenticator:32,NameComponentCount:33,RootDigest:36,Signature:37,Start:38,Timestamp:39,Type:40,Nonce:41,Scope:42,Exclude:43,Bloom:44,BloomSeed:45,AnswerOriginKind:47,InterestLifetime:48,Witness:53,SignatureBits:54,DigestAlgorithm:55,BlockSize:56,FreshnessSeconds:58,
-FinalBlockID:59,PublisherPublicKeyDigest:60,PublisherCertificateDigest:61,PublisherIssuerKeyDigest:62,PublisherIssuerCertificateDigest:63,ContentObject:64,WrappedKey:65,WrappingKeyIdentifier:66,WrapAlgorithm:67,KeyAlgorithm:68,Label:69,EncryptedKey:70,EncryptedNonceKey:71,WrappingKeyName:72,Action:73,FaceID:74,IPProto:75,Host:76,Port:77,MulticastInterface:78,ForwardingFlags:79,FaceInstance:80,ForwardingEntry:81,MulticastTTL:82,MinSuffixComponents:83,MaxSuffixComponents:84,ChildSelector:85,RepositoryInfo:86,
-Version:87,RepositoryVersion:88,GlobalPrefix:89,LocalName:90,Policy:91,Namespace:92,GlobalPrefixName:93,PolicyVersion:94,KeyValueSet:95,KeyValuePair:96,IntegerValue:97,DecimalValue:98,StringValue:99,BinaryValue:100,NameValue:101,Entry:102,ACL:103,ParameterizedName:104,Prefix:105,Suffix:106,Root:107,ProfileName:108,Parameters:109,InfoString:110,StatusResponse:112,StatusCode:113,StatusText:114,SyncNode:115,SyncNodeKind:116,SyncNodeElement:117,SyncVersion:118,SyncNodeElements:119,SyncContentHash:120,
-SyncLeafCount:121,SyncTreeDepth:122,SyncByteCount:123,ConfigSlice:124,ConfigSliceList:125,ConfigSliceOp:126,NDNProtocolDataUnit:17702112,NDNPROTOCOL_DATA_UNIT:"NDNProtocolDataUnit"},NDNProtocolDTagsStrings=[null,null,null,null,null,null,null,null,null,null,null,null,null,"Any","Name","Component","Certificate","Collection","CompleteName","Content","SignedInfo","ContentDigest","ContentHash",null,"Count","Header","Interest","Key","KeyLocator","KeyName","Length","Link","LinkAuthenticator","NameComponentCount",
-null,null,"RootDigest","Signature","Start","Timestamp","Type","Nonce","Scope","Exclude","Bloom","BloomSeed",null,"AnswerOriginKind","InterestLifetime",null,null,null,null,"Witness","SignatureBits","DigestAlgorithm","BlockSize",null,"FreshnessSeconds","FinalBlockID","PublisherPublicKeyDigest","PublisherCertificateDigest","PublisherIssuerKeyDigest","PublisherIssuerCertificateDigest","ContentObject","WrappedKey","WrappingKeyIdentifier","WrapAlgorithm","KeyAlgorithm","Label","EncryptedKey","EncryptedNonceKey",
-"WrappingKeyName","Action","FaceID","IPProto","Host","Port","MulticastInterface","ForwardingFlags","FaceInstance","ForwardingEntry","MulticastTTL","MinSuffixComponents","MaxSuffixComponents","ChildSelector","RepositoryInfo","Version","RepositoryVersion","GlobalPrefix","LocalName","Policy","Namespace","GlobalPrefixName","PolicyVersion","KeyValueSet","KeyValuePair","IntegerValue","DecimalValue","StringValue","BinaryValue","NameValue","Entry","ACL","ParameterizedName","Prefix","Suffix","Root","ProfileName",
-"Parameters","InfoString",null,"StatusResponse","StatusCode","StatusText","SyncNode","SyncNodeKind","SyncNodeElement","SyncVersion","SyncNodeElements","SyncContentHash","SyncLeafCount","SyncTreeDepth","SyncByteCount","ConfigSlice","ConfigSliceList","ConfigSliceOp"],NDNTime=function(a){this.NANOS_MAX=999877929;"number"==typeof a?this.msec=a:1<LOG&&console.log("UNRECOGNIZED TYPE FOR TIME")};NDNTime.prototype.getJavascriptDate=function(){var a=new Date;a.setTime(this.msec);return a};
-var ExponentialReExpressClosure=function(a,b){Closure.call(this);this.callerClosure=a;b=b||{};this.maxInterestLifetime=b.maxInterestLifetime||16E3};
-ExponentialReExpressClosure.prototype.upcall=function(a,b){try{if(a==Closure.UPCALL_INTEREST_TIMED_OUT){var c=b.interest.interestLifetime;if(null==c)return this.callerClosure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,b);c*=2;if(c>this.maxInterestLifetime)return this.callerClosure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,b);var d=b.interest.clone();d.interestLifetime=c;b.ndn.expressInterest(d.name,this,d);return Closure.RESULT_OK}return this.callerClosure.upcall(a,b)}catch(e){return console.log("ExponentialReExpressClosure.upcall exception: "+
-e),Closure.RESULT_ERR}};var Name=function Name(b){if("string"==typeof b)3<LOG&&console.log("Content Name String "+b),this.components=Name.createNameArray(b);else if("object"===typeof b)if(this.components=[],b instanceof Name)this.add(b);else for(var c=0;c<b.length;++c)this.add(b[c]);else null==b?this.components=[]:1<LOG&&console.log("NO CONTENT NAME GIVEN")};Name.prototype.getName=function(){return this.to_uri()};
-Name.createNameArray=function(a){a=a.trim();if(0>=a.length)return[];var b=a.indexOf(":");if(0<=b){var c=a.indexOf("/");if(0>c||b<c)a=a.substr(b+1,a.length-b-1).trim()}if("/"==a[0])if(2<=a.length&&"/"==a[1]){b=a.indexOf("/",2);if(0>b)return[];a=a.substr(b+1,a.length-b-1).trim()}else a=a.substr(1,a.length-1).trim();a=a.split("/");for(b=0;b<a.length;++b)c=Name.fromEscapedString(a[b]),null==c?(a.splice(b,1),--b):a[b]=c;return a};
-Name.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());for(this.components=[];a.peekStartElement(NDNProtocolDTags.Component);)this.add(a.readBinaryElement(NDNProtocolDTags.Component));a.readEndElement()};Name.prototype.to_ndnb=function(a){if(null==this.components)throw Error("CANNOT ENCODE EMPTY CONTENT NAME");a.writeStartElement(this.getElementLabel());for(var b=this.components.length,c=0;c<b;c++)a.writeElement(NDNProtocolDTags.Component,this.components[c]);a.writeEndElement()};
-Name.prototype.getElementLabel=function(){return NDNProtocolDTags.Name};
-Name.prototype.add=function(a){var b;if("string"==typeof a)b=DataUtils.stringToUtf8Array(a);else if("object"==typeof a&&a instanceof Uint8Array)b=new Uint8Array(a);else if("object"==typeof a&&a instanceof ArrayBuffer)b=new Uint8Array(new ArrayBuffer(a.byteLength)),b.set(new Uint8Array(a));else{if("object"==typeof a&&a instanceof Name){a=a==this?this.components.slice(0,this.components.length):a.components;for(b=0;b<a.length;++b)this.components.push(new Uint8Array(a[b]));return this}if("object"==typeof a)b=
-new Uint8Array(a);else throw Error("Cannot add Name element at index "+this.components.length+": Invalid type");}this.components.push(b);return this};Name.prototype.addSegment=function(a){for(var b=1,c=a;0<c;)b++,c>>=8;b=new Uint8Array(b);c=0;b[c]=0;for(c++;0<a;)b[c]=a&255,a>>=8,c++;this.components.push(b);return this};Name.prototype.to_uri=function(){if(0==this.components.length)return"/";for(var a="",b=0;b<this.components.length;++b)a+="/"+Name.toEscapedString(this.components[b]);return a};
-Name.prototype.addSegment=function(a){a=DataUtils.nonNegativeIntToBigEndian(a);var b=new Uint8Array(a.length+1);b.set(a,1);this.components.push(b);return this};Name.prototype.getPrefix=function(a){return new Name(this.components.slice(0,a))};Name.prototype.cut=function(){return new Name(this.components.slice(0,this.components.length-1))};Name.prototype.getComponent=function(a){var b=new ArrayBuffer(this.components[a].length);(new Uint8Array(b)).set(this.components[a]);return b};
-Name.prototype.indexOfFileName=function(){for(var a=this.components.length-1;0<=a;--a){var b=this.components[a];if(!(0>=b.length)&&!(0==b[0]||192==b[0]||193==b[0]||245<=b[0]&&255>=b[0]))return a}return-1};Name.prototype.equalsName=function(a){if(this.components.length!=a.components.length)return!1;for(var b=this.components.length-1;0<=b;--b)if(!DataUtils.arraysEqual(this.components[b],a.components[b]))return!1;return!0};
-Name.prototype.getContentDigestValue=function(){for(var a=this.components.length-1;0<=a;--a){var b=Name.getComponentContentDigestValue(this.components[a]);if(null!=b)return b}return null};
-Name.getComponentContentDigestValue=function(a){return a.length==Name.ContentDigestPrefix.length+32+Name.ContentDigestSuffix.length&&DataUtils.arraysEqual(a.subarray(0,Name.ContentDigestPrefix.length),Name.ContentDigestPrefix)&&DataUtils.arraysEqual(a.subarray(a.length-Name.ContentDigestSuffix.length,a.length),Name.ContentDigestSuffix)?a.subarray(Name.ContentDigestPrefix.length,Name.ContentDigestPrefix.length+32):null};Name.ContentDigestPrefix=new Uint8Array([193,46,77,46,71,193,1,170,2,133]);
-Name.ContentDigestSuffix=new Uint8Array([0]);Name.toEscapedString=function(a){for(var b="",c=!1,d=0;d<a.length;++d)if(46!=a[d]){c=!0;break}if(c)for(d=0;d<a.length;++d)c=a[d],b=48<=c&&57>=c||65<=c&&90>=c||97<=c&&122>=c||43==c||45==c||46==c||95==c?b+String.fromCharCode(c):b+("%"+(16>c?"0":"")+c.toString(16).toUpperCase());else{b="...";for(d=0;d<a.length;++d)b+="."}return b};
-Name.fromEscapedString=function(a){a=unescape(a.trim());return null==a.match(/[^.]/)?2>=a.length?null:DataUtils.toNumbersFromString(a.substr(3,a.length-3)):DataUtils.toNumbersFromString(a)};Name.prototype.match=function(a){var b=this.components;a=a.components;if(b.length>a.length)return!1;for(var c=0;c<b.length;++c)if(!DataUtils.arraysEqual(b[c],a[c]))return!1;return!0};
-var ContentObject=function(a,b,c,d){this.name="string"==typeof a?new Name(a):a;this.signedInfo=b;this.content="string"==typeof c?DataUtils.toNumbersFromString(c):c;this.signature=d;this.rawSignatureData=this.endContent=this.endSIG=this.startSIG=null};
-ContentObject.prototype.sign=function(){var a=this.encodeObject(this.name),b=this.encodeObject(this.signedInfo),c=this.encodeContent(),d=new ArrayBuffer(a.length+b.length+c.length),d=new Uint8Array(d);d.set(a,0);d.set(b,a.length);d.set(c,a.length+b.length);4<LOG&&console.log("Signature Data is (binary) "+d);4<LOG&&console.log("Signature Data is (RawString)");4<LOG&&console.log(DataUtils.toString(d));a=new RSAKey;a.readPrivateKeyFromPEMString(globalKeyManager.privateKey);a=a.signByteArrayWithSHA256(d);
-4<LOG&&console.log("SIGNATURE SAVED IS");4<LOG&&console.log(a);4<LOG&&console.log(DataUtils.toNumbers(a.trim()));this.signature.signature=DataUtils.toNumbers(a.trim())};ContentObject.prototype.encodeObject=function(a){var b=new BinaryXMLEncoder;a.to_ndnb(b);return b.getReducedOstream()};ContentObject.prototype.encodeContent=function(){var a=new BinaryXMLEncoder;a.writeElement(NDNProtocolDTags.Content,this.content);return a.getReducedOstream()};
-ContentObject.prototype.saveRawData=function(a){this.rawSignatureData=a.subarray(this.startSIG,this.endSIG)};
-ContentObject.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(NDNProtocolDTags.Signature)&&(this.signature=new Signature,this.signature.from_ndnb(a));this.startSIG=a.offset;this.name=new Name;this.name.from_ndnb(a);a.peekStartElement(NDNProtocolDTags.SignedInfo)&&(this.signedInfo=new SignedInfo,this.signedInfo.from_ndnb(a));this.content=a.readBinaryElement(NDNProtocolDTags.Content);this.endSIG=a.offset;a.readEndElement();this.saveRawData(a.istream)};
-ContentObject.prototype.to_ndnb=function(a){a.writeStartElement(this.getElementLabel());null!=this.signature&&this.signature.to_ndnb(a);this.startSIG=a.offset;null!=this.name&&this.name.to_ndnb(a);null!=this.signedInfo&&this.signedInfo.to_ndnb(a);a.writeElement(NDNProtocolDTags.Content,this.content);this.endSIG=a.offset;a.writeEndElement();this.saveRawData(a.ostream)};ContentObject.prototype.getElementLabel=function(){return NDNProtocolDTags.ContentObject};
-var Signature=function(a,b,c){this.Witness=a;this.signature=b;this.digestAlgorithm=c};
-Signature.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());4<LOG&&console.log("STARTED DECODING SIGNATURE");a.peekStartElement(NDNProtocolDTags.DigestAlgorithm)&&(4<LOG&&console.log("DIGIEST ALGORITHM FOUND"),this.digestAlgorithm=a.readUTF8Element(NDNProtocolDTags.DigestAlgorithm));a.peekStartElement(NDNProtocolDTags.Witness)&&(4<LOG&&console.log("WITNESS FOUND"),this.Witness=a.readBinaryElement(NDNProtocolDTags.Witness));4<LOG&&console.log("SIGNATURE FOUND");this.signature=
-a.readBinaryElement(NDNProtocolDTags.SignatureBits);a.readEndElement()};
-Signature.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode: field values missing.");a.writeStartElement(this.getElementLabel());null!=this.digestAlgorithm&&!this.digestAlgorithm.equals(NDNDigestHelper.DEFAULT_DIGEST_ALGORITHM)&&a.writeElement(NDNProtocolDTags.DigestAlgorithm,OIDLookup.getDigestOID(this.DigestAlgorithm));null!=this.Witness&&a.writeElement(NDNProtocolDTags.Witness,this.Witness);a.writeElement(NDNProtocolDTags.SignatureBits,this.signature);a.writeEndElement()};
-Signature.prototype.getElementLabel=function(){return NDNProtocolDTags.Signature};Signature.prototype.validate=function(){return null!=this.signature};
-var ContentType={DATA:0,ENCR:1,GONE:2,KEY:3,LINK:4,NACK:5},ContentTypeValue={"0":787648,1:1101969,2:1631044,3:2639423,4:2917194,5:3408010},ContentTypeValueReverse={787648:0,1101969:1,1631044:2,2639423:3,2917194:4,3408010:5},SignedInfo=function(a,b,c,d,e,f){this.publisher=a;this.timestamp=b;this.type=c;this.locator=d;this.freshnessSeconds=e;this.finalBlockID=f;this.setFields()};
-SignedInfo.prototype.setFields=function(){var a=globalKeyManager.publicKey;4<LOG&&console.log("PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ");4<LOG&&console.log(a);var a=DataUtils.toNumbers(globalKeyManager.publicKey),b=hex_sha256_from_bytes(a);this.publisher=new PublisherPublicKeyDigest(DataUtils.toNumbers(b));b=(new Date).getTime();this.timestamp=new NDNTime(b);4<LOG&&console.log("TIME msec is");4<LOG&&console.log(this.timestamp.msec);this.type=0;4<LOG&&console.log("PUBLIC KEY TO WRITE TO CONTENT OBJECT IS ");
-4<LOG&&console.log(a);this.locator=new KeyLocator(a,KeyLocatorType.KEY)};
-SignedInfo.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)&&(4<LOG&&console.log("DECODING PUBLISHER KEY"),this.publisher=new PublisherPublicKeyDigest,this.publisher.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.Timestamp)&&(4<LOG&&console.log("DECODING TIMESTAMP"),this.timestamp=a.readDateTime(NDNProtocolDTags.Timestamp));if(a.peekStartElement(NDNProtocolDTags.Type)){var b=a.readBinaryElement(NDNProtocolDTags.Type);
-4<LOG&&console.log("Binary Type of of Signed Info is "+b);this.type=b;if(null==this.type)throw Error("Cannot parse signedInfo type: bytes.");}else this.type=ContentType.DATA;a.peekStartElement(NDNProtocolDTags.FreshnessSeconds)&&(this.freshnessSeconds=a.readIntegerElement(NDNProtocolDTags.FreshnessSeconds),4<LOG&&console.log("FRESHNESS IN SECONDS IS "+this.freshnessSeconds));a.peekStartElement(NDNProtocolDTags.FinalBlockID)&&(4<LOG&&console.log("DECODING FINAL BLOCKID"),this.finalBlockID=a.readBinaryElement(NDNProtocolDTags.FinalBlockID));
-a.peekStartElement(NDNProtocolDTags.KeyLocator)&&(4<LOG&&console.log("DECODING KEY LOCATOR"),this.locator=new KeyLocator,this.locator.from_ndnb(a));a.readEndElement()};
-SignedInfo.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode : field values missing.");a.writeStartElement(this.getElementLabel());null!=this.publisher&&(3<LOG&&console.log("ENCODING PUBLISHER KEY"+this.publisher.publisherPublicKeyDigest),this.publisher.to_ndnb(a));null!=this.timestamp&&a.writeDateTime(NDNProtocolDTags.Timestamp,this.timestamp);null!=this.type&&0!=this.type&&a.writeElement(NDNProtocolDTags.type,this.type);null!=this.freshnessSeconds&&a.writeElement(NDNProtocolDTags.FreshnessSeconds,
-this.freshnessSeconds);null!=this.finalBlockID&&a.writeElement(NDNProtocolDTags.FinalBlockID,this.finalBlockID);null!=this.locator&&this.locator.to_ndnb(a);a.writeEndElement()};SignedInfo.prototype.valueToType=function(){return null};SignedInfo.prototype.getElementLabel=function(){return NDNProtocolDTags.SignedInfo};SignedInfo.prototype.validate=function(){return null==this.publisher||null==this.timestamp||null==this.locator?!1:!0};
-var DateFormat=function(){var a=/d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,b=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,c=/[^-+\dA-Z]/g,d=function(a,b){a=String(a);for(b=b||2;a.length<b;)a="0"+a;return a};return function(e,f,g){var h=dateFormat;1==arguments.length&&("[object String]"==Object.prototype.toString.call(e)&&!/\d/.test(e))&&(f=e,e=void 0);e=e?new Date(e):new Date;if(isNaN(e))throw SyntaxError("invalid date");
-f=String(h.masks[f]||f||h.masks["default"]);"UTC:"==f.slice(0,4)&&(f=f.slice(4),g=!0);var j=g?"getUTC":"get",l=e[j+"Date"](),n=e[j+"Day"](),m=e[j+"Month"](),p=e[j+"FullYear"](),k=e[j+"Hours"](),q=e[j+"Minutes"](),s=e[j+"Seconds"](),j=e[j+"Milliseconds"](),r=g?0:e.getTimezoneOffset(),t={d:l,dd:d(l),ddd:h.i18n.dayNames[n],dddd:h.i18n.dayNames[n+7],m:m+1,mm:d(m+1),mmm:h.i18n.monthNames[m],mmmm:h.i18n.monthNames[m+12],yy:String(p).slice(2),yyyy:p,h:k%12||12,hh:d(k%12||12),H:k,HH:d(k),M:q,MM:d(q),s:s,
-ss:d(s),l:d(j,3),L:d(99<j?Math.round(j/10):j),t:12>k?"a":"p",tt:12>k?"am":"pm",T:12>k?"A":"P",TT:12>k?"AM":"PM",Z:g?"UTC":(String(e).match(b)||[""]).pop().replace(c,""),o:(0<r?"-":"+")+d(100*Math.floor(Math.abs(r)/60)+Math.abs(r)%60,4),S:["th","st","nd","rd"][3<l%10?0:(10!=l%100-l%10)*l%10]};return f.replace(a,function(a){return a in t?t[a]:a.slice(1,a.length-1)})}}();
-DateFormat.masks={"default":"ddd mmm dd yyyy HH:MM:ss",shortDate:"m/d/yy",mediumDate:"mmm d, yyyy",longDate:"mmmm d, yyyy",fullDate:"dddd, mmmm d, yyyy",shortTime:"h:MM TT",mediumTime:"h:MM:ss TT",longTime:"h:MM:ss TT Z",isoDate:"yyyy-mm-dd",isoTime:"HH:MM:ss",isoDateTime:"yyyy-mm-dd'T'HH:MM:ss",isoUtcDateTime:"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"};DateFormat.i18n={dayNames:"Sun Mon Tue Wed Thu Fri Sat Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),monthNames:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December".split(" ")};
-Date.prototype.format=function(a,b){return dateFormat(this,a,b)};var Interest=function(a,b,c,d,e,f,g,h,j,l,n){this.name=a;this.faceInstance=b;this.maxSuffixComponents=d;this.minSuffixComponents=c;this.publisherPublicKeyDigest=e;this.exclude=f;this.childSelector=g;this.answerOriginKind=h;this.scope=j;this.interestLifetime=l;this.nonce=n};Interest.RECURSIVE_POSTFIX="*";Interest.CHILD_SELECTOR_LEFT=0;Interest.CHILD_SELECTOR_RIGHT=1;Interest.ANSWER_CONTENT_STORE=1;Interest.ANSWER_GENERATED=2;
-Interest.ANSWER_STALE=4;Interest.MARK_STALE=16;Interest.DEFAULT_ANSWER_ORIGIN_KIND=Interest.ANSWER_CONTENT_STORE|Interest.ANSWER_GENERATED;
-Interest.prototype.from_ndnb=function(a){a.readStartElement(NDNProtocolDTags.Interest);this.name=new Name;this.name.from_ndnb(a);a.peekStartElement(NDNProtocolDTags.MinSuffixComponents)&&(this.minSuffixComponents=a.readIntegerElement(NDNProtocolDTags.MinSuffixComponents));a.peekStartElement(NDNProtocolDTags.MaxSuffixComponents)&&(this.maxSuffixComponents=a.readIntegerElement(NDNProtocolDTags.MaxSuffixComponents));a.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)&&(this.publisherPublicKeyDigest=
-new PublisherPublicKeyDigest,this.publisherPublicKeyDigest.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.Exclude)&&(this.exclude=new Exclude,this.exclude.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.ChildSelector)&&(this.childSelector=a.readIntegerElement(NDNProtocolDTags.ChildSelector));a.peekStartElement(NDNProtocolDTags.AnswerOriginKind)&&(this.answerOriginKind=a.readIntegerElement(NDNProtocolDTags.AnswerOriginKind));a.peekStartElement(NDNProtocolDTags.Scope)&&(this.scope=a.readIntegerElement(NDNProtocolDTags.Scope));
-a.peekStartElement(NDNProtocolDTags.InterestLifetime)&&(this.interestLifetime=1E3*DataUtils.bigEndianToUnsignedInt(a.readBinaryElement(NDNProtocolDTags.InterestLifetime))/4096);a.peekStartElement(NDNProtocolDTags.Nonce)&&(this.nonce=a.readBinaryElement(NDNProtocolDTags.Nonce));a.readEndElement()};
-Interest.prototype.to_ndnb=function(a){a.writeStartElement(NDNProtocolDTags.Interest);this.name.to_ndnb(a);null!=this.minSuffixComponents&&a.writeElement(NDNProtocolDTags.MinSuffixComponents,this.minSuffixComponents);null!=this.maxSuffixComponents&&a.writeElement(NDNProtocolDTags.MaxSuffixComponents,this.maxSuffixComponents);null!=this.publisherPublicKeyDigest&&this.publisherPublicKeyDigest.to_ndnb(a);null!=this.exclude&&this.exclude.to_ndnb(a);null!=this.childSelector&&a.writeElement(NDNProtocolDTags.ChildSelector,
-this.childSelector);this.DEFAULT_ANSWER_ORIGIN_KIND!=this.answerOriginKind&&null!=this.answerOriginKind&&a.writeElement(NDNProtocolDTags.AnswerOriginKind,this.answerOriginKind);null!=this.scope&&a.writeElement(NDNProtocolDTags.Scope,this.scope);null!=this.interestLifetime&&a.writeElement(NDNProtocolDTags.InterestLifetime,DataUtils.nonNegativeIntToBigEndian(4096*(this.interestLifetime/1E3)));null!=this.nonce&&a.writeElement(NDNProtocolDTags.Nonce,this.nonce);a.writeEndElement()};
-Interest.prototype.matches_name=function(a){return!this.name.match(a)||null!=this.minSuffixComponents&&!(a.components.length+1-this.name.components.length>=this.minSuffixComponents)||null!=this.maxSuffixComponents&&!(a.components.length+1-this.name.components.length<=this.maxSuffixComponents)||null!=this.exclude&&a.components.length>this.name.components.length&&this.exclude.matches(a.components[this.name.components.length])?!1:!0};
-Interest.prototype.clone=function(){return new Interest(this.name,this.faceInstance,this.minSuffixComponents,this.maxSuffixComponents,this.publisherPublicKeyDigest,this.exclude,this.childSelector,this.answerOriginKind,this.scope,this.interestLifetime,this.nonce)};var Exclude=function(a){this.values=a||[]};Exclude.ANY="*";
-Exclude.prototype.from_ndnb=function(a){for(a.readStartElement(NDNProtocolDTags.Exclude);;)if(a.peekStartElement(NDNProtocolDTags.Component))this.values.push(a.readBinaryElement(NDNProtocolDTags.Component));else if(a.peekStartElement(NDNProtocolDTags.Any))a.readStartElement(NDNProtocolDTags.Any),a.readEndElement(),this.values.push(Exclude.ANY);else if(a.peekStartElement(NDNProtocolDTags.Bloom))a.readBinaryElement(NDNProtocolDTags.Bloom),this.values.push(Exclude.ANY);else break;a.readEndElement()};
-Exclude.prototype.to_ndnb=function(a){if(!(null==this.values||0==this.values.length)){a.writeStartElement(NDNProtocolDTags.Exclude);for(var b=0;b<this.values.length;++b)this.values[b]==Exclude.ANY?(a.writeStartElement(NDNProtocolDTags.Any),a.writeEndElement()):a.writeElement(NDNProtocolDTags.Component,this.values[b]);a.writeEndElement()}};
-Exclude.prototype.to_uri=function(){if(null==this.values||0==this.values.length)return"";for(var a="",b=0;b<this.values.length;++b)0<b&&(a+=","),a=this.values[b]==Exclude.ANY?a+"*":a+Name.toEscapedString(this.values[b]);return a};
-Exclude.prototype.matches=function(a){for(var b=0;b<this.values.length;++b)if(this.values[b]==Exclude.ANY){var c=null;0<b&&(c=this.values[b-1]);var d,e=null;for(d=b+1;d<this.values.length;++d)if(this.values[d]!=Exclude.ANY){e=this.values[d];break}if(null!=e){if(null!=c){if(0<Exclude.compareComponents(a,c)&&0>Exclude.compareComponents(a,e))return!0}else if(0>Exclude.compareComponents(a,e))return!0;b=d-1}else if(null!=c){if(0<Exclude.compareComponents(a,c))return!0}else return!0}else if(DataUtils.arraysEqual(a,
-this.values[b]))return!0;return!1};Exclude.compareComponents=function(a,b){if(a.length<b.length)return-1;if(a.length>b.length)return 1;for(var c=0;c<a.length;++c){if(a[c]<b[c])return-1;if(a[c]>b[c])return 1}return 0};
-var Key=function(){},KeyLocatorType={KEY:1,CERTIFICATE:2,KEYNAME:3},KeyLocator=function(a,b){this.type=b;b==KeyLocatorType.KEYNAME?(3<LOG&&console.log("KeyLocator: SET KEYNAME"),this.keyName=a):b==KeyLocatorType.KEY?(3<LOG&&console.log("KeyLocator: SET KEY"),this.publicKey=a):b==KeyLocatorType.CERTIFICATE&&(3<LOG&&console.log("KeyLocator: SET CERTIFICATE"),this.certificate=a)};
-KeyLocator.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());if(a.peekStartElement(NDNProtocolDTags.Key)){try{this.publicKey=a.readBinaryElement(NDNProtocolDTags.Key),this.type=KeyLocatorType.KEY,4<LOG&&console.log("PUBLIC KEY FOUND: "+this.publicKey)}catch(b){throw Error("Cannot parse key: ",b);}if(null==this.publicKey)throw Error("Cannot parse key: ");}else if(a.peekStartElement(NDNProtocolDTags.Certificate)){try{this.certificate=a.readBinaryElement(NDNProtocolDTags.Certificate),
-this.type=KeyLocatorType.CERTIFICATE,4<LOG&&console.log("CERTIFICATE FOUND: "+this.certificate)}catch(c){throw Error("Cannot decode certificate: "+c);}if(null==this.certificate)throw Error("Cannot parse certificate! ");}else this.type=KeyLocatorType.KEYNAME,this.keyName=new KeyName,this.keyName.from_ndnb(a);a.readEndElement()};
-KeyLocator.prototype.to_ndnb=function(a){4<LOG&&console.log("type is is "+this.type);if(!this.validate())throw new ContentEncodingException("Cannot encode "+this.getClass().getName()+": field values missing.");a.writeStartElement(this.getElementLabel());if(this.type==KeyLocatorType.KEY)5<LOG&&console.log("About to encode a public key"+this.publicKey),a.writeElement(NDNProtocolDTags.Key,this.publicKey);else if(this.type==KeyLocatorType.CERTIFICATE)try{a.writeElement(NDNProtocolDTags.Certificate,this.certificate)}catch(b){throw Error("CertificateEncodingException attempting to write key locator: "+
-b);}else this.type==KeyLocatorType.KEYNAME&&this.keyName.to_ndnb(a);a.writeEndElement()};KeyLocator.prototype.getElementLabel=function(){return NDNProtocolDTags.KeyLocator};KeyLocator.prototype.validate=function(){return null!=this.keyName||null!=this.publicKey||null!=this.certificate};var KeyName=function(){this.contentName=this.contentName;this.publisherID=this.publisherID};
-KeyName.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());this.contentName=new Name;this.contentName.from_ndnb(a);4<LOG&&console.log("KEY NAME FOUND: ");PublisherID.peek(a)&&(this.publisherID=new PublisherID,this.publisherID.from_ndnb(a));a.readEndElement()};
-KeyName.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode : field values missing.");a.writeStartElement(this.getElementLabel());this.contentName.to_ndnb(a);null!=this.publisherID&&this.publisherID.to_ndnb(a);a.writeEndElement()};KeyName.prototype.getElementLabel=function(){return NDNProtocolDTags.KeyName};KeyName.prototype.validate=function(){return null!=this.contentName};
-var PublisherType=function(a){this.KEY=NDNProtocolDTags.PublisherPublicKeyDigest;this.CERTIFICATE=NDNProtocolDTags.PublisherCertificateDigest;this.ISSUER_KEY=NDNProtocolDTags.PublisherIssuerKeyDigest;this.ISSUER_CERTIFICATE=NDNProtocolDTags.PublisherIssuerCertificateDigest;this.Tag=a},isTypeTagVal=function(a){return a==NDNProtocolDTags.PublisherPublicKeyDigest||a==NDNProtocolDTags.PublisherCertificateDigest||a==NDNProtocolDTags.PublisherIssuerKeyDigest||a==NDNProtocolDTags.PublisherIssuerCertificateDigest?
-!0:!1},PublisherID=function(){this.PUBLISHER_ID_DIGEST_ALGORITHM="SHA-256";this.PUBLISHER_ID_LEN=32;this.publisherType=this.publisherID=null};
-PublisherID.prototype.from_ndnb=function(a){var b=a.peekStartElementAsLong();if(null==b)throw Error("Cannot parse publisher ID.");this.publisherType=new PublisherType(b);if(!isTypeTagVal(b))throw Error("Invalid publisher ID, got unexpected type: "+b);this.publisherID=a.readBinaryElement(b);if(null==this.publisherID)throw new ContentDecodingException(Error("Cannot parse publisher ID of type : "+b+"."));};
-PublisherID.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode "+this.getClass().getName()+": field values missing.");a.writeElement(this.getElementLabel(),this.publisherID)};PublisherID.peek=function(a){a=a.peekStartElementAsLong();return null==a?!1:isTypeTagVal(a)};PublisherID.prototype.getElementLabel=function(){return this.publisherType.Tag};PublisherID.prototype.validate=function(){return null!=id()&&null!=type()};
-var PublisherPublicKeyDigest=function(a){this.PUBLISHER_ID_LEN=64;this.publisherPublicKeyDigest=a};
-PublisherPublicKeyDigest.prototype.from_ndnb=function(a){this.publisherPublicKeyDigest=a.readBinaryElement(this.getElementLabel());4<LOG&&console.log("Publisher public key digest is "+this.publisherPublicKeyDigest);if(null==this.publisherPublicKeyDigest)throw Error("Cannot parse publisher key digest.");this.publisherPublicKeyDigest.length!=this.PUBLISHER_ID_LEN&&0<LOG&&console.log("LENGTH OF PUBLISHER ID IS WRONG! Expected "+this.PUBLISHER_ID_LEN+", got "+this.publisherPublicKeyDigest.length)};
-PublisherPublicKeyDigest.prototype.to_ndnb=function(a){if(!this.validate())throw Error("Cannot encode : field values missing.");3<LOG&&console.log("PUBLISHER KEY DIGEST IS"+this.publisherPublicKeyDigest);a.writeElement(this.getElementLabel(),this.publisherPublicKeyDigest)};PublisherPublicKeyDigest.prototype.getElementLabel=function(){return NDNProtocolDTags.PublisherPublicKeyDigest};PublisherPublicKeyDigest.prototype.validate=function(){return null!=this.publisherPublicKeyDigest};
-var NetworkProtocol={TCP:6,UDP:17},FaceInstance=function(a,b,c,d,e,f,g,h,j){this.action=a;this.publisherPublicKeyDigest=b;this.faceID=c;this.ipProto=d;this.host=e;this.Port=f;this.multicastInterface=g;this.multicastTTL=h;this.freshnessSeconds=j};
-FaceInstance.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(NDNProtocolDTags.Action)&&(this.action=a.readUTF8Element(NDNProtocolDTags.Action));a.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)&&(this.publisherPublicKeyDigest=new PublisherPublicKeyDigest,this.publisherPublicKeyDigest.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.FaceID)&&(this.faceID=a.readIntegerElement(NDNProtocolDTags.FaceID));if(a.peekStartElement(NDNProtocolDTags.IPProto)){var b=
-a.readIntegerElement(NDNProtocolDTags.IPProto);this.ipProto=null;if(NetworkProtocol.TCP==b)this.ipProto=NetworkProtocol.TCP;else if(NetworkProtocol.UDP==b)this.ipProto=NetworkProtocol.UDP;else throw Error("FaceInstance.decoder.  Invalid "+NDNProtocolDTags.tagToString(NDNProtocolDTags.IPProto)+" field: "+b);}a.peekStartElement(NDNProtocolDTags.Host)&&(this.host=a.readUTF8Element(NDNProtocolDTags.Host));a.peekStartElement(NDNProtocolDTags.Port)&&(this.Port=a.readIntegerElement(NDNProtocolDTags.Port));
-a.peekStartElement(NDNProtocolDTags.MulticastInterface)&&(this.multicastInterface=a.readUTF8Element(NDNProtocolDTags.MulticastInterface));a.peekStartElement(NDNProtocolDTags.MulticastTTL)&&(this.multicastTTL=a.readIntegerElement(NDNProtocolDTags.MulticastTTL));a.peekStartElement(NDNProtocolDTags.FreshnessSeconds)&&(this.freshnessSeconds=a.readIntegerElement(NDNProtocolDTags.FreshnessSeconds));a.readEndElement()};
-FaceInstance.prototype.to_ndnb=function(a){a.writeStartElement(this.getElementLabel());null!=this.action&&0!=this.action.length&&a.writeElement(NDNProtocolDTags.Action,this.action);null!=this.publisherPublicKeyDigest&&this.publisherPublicKeyDigest.to_ndnb(a);null!=this.faceID&&a.writeElement(NDNProtocolDTags.FaceID,this.faceID);null!=this.ipProto&&a.writeElement(NDNProtocolDTags.IPProto,this.ipProto);null!=this.host&&0!=this.host.length&&a.writeElement(NDNProtocolDTags.Host,this.host);null!=this.Port&&
-a.writeElement(NDNProtocolDTags.Port,this.Port);null!=this.multicastInterface&&0!=this.multicastInterface.length&&a.writeElement(NDNProtocolDTags.MulticastInterface,this.multicastInterface);null!=this.multicastTTL&&a.writeElement(NDNProtocolDTags.MulticastTTL,this.multicastTTL);null!=this.freshnessSeconds&&a.writeElement(NDNProtocolDTags.FreshnessSeconds,this.freshnessSeconds);a.writeEndElement()};FaceInstance.prototype.getElementLabel=function(){return NDNProtocolDTags.FaceInstance};
-var ForwardingEntry=function(a,b,c,d,e,f){this.action=a;this.prefixName=b;this.ndndID=c;this.faceID=d;this.flags=e;this.lifetime=f};
-ForwardingEntry.prototype.from_ndnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(NDNProtocolDTags.Action)&&(this.action=a.readUTF8Element(NDNProtocolDTags.Action));a.peekStartElement(NDNProtocolDTags.Name)&&(this.prefixName=new Name,this.prefixName.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.PublisherPublicKeyDigest)&&(this.NdndId=new PublisherPublicKeyDigest,this.NdndId.from_ndnb(a));a.peekStartElement(NDNProtocolDTags.FaceID)&&(this.faceID=a.readIntegerElement(NDNProtocolDTags.FaceID));
-a.peekStartElement(NDNProtocolDTags.ForwardingFlags)&&(this.flags=a.readIntegerElement(NDNProtocolDTags.ForwardingFlags));a.peekStartElement(NDNProtocolDTags.FreshnessSeconds)&&(this.lifetime=a.readIntegerElement(NDNProtocolDTags.FreshnessSeconds));a.readEndElement()};
-ForwardingEntry.prototype.to_ndnb=function(a){a.writeStartElement(this.getElementLabel());null!=this.action&&0!=this.action.length&&a.writeElement(NDNProtocolDTags.Action,this.action);null!=this.prefixName&&this.prefixName.to_ndnb(a);null!=this.NdndId&&this.NdndId.to_ndnb(a);null!=this.faceID&&a.writeElement(NDNProtocolDTags.FaceID,this.faceID);null!=this.flags&&a.writeElement(NDNProtocolDTags.ForwardingFlags,this.flags);null!=this.lifetime&&a.writeElement(NDNProtocolDTags.FreshnessSeconds,this.lifetime);
-a.writeEndElement()};ForwardingEntry.prototype.getElementLabel=function(){return NDNProtocolDTags.ForwardingEntry};var DynamicUint8Array=function(a){a||(a=16);this.array=new Uint8Array(a);this.length=a};DynamicUint8Array.prototype.ensureLength=function(a){if(!(this.array.length>=a)){var b=2*this.array.length;a>b&&(b=a);a=new Uint8Array(b);a.set(this.array);this.array=a;this.length=b}};DynamicUint8Array.prototype.set=function(a,b){this.ensureLength(a.length+b);this.array.set(a,b)};
-DynamicUint8Array.prototype.subarray=function(a,b){return this.array.subarray(a,b)};
-var XML_EXT=0,XML_TAG=1,XML_DTAG=2,XML_ATTR=3,XML_DATTR=4,XML_BLOB=5,XML_UDATA=6,XML_CLOSE=0,XML_SUBTYPE_PROCESSING_INSTRUCTIONS=16,XML_TT_BITS=3,XML_TT_MASK=(1<<XML_TT_BITS)-1,XML_TT_VAL_BITS=XML_TT_BITS+1,XML_TT_VAL_MASK=(1<<XML_TT_VAL_BITS)-1,XML_REG_VAL_BITS=7,XML_REG_VAL_MASK=(1<<XML_REG_VAL_BITS)-1,XML_TT_NO_MORE=1<<XML_REG_VAL_BITS,BYTE_MASK=255,LONG_BYTES=8,LONG_BITS=64,bits_11=2047,bits_18=262143,bits_32=4294967295,BinaryXMLEncoder=function(){this.ostream=new DynamicUint8Array(100);this.offset=
-0;this.CODEC_NAME="Binary"};BinaryXMLEncoder.prototype.writeUString=function(a){this.encodeUString(a,XML_UDATA)};BinaryXMLEncoder.prototype.writeBlob=function(a){3<LOG&&console.log(a);this.encodeBlob(a,a.length)};BinaryXMLEncoder.prototype.writeStartElement=function(a,b){null==a?this.encodeUString(a,XML_TAG):this.encodeTypeAndVal(XML_DTAG,a);null!=b&&this.writeAttributes(b)};
-BinaryXMLEncoder.prototype.writeEndElement=function(){this.ostream.ensureLength(this.offset+1);this.ostream.array[this.offset]=XML_CLOSE;this.offset+=1};BinaryXMLEncoder.prototype.writeAttributes=function(a){if(null!=a)for(var b=0;b<a.length;b++){var c=a[b].k,d=a[b].v,e=stringToTag(c);null==e?this.encodeUString(c,XML_ATTR):this.encodeTypeAndVal(XML_DATTR,e);this.encodeUString(d)}};
-stringToTag=function(a){return 0<=a&&a<NDNProtocolDTagsStrings.length?NDNProtocolDTagsStrings[a]:a==NDNProtocolDTags.NDNProtocolDataUnit?NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT:null};tagToString=function(a){for(var b=0;b<NDNProtocolDTagsStrings.length;++b)if(null!=NDNProtocolDTagsStrings[b]&&NDNProtocolDTagsStrings[b]==a)return b;return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT==a?NDNProtocolDTags.NDNProtocolDataUnit:null};
-BinaryXMLEncoder.prototype.writeElement=function(a,b,c){this.writeStartElement(a,c);"number"===typeof b?(4<LOG&&console.log("GOING TO WRITE THE NUMBER .charCodeAt(0) "+b.toString().charCodeAt(0)),4<LOG&&console.log("GOING TO WRITE THE NUMBER "+b.toString()),4<LOG&&console.log("type of number is "+typeof b.toString()),this.writeUString(b.toString())):"string"===typeof b?(4<LOG&&console.log("GOING TO WRITE THE STRING  "+b),4<LOG&&console.log("type of STRING is "+typeof b),this.writeUString(b)):(4<LOG&&
-console.log("GOING TO WRITE A BLOB  "+b),this.writeBlob(b));this.writeEndElement()};var TypeAndVal=function(a,b){this.type=a;this.val=b};
-BinaryXMLEncoder.prototype.encodeTypeAndVal=function(a,b){4<LOG&&console.log("Encoding type "+a+" and value "+b);4<LOG&&console.log("OFFSET IS "+this.offset);if(a>XML_UDATA||0>a||0>b)throw Error("Tag and value must be positive, and tag valid.");var c=this.numEncodingBytes(b);this.ostream.ensureLength(this.offset+c);this.ostream.array[this.offset+c-1]=BYTE_MASK&(XML_TT_MASK&a|(XML_TT_VAL_MASK&b)<<XML_TT_BITS)|XML_TT_NO_MORE;b>>>=XML_TT_VAL_BITS;for(var d=this.offset+c-2;0!=b&&d>=this.offset;)this.ostream.array[d]=
-BYTE_MASK&b&XML_REG_VAL_MASK,b>>>=XML_REG_VAL_BITS,--d;if(0!=b)throw Error("This should not happen: miscalculated encoding");this.offset+=c;return c};
-BinaryXMLEncoder.prototype.encodeUString=function(a,b){if(null!=a&&!(b==XML_TAG||b==XML_ATTR&&0==a.length)){3<LOG&&console.log("The string to write is ");3<LOG&&console.log(a);var c=DataUtils.stringToUtf8Array(a);this.encodeTypeAndVal(b,b==XML_TAG||b==XML_ATTR?c.length-1:c.length);3<LOG&&console.log("THE string to write is ");3<LOG&&console.log(c);this.writeString(c);this.offset+=c.length}};
-BinaryXMLEncoder.prototype.encodeBlob=function(a,b){null!=a&&(4<LOG&&console.log("LENGTH OF XML_BLOB IS "+b),this.encodeTypeAndVal(XML_BLOB,b),this.writeBlobArray(a),this.offset+=b)};var ENCODING_LIMIT_1_BYTE=(1<<XML_TT_VAL_BITS)-1,ENCODING_LIMIT_2_BYTES=(1<<XML_TT_VAL_BITS+XML_REG_VAL_BITS)-1,ENCODING_LIMIT_3_BYTES=(1<<XML_TT_VAL_BITS+2*XML_REG_VAL_BITS)-1;
-BinaryXMLEncoder.prototype.numEncodingBytes=function(a){if(a<=ENCODING_LIMIT_1_BYTE)return 1;if(a<=ENCODING_LIMIT_2_BYTES)return 2;if(a<=ENCODING_LIMIT_3_BYTES)return 3;var b=1;for(a>>>=XML_TT_VAL_BITS;0!=a;)b++,a>>>=XML_REG_VAL_BITS;return b};
-BinaryXMLEncoder.prototype.writeDateTime=function(a,b){4<LOG&&console.log("ENCODING DATE with LONG VALUE");4<LOG&&console.log(b.msec);var c=Math.round(4096*(b.msec/1E3)).toString(16),c=DataUtils.toNumbers("0".concat(c,"0"));4<LOG&&console.log("ENCODING DATE with BINARY VALUE");4<LOG&&console.log(c);4<LOG&&console.log("ENCODING DATE with BINARY VALUE(HEX)");4<LOG&&console.log(DataUtils.toHex(c));this.writeElement(a,c)};
-BinaryXMLEncoder.prototype.writeString=function(a){if("string"===typeof a){4<LOG&&console.log("GOING TO WRITE A STRING");4<LOG&&console.log(a);this.ostream.ensureLength(this.offset+a.length);for(var b=0;b<a.length;b++)4<LOG&&console.log("input.charCodeAt(i)="+a.charCodeAt(b)),this.ostream.array[this.offset+b]=a.charCodeAt(b)}else 4<LOG&&console.log("GOING TO WRITE A STRING IN BINARY FORM"),4<LOG&&console.log(a),this.writeBlobArray(a)};
-BinaryXMLEncoder.prototype.writeBlobArray=function(a){4<LOG&&console.log("GOING TO WRITE A BLOB");this.ostream.set(a,this.offset)};BinaryXMLEncoder.prototype.getReducedOstream=function(){return this.ostream.subarray(0,this.offset)};XML_EXT=0;XML_TAG=1;XML_DTAG=2;XML_ATTR=3;XML_DATTR=4;XML_BLOB=5;XML_UDATA=6;XML_CLOSE=0;XML_SUBTYPE_PROCESSING_INSTRUCTIONS=16;XML_TT_BITS=3;XML_TT_MASK=(1<<XML_TT_BITS)-1;XML_TT_VAL_BITS=XML_TT_BITS+1;XML_TT_VAL_MASK=(1<<XML_TT_VAL_BITS)-1;XML_REG_VAL_BITS=7;
-XML_REG_VAL_MASK=(1<<XML_REG_VAL_BITS)-1;XML_TT_NO_MORE=1<<XML_REG_VAL_BITS;BYTE_MASK=255;LONG_BYTES=8;LONG_BITS=64;bits_11=2047;bits_18=262143;bits_32=4294967295;tagToString=function(a){return 0<=a&&a<NDNProtocolDTagsStrings.length?NDNProtocolDTagsStrings[a]:a==NDNProtocolDTags.NDNProtocolDataUnit?NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT:null};
-stringToTag=function(a){for(var b=0;b<NDNProtocolDTagsStrings.length;++b)if(null!=NDNProtocolDTagsStrings[b]&&NDNProtocolDTagsStrings[b]==a)return b;return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT==a?NDNProtocolDTags.NDNProtocolDataUnit:null};var BinaryXMLDecoder=function(a){this.istream=a;this.offset=0};BinaryXMLDecoder.prototype.initializeDecoding=function(){};BinaryXMLDecoder.prototype.readStartDocument=function(){};BinaryXMLDecoder.prototype.readEndDocument=function(){};
-BinaryXMLDecoder.prototype.readStartElement=function(a,b){var c=this.decodeTypeAndVal();if(null==c)throw new ContentDecodingException(Error("Expected start element: "+a+" got something not a tag."));var d=null;c.type()==XML_TAG?(d="string"==typeof c.val()?parseInt(c.val())+1:c.val()+1,d=this.decodeUString(d)):c.type()==XML_DTAG&&(d=c.val());if(null==d||d!=a)throw console.log("expecting "+a+" but got "+d),new ContentDecodingException(Error("Expected start element: "+a+" got: "+d+"("+c.val()+")"));
-null!=b&&readAttributes(b)};
-BinaryXMLDecoder.prototype.readAttributes=function(a){if(null!=a)try{for(var b=this.peekTypeAndVal();null!=b&&(XML_ATTR==b.type()||XML_DATTR==b.type());){var c=this.decodeTypeAndVal(),d=null;if(XML_ATTR==c.type()){var e;e="string"==typeof c.val()?parseInt(c.val())+1:c.val()+1;d=this.decodeUString(e)}else if(XML_DATTR==c.type()&&(d=tagToString(c.val()),null==d))throw new ContentDecodingException(Error("Unknown DATTR value"+c.val()));var f=this.decodeUString();a.push([d,f]);b=this.peekTypeAndVal()}}catch(g){throw new ContentDecodingException(Error("readStartElement",
-g));}};BinaryXMLDecoder.prototype.peekStartElementAsString=function(){var a=null,b=this.offset;try{var c=this.decodeTypeAndVal();if(null!=c)if(c.type()==XML_TAG){var d;d="string"==typeof c.val()?parseInt(c.val())+1:c.val()+1;a=this.decodeUString(d)}else c.type()==XML_DTAG&&(a=tagToString(c.val()))}catch(e){}finally{try{this.offset=b}catch(f){throw Log.logStackTrace(Log.FAC_ENCODING,Level.WARNING,f),new ContentDecodingException(Error("Cannot reset stream! "+f.getMessage(),f));}}return a};
-BinaryXMLDecoder.prototype.peekStartElement=function(a){if("string"==typeof a){var b=this.peekStartElementAsString();return null!=b&&b==a?!0:!1}if("number"==typeof a)return b=this.peekStartElementAsLong(),null!=b&&b==a?!0:!1;throw new ContentDecodingException(Error("SHOULD BE STRING OR NUMBER"));};
-BinaryXMLDecoder.prototype.peekStartElementAsLong=function(){var a=null,b=this.offset;try{var c=this.decodeTypeAndVal();if(null!=c)if(c.type()==XML_TAG){if(c.val()+1>DEBUG_MAX_LEN)throw new ContentDecodingException(Error("Decoding error: length "+c.val()+1+" longer than expected maximum length!"));var d;d="string"==typeof c.val()?parseInt(c.val())+1:c.val()+1;var e=this.decodeUString(d),a=stringToTag(e)}else c.type()==XML_DTAG&&(a=c.val())}catch(f){}finally{try{this.offset=b}catch(g){throw Log.logStackTrace(Log.FAC_ENCODING,
-Level.WARNING,g),Error("Cannot reset stream! "+g.getMessage(),g);}}return a};BinaryXMLDecoder.prototype.readBinaryElement=function(a,b){var c=null;this.readStartElement(a,b);return c=this.readBlob()};
-BinaryXMLDecoder.prototype.readEndElement=function(){4<LOG&&console.log("this.offset is "+this.offset);var a=this.istream[this.offset];this.offset++;4<LOG&&console.log("XML_CLOSE IS "+XML_CLOSE);4<LOG&&console.log("next is "+a);if(a!=XML_CLOSE)throw console.log("Expected end element, got: "+a),new ContentDecodingException(Error("Expected end element, got: "+a));};BinaryXMLDecoder.prototype.readUString=function(){var a=this.decodeUString();this.readEndElement();return a};
-BinaryXMLDecoder.prototype.readBlob=function(){var a=this.decodeBlob();this.readEndElement();return a};BinaryXMLDecoder.prototype.readDateTime=function(a){a=this.readBinaryElement(a);a=DataUtils.toHex(a);a=parseInt(a,16);var b=1E3*(a/4096);3<LOG&&console.log("DECODED DATE WITH VALUE");3<LOG&&console.log(b);b=new NDNTime(b);if(null==b)throw new ContentDecodingException(Error("Cannot parse timestamp: "+DataUtils.printHexBytes(a)));return b};
-BinaryXMLDecoder.prototype.decodeTypeAndVal=function(){var a=-1,b=0,c=!0;do{var d=this.istream[this.offset];if(0>d||0==d&&0==b)return null;(c=0==(d&XML_TT_NO_MORE))?(b<<=XML_REG_VAL_BITS,b|=d&XML_REG_VAL_MASK):(a=d&XML_TT_MASK,b<<=XML_TT_VAL_BITS,b|=d>>>XML_TT_BITS&XML_TT_VAL_MASK);this.offset++}while(c);3<LOG&&console.log("TYPE is "+a+" VAL is "+b);return new TypeAndVal(a,b)};BinaryXMLDecoder.peekTypeAndVal=function(){var a=null,b=this.offset;try{a=this.decodeTypeAndVal()}finally{this.offset=b}return a};
-BinaryXMLDecoder.prototype.decodeBlob=function(a){if(null==a)return a=this.decodeTypeAndVal(),a="string"==typeof a.val()?parseInt(a.val()):a.val(),this.decodeBlob(a);var b=this.istream.subarray(this.offset,this.offset+a);this.offset+=a;return b};
-BinaryXMLDecoder.prototype.decodeUString=function(a){if(null==a){a=this.offset;var b=this.decodeTypeAndVal();3<LOG&&console.log("TV is "+b);3<LOG&&console.log(b);3<LOG&&console.log("Type of TV is "+typeof b);return null==b||XML_UDATA!=b.type()?(this.offset=a,""):this.decodeUString(b.val())}a=this.decodeBlob(a);return DataUtils.toString(a)};TypeAndVal=function(a,b){this.t=a;this.v=b};TypeAndVal.prototype.type=function(){return this.t};TypeAndVal.prototype.val=function(){return this.v};
-BinaryXMLDecoder.prototype.readIntegerElement=function(a){4<LOG&&console.log("READING INTEGER "+a);4<LOG&&console.log("TYPE OF "+typeof a);a=this.readUTF8Element(a);return parseInt(a)};BinaryXMLDecoder.prototype.readUTF8Element=function(a,b){this.readStartElement(a,b);return this.readUString()};BinaryXMLDecoder.prototype.seek=function(a){this.offset=a};function ContentDecodingException(a){this.message=a.message;for(var b in a)this[b]=a[b]}ContentDecodingException.prototype=Error();
-ContentDecodingException.prototype.name="ContentDecodingException";var BinaryXMLStructureDecoder=function(){this.gotElementEnd=!1;this.level=this.offset=0;this.state=BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;this.headerLength=0;this.useHeaderBuffer=!1;this.headerBuffer=new DynamicUint8Array(5);this.nBytesToRead=0};BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE=0;BinaryXMLStructureDecoder.READ_BYTES=1;
-BinaryXMLStructureDecoder.prototype.findElementEnd=function(a){if(this.gotElementEnd)return!0;for(var b=new BinaryXMLDecoder(a);;){if(this.offset>=a.length)return!1;switch(this.state){case BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE:if(0==this.headerLength&&a[this.offset]==XML_CLOSE){++this.offset;--this.level;if(0==this.level)return!0;if(0>this.level)throw Error("BinaryXMLStructureDecoder: Unexepected close tag at offset "+(this.offset-1));this.startHeader();break}for(var c=this.headerLength;;){if(this.offset>=
-a.length){this.useHeaderBuffer=!0;var d=this.headerLength-c;this.headerBuffer.set(a.subarray(this.offset-d,d),c);return!1}d=a[this.offset++];++this.headerLength;if(d&XML_TT_NO_MORE)break}this.useHeaderBuffer?(d=this.headerLength-c,this.headerBuffer.set(a.subarray(this.offset-d,d),c),c=(new BinaryXMLDecoder(this.headerBuffer.array)).decodeTypeAndVal()):(b.seek(this.offset-this.headerLength),c=b.decodeTypeAndVal());if(null==c)throw Error("BinaryXMLStructureDecoder: Can't read header starting at offset "+
-(this.offset-this.headerLength));d=c.t;if(d==XML_DATTR)this.startHeader();else if(d==XML_DTAG||d==XML_EXT)++this.level,this.startHeader();else if(d==XML_TAG||d==XML_ATTR)d==XML_TAG&&++this.level,this.nBytesToRead=c.v+1,this.state=BinaryXMLStructureDecoder.READ_BYTES;else if(d==XML_BLOB||d==XML_UDATA)this.nBytesToRead=c.v,this.state=BinaryXMLStructureDecoder.READ_BYTES;else throw Error("BinaryXMLStructureDecoder: Unrecognized header type "+d);break;case BinaryXMLStructureDecoder.READ_BYTES:c=a.length-
-this.offset;if(c<this.nBytesToRead)return this.offset+=c,this.nBytesToRead-=c,!1;this.offset+=this.nBytesToRead;this.startHeader();break;default:throw Error("BinaryXMLStructureDecoder: Unrecognized state "+this.state);}}};BinaryXMLStructureDecoder.prototype.startHeader=function(){this.headerLength=0;this.useHeaderBuffer=!1;this.state=BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE};BinaryXMLStructureDecoder.prototype.seek=function(a){this.offset=a};var DataUtils=function(){};DataUtils.keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-DataUtils.stringtoBase64=function(a){a=escape(a);var b="",c,d,e="",f,g,h="",j=0;do c=a.charCodeAt(j++),d=a.charCodeAt(j++),e=a.charCodeAt(j++),f=c>>2,c=(c&3)<<4|d>>4,g=(d&15)<<2|e>>6,h=e&63,isNaN(d)?g=h=64:isNaN(e)&&(h=64),b=b+DataUtils.keyStr.charAt(f)+DataUtils.keyStr.charAt(c)+DataUtils.keyStr.charAt(g)+DataUtils.keyStr.charAt(h);while(j<a.length);return b};
-DataUtils.base64toString=function(a){var b="",c,d,e="",f,g="",h=0;/[^A-Za-z0-9\+\/\=]/g.exec(a)&&alert("There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\nExpect errors in decoding.");a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do c=DataUtils.keyStr.indexOf(a.charAt(h++)),d=DataUtils.keyStr.indexOf(a.charAt(h++)),f=DataUtils.keyStr.indexOf(a.charAt(h++)),g=DataUtils.keyStr.indexOf(a.charAt(h++)),c=c<<2|d>>4,d=(d&15)<<4|f>>2,e=(f&3)<<6|g,
-b+=String.fromCharCode(c),64!=f&&(b+=String.fromCharCode(d)),64!=g&&(b+=String.fromCharCode(e));while(h<a.length);return unescape(b)};DataUtils.toHex=function(a){4<LOG&&console.log("ABOUT TO CONVERT "+a);for(var b="",c=0;c<a.length;c++)b+=(16>a[c]?"0":"")+a[c].toString(16);4<LOG&&console.log("Converted to: "+b);return b};DataUtils.stringToHex=function(a){for(var b="",c=0;c<a.length;++c)var d=a.charCodeAt(c),b=b+((16>d?"0":"")+d.toString(16));return b};
-DataUtils.toString=function(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a[c]);return b};DataUtils.toNumbers=function(a){if("string"==typeof a){var b=new Uint8Array(Math.floor(a.length/2)),c=0;a.replace(/(..)/g,function(a){b[c++]=parseInt(a,16)});return b}};DataUtils.hexToRawString=function(a){if("string"==typeof a){var b="";a.replace(/(..)/g,function(a){b+=String.fromCharCode(parseInt(a,16))});return b}};
-DataUtils.toNumbersFromString=function(a){for(var b=new Uint8Array(a.length),c=0;c<a.length;c++)b[c]=a.charCodeAt(c);return b};DataUtils.stringToUtf8Array=function(a){return DataUtils.toNumbersFromString(str2rstr_utf8(a))};DataUtils.concatArrays=function(a){for(var b=0,c=0;c<a.length;++c)b+=a[c].length;for(var b=new Uint8Array(b),d=0,c=0;c<a.length;++c)b.set(a[c],d),d+=a[c].length;return b};
-DataUtils.decodeUtf8=function(a){for(var b="",c=0,d=0,e=0;c<a.length;)if(d=a.charCodeAt(c),128>d)b+=String.fromCharCode(d),c++;else if(191<d&&224>d)e=a.charCodeAt(c+1),b+=String.fromCharCode((d&31)<<6|e&63),c+=2;else var e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b=b+String.fromCharCode((d&15)<<12|(e&63)<<6|f&63),c=c+3;return b};DataUtils.arraysEqual=function(a,b){if(a.length!=b.length)return!1;for(var c=0;c<a.length;++c)if(a[c]!=b[c])return!1;return!0};
-DataUtils.bigEndianToUnsignedInt=function(a){for(var b=0,c=0;c<a.length;++c)b<<=8,b+=a[c];return b};DataUtils.nonNegativeIntToBigEndian=function(a){a=Math.round(a);if(0>=a)return new Uint8Array(0);for(var b=new Uint8Array(8),c=0;0!=a;)++c,b[8-c]=a&255,a>>=8;return b.subarray(8-c,8)};DataUtils.shuffle=function(a){for(var b=a.length-1;1<=b;--b){var c=Math.floor(Math.random()*(b+1)),d=a[b];a[b]=a[c];a[c]=d}};function encodeToHexInterest(a){return DataUtils.toHex(encodeToBinaryInterest(a))}
-function encodeToBinaryInterest(a){var b=new BinaryXMLEncoder;a.to_ndnb(b);return b.getReducedOstream()}function encodeToHexContentObject(a){return DataUtils.toHex(encodeToBinaryContentObject(a))}function encodeToBinaryContentObject(a){var b=new BinaryXMLEncoder;a.to_ndnb(b);return b.getReducedOstream()}function encodeForwardingEntry(a){var b=new BinaryXMLEncoder;a.to_ndnb(b);return b.getReducedOstream()}
-function decodeHexFaceInstance(a){var b=DataUtils.toNumbers(a);a=new BinaryXMLDecoder(b);3<LOG&&console.log("DECODING HEX FACE INSTANCE  \n"+b);b=new FaceInstance;b.from_ndnb(a);return b}function decodeHexInterest(a){var b=DataUtils.toNumbers(a);a=new BinaryXMLDecoder(b);3<LOG&&console.log("DECODING HEX INTERST  \n"+b);b=new Interest;b.from_ndnb(a);return b}
-function decodeHexContentObject(a){var b=DataUtils.toNumbers(a);a=new BinaryXMLDecoder(b);3<LOG&&console.log("DECODED HEX CONTENT OBJECT \n"+b);b=new ContentObject;b.from_ndnb(a);return b}function decodeHexForwardingEntry(a){var b=DataUtils.toNumbers(a);a=new BinaryXMLDecoder(b);3<LOG&&console.log("DECODED HEX FORWARDING ENTRY \n"+b);b=new ForwardingEntry;b.from_ndnb(a);return b}
-function decodeSubjectPublicKeyInfo(a){a=DataUtils.toHex(a).toLowerCase();a=_x509_getPublicKeyHexArrayFromCertHex(a,_x509_getSubjectPublicKeyPosFromCertHex(a,0));var b=new RSAKey;b.setPublic(a[0],a[1]);return b}
-function contentObjectToHtml(a){var b="";if(-1==a)b+="NO CONTENT FOUND";else if(-2==a)b+="CONTENT NAME IS EMPTY";else{null!=a.name&&null!=a.name.components&&(b+="NAME: "+a.name.to_uri(),b+="<br /><br />");null!=a.content&&(b+="CONTENT(ASCII): "+DataUtils.toString(a.content),b+="<br />",b+="<br />");null!=a.content&&(b+="CONTENT(hex): "+DataUtils.toHex(a.content),b+="<br />",b+="<br />");null!=a.signature&&null!=a.signature.signature&&(b+="SIGNATURE(hex): "+DataUtils.toHex(a.signature.signature),b+=
-"<br />",b+="<br />");null!=a.signedInfo&&(null!=a.signedInfo.publisher&&null!=a.signedInfo.publisher.publisherPublicKeyDigest)&&(b+="Publisher Public Key Digest(hex): "+DataUtils.toHex(a.signedInfo.publisher.publisherPublicKeyDigest),b+="<br />",b+="<br />");if(null!=a.signedInfo&&null!=a.signedInfo.timestamp){var c=new Date;c.setTime(a.signedInfo.timestamp.msec);b+="TimeStamp: "+c;b+="<br />";b+="TimeStamp(number): "+a.signedInfo.timestamp.msec;b+="<br />"}null!=a.signedInfo&&null!=a.signedInfo.finalBlockID&&
-(b+="FinalBlockID: "+DataUtils.toHex(a.signedInfo.finalBlockID),b+="<br />");if(null!=a.signedInfo&&null!=a.signedInfo.locator&&null!=a.signedInfo.locator.certificate){var d=DataUtils.toHex(a.signedInfo.locator.certificate).toLowerCase(),c=DataUtils.toHex(a.signature.signature).toLowerCase(),e=DataUtils.toString(a.rawSignatureData),b=b+("Hex Certificate: "+d),b=b+"<br />",b=b+"<br />",e=new X509;e.readCertHex(d);b+="Public key (hex) modulus: "+e.subjectPublicKeyRSA.n.toString(16)+"<br/>";b+="exponent: "+
-e.subjectPublicKeyRSA.e.toString(16)+"<br/>";b+="<br/>";c=e.subjectPublicKeyRSA.verifyByteArray(a.rawSignatureData,null,c);2<LOG&&console.log("result is "+c);d=e.subjectPublicKeyRSA.n;e=e.subjectPublicKeyRSA.e;2<LOG&&console.log("PUBLIC KEY n after is ");2<LOG&&console.log(d);2<LOG&&console.log("EXPONENT e after is ");2<LOG&&console.log(e);b=c?b+"SIGNATURE VALID":b+"SIGNATURE INVALID";b+="<br />";b+="<br />"}if(null!=a.signedInfo&&null!=a.signedInfo.locator&&null!=a.signedInfo.locator.publicKey){var f=
-DataUtils.toHex(a.signedInfo.locator.publicKey).toLowerCase(),g=DataUtils.toString(a.signedInfo.locator.publicKey),c=DataUtils.toHex(a.signature.signature).toLowerCase(),e=DataUtils.toString(a.rawSignatureData),d=null,h="";null!=a.signature.Witness&&(d=new Witness,d.decode(a.signature.Witness),h=DataUtils.toHex(a.signature.Witness));b+="Public key: "+f;b+="<br />";b+="<br />";2<LOG&&console.log(" ContentName + SignedInfo + Content = "+e);2<LOG&&console.log(" PublicKeyHex = "+f);2<LOG&&console.log(" PublicKeyString = "+
-g);2<LOG&&console.log(" Signature "+c);2<LOG&&console.log(" Witness "+h);2<LOG&&console.log(" Signature NOW IS");2<LOG&&console.log(a.signature.signature);e=decodeSubjectPublicKeyInfo(a.signedInfo.locator.publicKey);b+="Public key (hex) modulus: "+e.n.toString(16)+"<br/>";b+="exponent: "+e.e.toString(16)+"<br/>";b+="<br/>";c=e.verifyByteArray(a.rawSignatureData,d,c);2<LOG&&console.log("PUBLIC KEY n after is ");2<LOG&&console.log(e.n);2<LOG&&console.log("EXPONENT e after is ");2<LOG&&console.log(e.e);
-b=c?b+"SIGNATURE VALID":b+"SIGNATURE INVALID";b+="<br />";b+="<br />"}}return b}
-var KeyManager=function(){this.certificate="MIIBmzCCAQQCCQC32FyQa61S7jANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdheGVsY2R2MB4XDTEyMDQyODIzNDQzN1oXDTEyMDUyODIzNDQzN1owEjEQMA4GA1UEAxMHYXhlbGNkdjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4X0wp9goqxuECxdULcr2IHr9Ih4Iaypg0Wy39URIup8/CLzQmdsh3RYqd55hqonu5VTTpH3iMLx6xZDVJAZ8OJi7pvXcQ2C4Re2kjL2c8SanI0RfDhlS1zJadfr1VhRPmpivcYawJ4aFuOLAi+qHFxtN7lhcGCgpW1OV60oXd58CAwEAATANBgkqhkiG9w0BAQUFAAOBgQDLOrA1fXzSrpftUB5Ro6DigX1Bjkf7F5Bkd69hSVp+jYeJFBBlsILQAfSxUZPQtD+2Yc3iCmSYNyxqu9PcufDRJlnvB7PG29+L3y9lR37tetzUV9eTscJ7rdp8Wt6AzpW32IJ/54yKNfP7S6ZIoIG+LP6EIxq6s8K1MXRt8uBJKw==";this.publicKey=
-"30819F300D06092A864886F70D010101050003818D0030818902818100E17D30A7D828AB1B840B17542DCAF6207AFD221E086B2A60D16CB7F54448BA9F3F08BCD099DB21DD162A779E61AA89EEE554D3A47DE230BC7AC590D524067C3898BBA6F5DC4360B845EDA48CBD9CF126A723445F0E1952D7325A75FAF556144F9A98AF7186B0278685B8E2C08BEA87171B4DEE585C1828295B5395EB4A17779F0203010001";this.privateKey="MIICXQIBAAKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQABAoGAGkv6T6jC3WmhFZYL6CdCWvlc6gysmKrhjarrLTxgavtFY6R5g2ft5BXAsCCVbUkWxkIFSKqxpVNl0gKZCNGEzPDN6mHJOQI/h0rlxNIHAuGfoAbCzALnqmyZivhJAPGijAyKuU9tczsst5+Kpn+bn7ehzHQuj7iwJonS5WbojqECQQD851K8TpW2GrRizNgG4dx6orZxAaon/Jnl8lS7soXhllQty7qG+oDfzznmdMsiznCqEABzHUUKOVGE9RWPN3aRAkEA5D/w9N55d0ibnChFJlc8cUAoaqH+w+U3oQP2Lb6AZHJpLptN4y4b/uf5d4wYU5/i/gC7SSBH3wFhh9bjRLUDLwJAVOx8vN0Kqt7myfKNbCo19jxjVSlA8TKCn1Oznl/BU1I+rC4oUaEW25DjmX6IpAR8kq7S59ThVSCQPjxqY/A08QJBAIRaF2zGPITQk3r/VumemCvLWiRK/yG0noc9dtibqHOWbCtcXtOm/xDWjq+lis2i3ssOvYrvrv0/HcDY+Dv1An0CQQCLJtMsfSg4kvG/FRY5UMhtMuwo8ovYcMXt4Xv/LWaMhndD67b2UGawQCRqr5ghRTABWdDD/HuuMBjrkPsX0861"};
-KeyManager.prototype.verify=function(a,b){var c=this.certificate,d=new X509;d.readCertPEM(c);return d.subjectPublicKeyRSA.verifyString(a,b)};KeyManager.prototype.sign=function(a){var b=this.privateKey,c=new RSAKey;c.readPrivateKeyFromPEMString(b);return c.signString(a,"sha256")};var globalKeyManager=new KeyManager,MerklePath=function(){this.index=null;this.digestList=[]},Witness=function(){this.oid=null;this.path=new MerklePath};
-function parseOID(a,b,c){for(var d,e=0,f=0;b<c;++b){var g=a[b],e=e<<7|g&127,f=f+7;g&128||(d=void 0==d?parseInt(e/40)+"."+e%40:d+("."+(31<=f?"bigint":e)),e=f=0);d+=String.fromCharCode()}return d}function parseInteger(a,b,c){for(var d=0;b<c;++b)d=d<<8|a[b];return d}
-Witness.prototype.decode=function(a){for(var b=0,c=0;b<a.length;){var d=0;if(48==a[b])0!=(a[b+1]&128)&&(d=a[b+1]&127),c++;else if(6==a[b])d=a[b+1],this.oid=parseOID(a,b+2,b+2+d);else if(2==a[b])d=a[b+1],this.path.index=parseInteger(a,b+2,b+2+d);else if(4==a[b]&&(0!=(a[b+1]&128)&&(d=a[b+1]&127),4==c)){var d=a[b+1],e=DataUtils.toHex(a.subarray(b+2,b+2+d));this.path.digestList.push(e)}b=b+2+d}};var hexcase=0,b64pad="";
-function hex_sha256_from_bytes(a){return rstr2hex(binb2rstr(binb_sha256(byteArray2binb(a),8*a.length)))}function hex_sha256(a){return rstr2hex(rstr_sha256(str2rstr_utf8(a)))}function b64_sha256(a){return rstr2b64(rstr_sha256(str2rstr_utf8(a)))}function any_sha256(a,b){return rstr2any(rstr_sha256(str2rstr_utf8(a)),b)}function hex_hmac_sha256(a,b){return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(a),str2rstr_utf8(b)))}
-function b64_hmac_sha256(a,b){return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(a),str2rstr_utf8(b)))}function any_hmac_sha256(a,b,c){return rstr2any(rstr_hmac_sha256(str2rstr_utf8(a),str2rstr_utf8(b)),c)}function sha256_vm_test(){return"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"==hex_sha256("abc").toLowerCase()}function rstr_sha256(a){return binb2rstr(binb_sha256(rstr2binb(a),8*a.length))}
-function rstr_hmac_sha256(a,b){var c=rstr2binb(a);16<c.length&&(c=binb_sha256(c,8*a.length));for(var d=Array(16),e=Array(16),f=0;16>f;f++)d[f]=c[f]^909522486,e[f]=c[f]^1549556828;c=binb_sha256(d.concat(rstr2binb(b)),512+8*b.length);return binb2rstr(binb_sha256(e.concat(c),768))}function rstr2hex(a){try{hexcase}catch(b){hexcase=0}for(var c=hexcase?"0123456789ABCDEF":"0123456789abcdef",d="",e,f=0;f<a.length;f++)e=a.charCodeAt(f),d+=c.charAt(e>>>4&15)+c.charAt(e&15);return d}
-function rstr2b64(a){try{b64pad}catch(b){b64pad=""}for(var c="",d=a.length,e=0;e<d;e+=3)for(var f=a.charCodeAt(e)<<16|(e+1<d?a.charCodeAt(e+1)<<8:0)|(e+2<d?a.charCodeAt(e+2):0),g=0;4>g;g++)c=8*e+6*g>8*a.length?c+b64pad:c+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(f>>>6*(3-g)&63);return c}
-function rstr2any(a,b){var c=b.length,d=[],e,f,g,h,j=Array(Math.ceil(a.length/2));for(e=0;e<j.length;e++)j[e]=a.charCodeAt(2*e)<<8|a.charCodeAt(2*e+1);for(;0<j.length;){h=[];for(e=g=0;e<j.length;e++)if(g=(g<<16)+j[e],f=Math.floor(g/c),g-=f*c,0<h.length||0<f)h[h.length]=f;d[d.length]=g;j=h}c="";for(e=d.length-1;0<=e;e--)c+=b.charAt(d[e]);d=Math.ceil(8*a.length/(Math.log(b.length)/Math.log(2)));for(e=c.length;e<d;e++)c=b[0]+c;return c}
-function str2rstr_utf8(a){for(var b="",c=-1,d,e;++c<a.length;)d=a.charCodeAt(c),e=c+1<a.length?a.charCodeAt(c+1):0,55296<=d&&(56319>=d&&56320<=e&&57343>=e)&&(d=65536+((d&1023)<<10)+(e&1023),c++),127>=d?b+=String.fromCharCode(d):2047>=d?b+=String.fromCharCode(192|d>>>6&31,128|d&63):65535>=d?b+=String.fromCharCode(224|d>>>12&15,128|d>>>6&63,128|d&63):2097151>=d&&(b+=String.fromCharCode(240|d>>>18&7,128|d>>>12&63,128|d>>>6&63,128|d&63));return b}
-function str2rstr_utf16le(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a.charCodeAt(c)&255,a.charCodeAt(c)>>>8&255);return b}function str2rstr_utf16be(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a.charCodeAt(c)>>>8&255,a.charCodeAt(c)&255);return b}function rstr2binb(a){for(var b=Array(a.length>>2),c=0;c<8*a.length;c+=8)b[c>>5]|=(a.charCodeAt(c/8)&255)<<24-c%32;return b}
-function byteArray2binb(a){for(var b=Array(a.length>>2),c=0;c<8*a.length;c+=8)b[c>>5]|=(a[c/8]&255)<<24-c%32;return b}function binb2rstr(a){for(var b="",c=0;c<32*a.length;c+=8)b+=String.fromCharCode(a[c>>5]>>>24-c%32&255);return b}function sha256_S(a,b){return a>>>b|a<<32-b}function sha256_R(a,b){return a>>>b}function sha256_Ch(a,b,c){return a&b^~a&c}function sha256_Maj(a,b,c){return a&b^a&c^b&c}function sha256_Sigma0256(a){return sha256_S(a,2)^sha256_S(a,13)^sha256_S(a,22)}
-function sha256_Sigma1256(a){return sha256_S(a,6)^sha256_S(a,11)^sha256_S(a,25)}function sha256_Gamma0256(a){return sha256_S(a,7)^sha256_S(a,18)^sha256_R(a,3)}function sha256_Gamma1256(a){return sha256_S(a,17)^sha256_S(a,19)^sha256_R(a,10)}function sha256_Sigma0512(a){return sha256_S(a,28)^sha256_S(a,34)^sha256_S(a,39)}function sha256_Sigma1512(a){return sha256_S(a,14)^sha256_S(a,18)^sha256_S(a,41)}function sha256_Gamma0512(a){return sha256_S(a,1)^sha256_S(a,8)^sha256_R(a,7)}
-function sha256_Gamma1512(a){return sha256_S(a,19)^sha256_S(a,61)^sha256_R(a,6)}
-var sha256_K=[1116352408,1899447441,-1245643825,-373957723,961987163,1508970993,-1841331548,-1424204075,-670586216,310598401,607225278,1426881987,1925078388,-2132889090,-1680079193,-1046744716,-459576895,-272742522,264347078,604807628,770255983,1249150122,1555081692,1996064986,-1740746414,-1473132947,-1341970488,-1084653625,-958395405,-710438585,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,-2117940946,-1838011259,-1564481375,-1474664885,-1035236496,-949202525,
--778901479,-694614492,-200395387,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,-2067236844,-1933114872,-1866530822,-1538233109,-1090935817,-965641998];function binb_sha256(a,b){var c=[1779033703,-1150833019,1013904242,-1521486534,1359893119,-1694144372,528734635,1541459225],d=Array(64);a[b>>5]|=128<<24-b%32;a[(b+64>>9<<4)+15]=b;for(var e=0;e<a.length;e+=16)processBlock_sha256(a,e,c,d);return c}
-function processBlock_sha256(a,b,c,d){var e,f,g,h,j,l,n,m,p,k,q;e=c[0];f=c[1];g=c[2];h=c[3];j=c[4];l=c[5];n=c[6];m=c[7];for(p=0;64>p;p++)d[p]=16>p?a[p+b]:safe_add(safe_add(safe_add(sha256_Gamma1256(d[p-2]),d[p-7]),sha256_Gamma0256(d[p-15])),d[p-16]),k=safe_add(safe_add(safe_add(safe_add(m,sha256_Sigma1256(j)),sha256_Ch(j,l,n)),sha256_K[p]),d[p]),q=safe_add(sha256_Sigma0256(e),sha256_Maj(e,f,g)),m=n,n=l,l=j,j=safe_add(h,k),h=g,g=f,f=e,e=safe_add(k,q);c[0]=safe_add(e,c[0]);c[1]=safe_add(f,c[1]);c[2]=
-safe_add(g,c[2]);c[3]=safe_add(h,c[3]);c[4]=safe_add(j,c[4]);c[5]=safe_add(l,c[5]);c[6]=safe_add(n,c[6]);c[7]=safe_add(m,c[7])}function safe_add(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535}var Sha256=function(){this.W=Array(64);this.hash=[1779033703,-1150833019,1013904242,-1521486534,1359893119,-1694144372,528734635,1541459225];this.nTotalBytes=0;this.buffer=new Uint8Array(64);this.nBufferBytes=0};
-Sha256.prototype.update=function(a){this.nTotalBytes+=a.length;if(0<this.nBufferBytes){var b=this.buffer.length-this.nBufferBytes;if(a.length<b){this.buffer.set(a,this.nBufferBytes);this.nBufferBytes+=a.length;return}this.buffer.set(a.subarray(0,b),this.nBufferBytes);processBlock_sha256(byteArray2binb(this.buffer),0,this.hash,this.W);this.nBufferBytes=0;a=a.subarray(b,a.length);if(0==a.length)return}b=a.length>>6;if(0<b){for(var b=64*b,c=byteArray2binb(a.subarray(0,b)),d=0;d<c.length;d+=16)processBlock_sha256(c,
-d,this.hash,this.W);a=a.subarray(b,a.length)}0<a.length&&(this.buffer.set(a),this.nBufferBytes=a.length)};Sha256.prototype.finalize=function(){var a=byteArray2binb(this.buffer.subarray(0,this.nBufferBytes)),b=8*this.nBufferBytes;a[b>>5]|=128<<24-b%32;a[(b+64>>9<<4)+15]=8*this.nTotalBytes;for(b=0;b<a.length;b+=16)processBlock_sha256(a,b,this.hash,this.W);return Sha256.binb2Uint8Array(this.hash)};
-Sha256.binb2Uint8Array=function(a){for(var b=new Uint8Array(4*a.length),c=0,d=0;d<32*a.length;d+=8)b[c++]=a[d>>5]>>>24-d%32&255;return b};var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b64pad="=";
-function hex2b64(a){var b,c,d="";for(b=0;b+3<=a.length;b+=3)c=parseInt(a.substring(b,b+3),16),d+=b64map.charAt(c>>6)+b64map.charAt(c&63);b+1==a.length?(c=parseInt(a.substring(b,b+1),16),d+=b64map.charAt(c<<2)):b+2==a.length&&(c=parseInt(a.substring(b,b+2),16),d+=b64map.charAt(c>>2)+b64map.charAt((c&3)<<4));for(;0<(d.length&3);)d+=b64pad;return d}
-function b64tohex(a){var b="",c,d=0,e;for(c=0;c<a.length&&a.charAt(c)!=b64pad;++c){var f=b64map.indexOf(a.charAt(c));0>f||(0==d?(b+=int2char(f>>2),e=f&3,d=1):1==d?(b+=int2char(e<<2|f>>4),e=f&15,d=2):2==d?(b+=int2char(e),b+=int2char(f>>2),e=f&3,d=3):(b+=int2char(e<<2|f>>4),b+=int2char(f&15),d=0))}1==d&&(b+=int2char(e<<2));return b}function b64toBA(a){a=b64tohex(a);var b,c=[];for(b=0;2*b<a.length;++b)c[b]=parseInt(a.substring(2*b,2*b+2),16);return c}
-function parseBigInt(a,b){return new BigInteger(a,b)}function linebrk(a,b){for(var c="",d=0;d+b<a.length;)c+=a.substring(d,d+b)+"\n",d+=b;return c+a.substring(d,a.length)}function byte2Hex(a){return 16>a?"0"+a.toString(16):a.toString(16)}
-function pkcs1pad2(a,b){if(b<a.length+11)return alert("Message too long for RSA"),null;for(var c=[],d=a.length-1;0<=d&&0<b;){var e=a.charCodeAt(d--);128>e?c[--b]=e:127<e&&2048>e?(c[--b]=e&63|128,c[--b]=e>>6|192):(c[--b]=e&63|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;d=new SecureRandom;for(e=[];2<b;){for(e[0]=0;0==e[0];)d.nextBytes(e);c[--b]=e[0]}c[--b]=2;c[--b]=0;return new BigInteger(c)}function RSAKey(){this.n=null;this.e=0;this.coeff=this.dmq1=this.dmp1=this.q=this.p=this.d=null}
-function RSASetPublic(a,b){null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16)):alert("Invalid RSA public key")}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}function RSAEncrypt(a){a=pkcs1pad2(a,this.n.bitLength()+7>>3);if(null==a)return null;a=this.doPublic(a);if(null==a)return null;a=a.toString(16);return 0==(a.length&1)?a:"0"+a}RSAKey.prototype.doPublic=RSADoPublic;RSAKey.prototype.setPublic=RSASetPublic;RSAKey.prototype.encrypt=RSAEncrypt;
+/*
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+  MIT
+ <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE">MIT License</a>
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+ <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
+*/
+(function(a,b){"object"===typeof exports?module.exports.printStackTrace=b():"function"===typeof define&&define.amd?define(b):a.printStackTrace=b()})(this,function(){function a(b){b=b||{guess:!0};var c=b.e||null,d=!!b.guess,e=b.mode||null;b=new a.implementation;c=b.run(c,e);return d?b.guessAnonymousFunctions(c):c}a.implementation=function(){};a.implementation.prototype={run:function(a,c){a=a||this.createException();c=c||this.mode(a);return"other"===c?this.other(arguments.callee):this[c](a)},createException:function(){try{this.undef()}catch(a){return a}},
+mode:function(a){return"undefined"!==typeof window&&-1<window.navigator.userAgent.indexOf("PhantomJS")?"phantomjs":a.arguments&&a.stack?"chrome":a.stack&&a.sourceURL?"safari":a.stack&&a.number?"ie":a.stack&&a.fileName?"firefox":a.message&&a["opera#sourceloc"]?!a.stacktrace||-1<a.message.indexOf("\n")&&a.message.split("\n").length>a.stacktrace.split("\n").length?"opera9":"opera10a":a.message&&a.stack&&a.stacktrace?0>a.stacktrace.indexOf("called from line")?"opera10b":"opera11":a.stack&&!a.fileName?
+"chrome":"other"},instrumentFunction:function(b,c,d){b=b||window;var e=b[c];b[c]=function(){d.call(this,a().slice(4));return b[c]._instrumented.apply(this,arguments)};b[c]._instrumented=e},deinstrumentFunction:function(a,c){a[c].constructor===Function&&a[c]._instrumented&&a[c]._instrumented.constructor===Function&&(a[c]=a[c]._instrumented)},chrome:function(a){return(a.stack+"\n").replace(/^[\s\S]+?\s+at\s+/," at ").replace(/^\s+(at eval )?at\s+/gm,"").replace(/^([^\(]+?)([\n$])/gm,"{anonymous}() ($1)$2").replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm,
+"{anonymous}() ($1)").replace(/^(.+) \((.+)\)$/gm,"$1@$2").split("\n").slice(0,-1)},safari:function(a){return a.stack.replace(/\[native code\]\n/m,"").replace(/^(?=\w+Error\:).*$\n/m,"").replace(/^@/gm,"{anonymous}()@").split("\n")},ie:function(a){return a.stack.replace(/^\s*at\s+(.*)$/gm,"$1").replace(/^Anonymous function\s+/gm,"{anonymous}() ").replace(/^(.+)\s+\((.+)\)$/gm,"$1@$2").split("\n").slice(1)},firefox:function(a){return a.stack.replace(/(?:\n@:0)?\s+$/m,"").replace(/^(?:\((\S*)\))?@/gm,
+"{anonymous}($1)@").split("\n")},opera11:function(a){var c=/^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/;a=a.stacktrace.split("\n");for(var d=[],e=0,f=a.length;e<f;e+=2){var g=c.exec(a[e]);if(g){var h=g[4]+":"+g[1]+":"+g[2],g=g[3]||"global code",g=g.replace(/<anonymous function: (\S+)>/,"$1").replace(/<anonymous function>/,"{anonymous}");d.push(g+"@"+h+" -- "+a[e+1].replace(/^\s+/,""))}}return d},opera10b:function(a){var c=/^(.*)@(.+):(\d+)$/;a=a.stacktrace.split("\n");for(var d=[],e=0,f=
+a.length;e<f;e++){var g=c.exec(a[e]);g&&d.push((g[1]?g[1]+"()":"global code")+"@"+g[2]+":"+g[3])}return d},opera10a:function(a){var c=/Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;a=a.stacktrace.split("\n");for(var d=[],e=0,f=a.length;e<f;e+=2){var g=c.exec(a[e]);g&&d.push((g[3]||"{anonymous}")+"()@"+g[2]+":"+g[1]+" -- "+a[e+1].replace(/^\s+/,""))}return d},opera9:function(a){var c=/Line (\d+).*script (?:in )?(\S+)/i;a=a.message.split("\n");for(var d=[],e=2,f=a.length;e<f;e+=2){var g=
+c.exec(a[e]);g&&d.push("{anonymous}()@"+g[2]+":"+g[1]+" -- "+a[e+1].replace(/^\s+/,""))}return d},phantomjs:function(a){var c=/(\S+) \((\S+)\)/i;a=a.stack.split("\n");for(var d=[],e=1,f=a.length;e<f;e++){a[e]=a[e].replace(/^\s+at\s+/gm,"");var g=c.exec(a[e]);g?d.push(g[1]+"()@"+g[2]):d.push("{anonymous}()@"+a[e])}return d},other:function(a){for(var c=/function(?:\s+([\w$]+))?\s*\(/,d=[],e,f,g=Array.prototype.slice;a&&10>d.length;){e=c.test(a.toString())?RegExp.$1||"{anonymous}":"{anonymous}";try{f=
+g.call(a.arguments||[])}catch(h){f=["Cannot access arguments: "+h]}d[d.length]=e+"("+this.stringifyArguments(f)+")";try{a=a.caller}catch(k){d[d.length]="Cannot access caller: "+k;break}}return d},stringifyArguments:function(a){for(var c=[],d=Array.prototype.slice,e=0;e<a.length;++e){var f=a[e];void 0===f?c[e]="undefined":null===f?c[e]="null":f.constructor&&(c[e]=f.constructor===Array?3>f.length?"["+this.stringifyArguments(f)+"]":"["+this.stringifyArguments(d.call(f,0,1))+"..."+this.stringifyArguments(d.call(f,
+-1))+"]":f.constructor===Object?"#object":f.constructor===Function?"#function":f.constructor===String?'"'+f+'"':f.constructor===Number?f:"?")}return c.join(",")},sourceCache:{},ajax:function(a){var c=this.createXMLHTTPObject();if(c)try{return c.open("GET",a,!1),c.send(null),c.responseText}catch(d){}return""},createXMLHTTPObject:function(){for(var a,c=[function(){return new XMLHttpRequest},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml3.XMLHTTP")},
+function(){return new ActiveXObject("Microsoft.XMLHTTP")}],d=0;d<c.length;d++)try{return a=c[d](),this.createXMLHTTPObject=c[d],a}catch(e){}},isSameDomain:function(a){return"undefined"!==typeof location&&-1!==a.indexOf(location.hostname)},getSource:function(a){a in this.sourceCache||(this.sourceCache[a]=this.ajax(a).split("\n"));return this.sourceCache[a]},guessAnonymousFunctions:function(a){for(var c=0;c<a.length;++c){var d=/^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/,e=a[c],f=/\{anonymous\}\(.*\)@(.*)/.exec(e);
+if(f){var g=d.exec(f[1]);g&&(d=g[1],f=g[2],g=g[3]||0,d&&this.isSameDomain(d)&&f&&(d=this.guessAnonymousFunction(d,f,g),a[c]=e.replace("{anonymous}",d)))}}return a},guessAnonymousFunction:function(a,c,d){var e;try{e=this.findFunctionName(this.getSource(a),c)}catch(f){e="getSource failed with url: "+a+", exception: "+f.toString()}return e},findFunctionName:function(a,c){for(var d=/function\s+([^(]*?)\s*\(([^)]*)\)/,e=/['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*function\b/,f=/['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*(?:eval|new Function)\b/,
+g="",h,k=Math.min(c,20),l,m=0;m<k;++m)if(h=a[c-m-1],l=h.indexOf("//"),0<=l&&(h=h.substr(0,l)),h)if(g=h+g,(h=e.exec(g))&&h[1]||(h=d.exec(g))&&h[1]||(h=f.exec(g))&&h[1])return h[1];return"(?)"}};return a});var ndn=ndn||{},exports=ndn,module={};function require(){return ndn}exports.printStackTrace=printStackTrace;
+function DetectSubtleCrypto(){var a=!1;if("undefined"!==typeof crypto&&crypto&&crypto.subtle){var b={name:"RSASSA-PKCS1-v1_5",modulusLength:2048,hash:{name:"SHA-256"},publicExponent:new Uint8Array([1,0,1])},c;crypto.subtle.generateKey(b,!0,["sign","verify"]).then(function(a){c=a;return crypto.subtle.sign(b,a.privateKey,new Uint8Array([1,2,3,4,5]))}).then(function(a){return crypto.subtle.verify(b,c.publicKey,a,new Uint8Array([1,2,3,4,5]))}).then(function(a){return crypto.subtle.exportKey("pkcs8",c.privateKey)}).then(function(a){return crypto.subtle.importKey("pkcs8",
+a,b,!0,["sign"])}).then(function(a){return crypto.subtle.exportKey("spki",c.publicKey)}).then(function(a){return crypto.subtle.importKey("spki",a,b,!0,["verify"])}).then(function(a){a=new Uint8Array([1,2,3,4,5]);return crypto.subtle.digest({name:"SHA-256"},a.buffer)}).then(function(b){a=!0},function(a){console.log("DetectSubtleCrypto encountered error, not using crypto.subtle: ",a)})}return function(){return a}}var UseSubtleCrypto=DetectSubtleCrypto();exports.UseSubtleCrypto=UseSubtleCrypto;
+var CryptoJS=CryptoJS||function(a,b){var c={},d=c.lib={},e=d.Base=function(){function a(){}return{extend:function(b){a.prototype=this;var c=new a;b&&c.mixIn(b);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},
+clone:function(){return this.init.prototype.extend(this)}}}(),f=d.WordArray=e.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=b?c:4*a.length},toString:function(a){return(a||h).stringify(this)},concat:function(a){var b=this.words,c=a.words,d=this.sigBytes;a=a.sigBytes;this.clamp();if(d%4)for(var e=0;e<a;e++)b[d+e>>>2]|=(c[e>>>2]>>>24-e%4*8&255)<<24-(d+e)%4*8;else for(e=0;e<a;e+=4)b[d+e>>>2]=c[e>>>2];this.sigBytes+=a;return this},clamp:function(){var b=this.words,c=this.sigBytes;b[c>>>
+2]&=4294967295<<32-c%4*8;b.length=a.ceil(c/4)},clone:function(){var a=e.clone.call(this);a.words=this.words.slice(0);return a},random:function(b){for(var c=[],d=0;d<b;d+=4)c.push(4294967296*a.random()|0);return new f.init(c,b)}}),g=c.enc={},h=g.Hex={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],d=0;d<a;d++){var e=b[d>>>2]>>>24-d%4*8&255;c.push((e>>>4).toString(16));c.push((e&15).toString(16))}return c.join("")},parse:function(a){for(var b=a.length,c=[],d=0;d<b;d+=2)c[d>>>3]|=parseInt(a.substr(d,
+2),16)<<24-d%8*4;return new f.init(c,b/2)}},k=g.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],d=0;d<a;d++)c.push(String.fromCharCode(b[d>>>2]>>>24-d%4*8&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],d=0;d<b;d++)c[d>>>2]|=(a.charCodeAt(d)&255)<<24-d%4*8;return new f.init(c,b)}},l=g.Utf8={stringify:function(a){try{return decodeURIComponent(escape(k.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return k.parse(unescape(encodeURIComponent(a)))}},
+m=d.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new f.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=l.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(b){var c=this._data,d=c.words,e=c.sigBytes,g=this.blockSize,h=e/(4*g),h=b?a.ceil(h):a.max((h|0)-this._minBufferSize,0);b=h*g;e=a.min(4*b,e);if(b){for(var k=0;k<b;k+=g)this._doProcessBlock(d,k);k=d.splice(0,b);c.sigBytes-=e}return new f.init(k,e)},clone:function(){var a=e.clone.call(this);
+a._data=this._data.clone();return a},_minBufferSize:0});d.Hasher=m.extend({cfg:e.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){m.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,c){return(new a.init(c)).finalize(b)}},_createHmacHelper:function(a){return function(b,c){return(new q.HMAC.init(a,
+c)).finalize(b)}}});var q=c.algo={};return c}(Math);exports.CryptoJS=CryptoJS;module.exports=exports;var C=require("./core.js").CryptoJS;
+(function(a){var b=C.lib,c=b.WordArray,d=b.Hasher,b=C.algo,e=[],f=[];(function(){function b(c){for(var d=a.sqrt(c),e=2;e<=d;e++)if(!(c%e))return!1;return!0}function c(a){return 4294967296*(a-(a|0))|0}for(var d=2,g=0;64>g;)b(d)&&(8>g&&(e[g]=c(a.pow(d,0.5))),f[g]=c(a.pow(d,1/3)),g++),d++})();var g=[],b=b.SHA256=d.extend({_doReset:function(){this._hash=new c.init(e.slice(0))},_doProcessBlock:function(a,b){for(var c=this._hash.words,d=c[0],e=c[1],p=c[2],s=c[3],w=c[4],M=c[5],O=c[6],K=c[7],x=0;64>x;x++){if(16>
+x)g[x]=a[b+x]|0;else{var A=g[x-15],I=g[x-2];g[x]=((A<<25|A>>>7)^(A<<14|A>>>18)^A>>>3)+g[x-7]+((I<<15|I>>>17)^(I<<13|I>>>19)^I>>>10)+g[x-16]}A=K+((w<<26|w>>>6)^(w<<21|w>>>11)^(w<<7|w>>>25))+(w&M^~w&O)+f[x]+g[x];I=((d<<30|d>>>2)^(d<<19|d>>>13)^(d<<10|d>>>22))+(d&e^d&p^e&p);K=O;O=M;M=w;w=s+A|0;s=p;p=e;e=d;d=A+I|0}c[0]=c[0]+d|0;c[1]=c[1]+e|0;c[2]=c[2]+p|0;c[3]=c[3]+s|0;c[4]=c[4]+w|0;c[5]=c[5]+M|0;c[6]=c[6]+O|0;c[7]=c[7]+K|0},_doFinalize:function(){var b=this._data,c=b.words,d=8*this._nDataBytes,e=8*b.sigBytes;
+c[e>>>5]|=128<<24-e%32;c[(e+64>>>9<<4)+14]=a.floor(d/4294967296);c[(e+64>>>9<<4)+15]=d;b.sigBytes=4*c.length;this._process();return this._hash},clone:function(){var a=d.clone.call(this);a._hash=this._hash.clone();return a}});C.SHA256=d._createHelper(b);C.HmacSHA256=d._createHmacHelper(b)})(Math);exports.CryptoJS=C;module.exports=exports;
+(function(){var a=CryptoJS,b=a.enc.Utf8;a.algo.HMAC=a.lib.Base.extend({init:function(a,d){a=this._hasher=new a.init;"string"==typeof d&&(d=b.parse(d));var e=a.blockSize,f=4*e;d.sigBytes>f&&(d=a.finalize(d));d.clamp();for(var g=this._oKey=d.clone(),h=this._iKey=d.clone(),k=g.words,l=h.words,m=0;m<e;m++)k[m]^=1549556828,l[m]^=909522486;g.sigBytes=h.sigBytes=f;this.reset()},reset:function(){var a=this._hasher;a.reset();a.update(this._iKey)},update:function(a){this._hasher.update(a);return this},finalize:function(a){var b=
+this._hasher;a=b.finalize(a);b.reset();return b.finalize(this._oKey.clone().concat(a))}})})();var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b64pad="=";
+function hex2b64(a){var b,c,d="";for(b=0;b+3<=a.length;b+=3)c=parseInt(a.substring(b,b+3),16),d+=b64map.charAt(c>>6)+b64map.charAt(c&63);b+1==a.length?(c=parseInt(a.substring(b,b+1),16),d+=b64map.charAt(c<<2)):b+2==a.length&&(c=parseInt(a.substring(b,b+2),16),d+=b64map.charAt(c>>2)+b64map.charAt((c&3)<<4));if(b64pad)for(;0<(d.length&3);)d+=b64pad;return d}
+function b64tohex(a){var b="",c,d=0,e,f;for(c=0;c<a.length&&a.charAt(c)!=b64pad;++c)f=b64map.indexOf(a.charAt(c)),0>f||(0==d?(b+=int2char(f>>2),e=f&3,d=1):1==d?(b+=int2char(e<<2|f>>4),e=f&15,d=2):2==d?(b+=int2char(e),b+=int2char(f>>2),e=f&3,d=3):(b+=int2char(e<<2|f>>4),b+=int2char(f&15),d=0));1==d&&(b+=int2char(e<<2));return b}function b64toBA(a){a=b64tohex(a);var b,c=[];for(b=0;2*b<a.length;++b)c[b]=parseInt(a.substring(2*b,2*b+2),16);return c}exports.b64tohex=b64tohex;exports.b64toBA=b64toBA;
+exports.hex2b64=hex2b64;module.exports=exports;function Arcfour(){this.j=this.i=0;this.S=[]}function ARC4init(a){var b,c,d;for(b=0;256>b;++b)this.S[b]=b;for(b=c=0;256>b;++b)c=c+this.S[b]+a[b%a.length]&255,d=this.S[b],this.S[b]=this.S[c],this.S[c]=d;this.j=this.i=0}function ARC4next(){var a;this.i=this.i+1&255;this.j=this.j+this.S[this.i]&255;a=this.S[this.i];this.S[this.i]=this.S[this.j];this.S[this.j]=a;return this.S[a+this.S[this.i]&255]}Arcfour.prototype.init=ARC4init;Arcfour.prototype.next=ARC4next;
+function prng_newstate(){return new Arcfour}var rng_psize=256,rng_state,rng_pool,rng_pptr;function rng_seed_int(a){rng_pool[rng_pptr++]^=a&255;rng_pool[rng_pptr++]^=a>>8&255;rng_pool[rng_pptr++]^=a>>16&255;rng_pool[rng_pptr++]^=a>>24&255;rng_pptr>=rng_psize&&(rng_pptr-=rng_psize)}function rng_seed_time(){rng_seed_int((new Date).getTime())}
+if(null==rng_pool){rng_pool=[];rng_pptr=0;var t;if("Netscape"==navigator.appName&&"5">navigator.appVersion&&window.crypto){var z=window.crypto.random(32);for(t=0;t<z.length;++t)rng_pool[rng_pptr++]=z.charCodeAt(t)&255}for(;rng_pptr<rng_psize;)t=Math.floor(65536*Math.random()),rng_pool[rng_pptr++]=t>>>8,rng_pool[rng_pptr++]=t&255;rng_pptr=0;rng_seed_time()}
+function rng_get_byte(){if(null==rng_state){rng_seed_time();rng_state=prng_newstate();rng_state.init(rng_pool);for(rng_pptr=0;rng_pptr<rng_pool.length;++rng_pptr)rng_pool[rng_pptr]=0;rng_pptr=0}return rng_state.next()}function rng_get_bytes(a){var b;for(b=0;b<a.length;++b)a[b]=rng_get_byte()}function SecureRandom(){}SecureRandom.prototype.nextBytes=rng_get_bytes;var intShim=require("jsbn");function parseBigInt(a,b){return new BigInteger(a,b)}
+function linebrk(a,b){for(var c="",d=0;d+b<a.length;)c+=a.substring(d,d+b)+"\n",d+=b;return c+a.substring(d,a.length)}function byte2Hex(a){return 16>a?"0"+a.toString(16):a.toString(16)}
+function pkcs1pad2(a,b){if(b<a.length+11)return alert("Message too long for RSA"),null;for(var c=[],d=a.length-1;0<=d&&0<b;){var e=a.charCodeAt(d--);128>e?c[--b]=e:127<e&&2048>e?(c[--b]=e&63|128,c[--b]=e>>6|192):(c[--b]=e&63|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;d=new SecureRandom;for(e=[];2<b;){for(e[0]=0;0==e[0];)d.nextBytes(e);c[--b]=e[0]}c[--b]=2;c[--b]=0;return new BigInteger(c)}
+function oaep_mgf1_arr(a,b,c){for(var d="",e=0;d.length<b;)d+=c(String.fromCharCode.apply(String,a.concat([(e&4278190080)>>24,(e&16711680)>>16,(e&65280)>>8,e&255]))),e+=1;return d}var SHA1_SIZE=20;
+function oaep_pad(a,b,c){if(a.length+2*SHA1_SIZE+2>b)throw"Message too long for RSA";var d="",e;for(e=0;e<b-a.length-2*SHA1_SIZE-2;e+=1)d+="\x00";b=rstr_sha1("")+d+"\u0001"+a;a=Array(SHA1_SIZE);(new SecureRandom).nextBytes(a);d=oaep_mgf1_arr(a,b.length,c||rstr_sha1);c=[];for(e=0;e<b.length;e+=1)c[e]=b.charCodeAt(e)^d.charCodeAt(e);b=oaep_mgf1_arr(c,a.length,rstr_sha1);d=[0];for(e=0;e<a.length;e+=1)d[e+1]=a[e]^b.charCodeAt(e);return new BigInteger(d.concat(c))}
+function RSAKey(){this.n=null;this.e=0;this.coeff=this.dmq1=this.dmp1=this.q=this.p=this.d=null}function RSASetPublic(a,b){this.isPublic=!0;"string"!==typeof a?(this.n=a,this.e=b):null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16)):alert("Invalid RSA public key")}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}
+function RSAEncrypt(a){a=pkcs1pad2(a,this.n.bitLength()+7>>3);if(null==a)return null;a=this.doPublic(a);if(null==a)return null;a=a.toString(16);return 0==(a.length&1)?a:"0"+a}function RSAEncryptOAEP(a,b){var c=oaep_pad(a,this.n.bitLength()+7>>3,b);if(null==c)return null;c=this.doPublic(c);if(null==c)return null;c=c.toString(16);return 0==(c.length&1)?c:"0"+c}RSAKey.prototype.doPublic=RSADoPublic;RSAKey.prototype.setPublic=RSASetPublic;RSAKey.prototype.encrypt=RSAEncrypt;
+RSAKey.prototype.encryptOAEP=RSAEncryptOAEP;RSAKey.prototype.type="RSA";exports.RSAKey=RSAKey;module.exports=exports;var intShim=require("jsbn"),BigInteger=intShim.BigInteger?intShim.BigInteger:intShim,RSAKey=require("./rsa.js").RSAKey;
 function pkcs1unpad2(a,b){for(var c=a.toByteArray(),d=0;d<c.length&&0==c[d];)++d;if(c.length-d!=b-1||2!=c[d])return null;for(++d;0!=c[d];)if(++d>=c.length)return null;for(var e="";++d<c.length;){var f=c[d]&255;128>f?e+=String.fromCharCode(f):191<f&&224>f?(e+=String.fromCharCode((f&31)<<6|c[d+1]&63),++d):(e+=String.fromCharCode((f&15)<<12|(c[d+1]&63)<<6|c[d+2]&63),d+=2)}return e}
-function RSASetPrivate(a,b,c){null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16)):alert("Invalid RSA private key")}
-function RSASetPrivateEx(a,b,c,d,e,f,g,h){null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16),this.p=parseBigInt(d,16),this.q=parseBigInt(e,16),this.dmp1=parseBigInt(f,16),this.dmq1=parseBigInt(g,16),this.coeff=parseBigInt(h,16)):alert("Invalid RSA private key")}
-function RSAGenerate(a,b){var c=new SecureRandom,d=a>>1;this.e=parseInt(b,16);for(var e=new BigInteger(b,16);;){for(;!(this.p=new BigInteger(a-d,1,c),0==this.p.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)&&this.p.isProbablePrime(10)););for(;!(this.q=new BigInteger(d,1,c),0==this.q.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)&&this.q.isProbablePrime(10)););if(0>=this.p.compareTo(this.q)){var f=this.p;this.p=this.q;this.q=f}var f=this.p.subtract(BigInteger.ONE),g=this.q.subtract(BigInteger.ONE),
-h=f.multiply(g);if(0==h.gcd(e).compareTo(BigInteger.ONE)){this.n=this.p.multiply(this.q);this.d=e.modInverse(h);this.dmp1=this.d.mod(f);this.dmq1=this.d.mod(g);this.coeff=this.q.modInverse(this.p);break}}}function RSADoPrivate(a){if(null==this.p||null==this.q)return a.modPow(this.d,this.n);var b=a.mod(this.p).modPow(this.dmp1,this.p);for(a=a.mod(this.q).modPow(this.dmq1,this.q);0>b.compareTo(a);)b=b.add(this.p);return b.subtract(a).multiply(this.coeff).mod(this.p).multiply(this.q).add(a)}
-function RSADecrypt(a){a=parseBigInt(a,16);a=this.doPrivate(a);return null==a?null:pkcs1unpad2(a,this.n.bitLength()+7>>3)}RSAKey.prototype.doPrivate=RSADoPrivate;RSAKey.prototype.setPrivate=RSASetPrivate;RSAKey.prototype.setPrivateEx=RSASetPrivateEx;RSAKey.prototype.generate=RSAGenerate;RSAKey.prototype.decrypt=RSADecrypt;function _rsapem_pemToBase64(a){a=a.replace("-----BEGIN RSA PRIVATE KEY-----","");a=a.replace("-----END RSA PRIVATE KEY-----","");return a=a.replace(/[ \n]+/g,"")}
-function _rsapem_getPosArrayOfChildrenFromHex(a){var b=[],c=ASN1HEX.getStartPosOfV_AtObj(a,0),d=ASN1HEX.getPosOfNextSibling_AtObj(a,c),e=ASN1HEX.getPosOfNextSibling_AtObj(a,d),f=ASN1HEX.getPosOfNextSibling_AtObj(a,e),g=ASN1HEX.getPosOfNextSibling_AtObj(a,f),h=ASN1HEX.getPosOfNextSibling_AtObj(a,g),j=ASN1HEX.getPosOfNextSibling_AtObj(a,h),l=ASN1HEX.getPosOfNextSibling_AtObj(a,j);a=ASN1HEX.getPosOfNextSibling_AtObj(a,l);b.push(c,d,e,f,g,h,j,l,a);return b}
-function _rsapem_getHexValueArrayOfChildrenFromHex(a){var b=_rsapem_getPosArrayOfChildrenFromHex(a),c=ASN1HEX.getHexOfV_AtObj(a,b[0]),d=ASN1HEX.getHexOfV_AtObj(a,b[1]),e=ASN1HEX.getHexOfV_AtObj(a,b[2]),f=ASN1HEX.getHexOfV_AtObj(a,b[3]),g=ASN1HEX.getHexOfV_AtObj(a,b[4]),h=ASN1HEX.getHexOfV_AtObj(a,b[5]),j=ASN1HEX.getHexOfV_AtObj(a,b[6]),l=ASN1HEX.getHexOfV_AtObj(a,b[7]);a=ASN1HEX.getHexOfV_AtObj(a,b[8]);b=[];b.push(c,d,e,f,g,h,j,l,a);return b}
-function _rsapem_readPrivateKeyFromPEMString(a){a=_rsapem_pemToBase64(a);a=b64tohex(a);a=_rsapem_getHexValueArrayOfChildrenFromHex(a);this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])}RSAKey.prototype.readPrivateKeyFromPEMString=_rsapem_readPrivateKeyFromPEMString;var _RSASIGN_DIHEAD=[];_RSASIGN_DIHEAD.sha1="3021300906052b0e03021a05000414";_RSASIGN_DIHEAD.sha256="3031300d060960864801650304020105000420";_RSASIGN_DIHEAD.sha384="3041300d060960864801650304020205000430";
-_RSASIGN_DIHEAD.sha512="3051300d060960864801650304020305000440";_RSASIGN_DIHEAD.md2="3020300c06082a864886f70d020205000410";_RSASIGN_DIHEAD.md5="3020300c06082a864886f70d020505000410";_RSASIGN_DIHEAD.ripemd160="3021300906052b2403020105000414";var _RSASIGN_HASHHEXFUNC=[];_RSASIGN_HASHHEXFUNC.sha1=function(a){return hex_sha1(a)};_RSASIGN_HASHHEXFUNC.sha256=function(a){return hex_sha256(a)};_RSASIGN_HASHHEXFUNC.sha512=function(a){return hex_sha512(a)};_RSASIGN_HASHHEXFUNC.md5=function(a){return hex_md5(a)};
-_RSASIGN_HASHHEXFUNC.ripemd160=function(a){return hex_rmd160(a)};var _RSASIGN_HASHBYTEFUNC=[];_RSASIGN_HASHBYTEFUNC.sha256=function(a){return hex_sha256_from_bytes(a)};var _RE_HEXDECONLY=RegExp("");_RE_HEXDECONLY.compile("[^0-9a-f]","gi");function _rsasign_getHexPaddedDigestInfoForString(a,b,c){b/=4;a=(0,_RSASIGN_HASHHEXFUNC[c])(a);c="00"+_RSASIGN_DIHEAD[c]+a;a="";b=b-4-c.length;for(var d=0;d<b;d+=2)a+="ff";return sPaddedMessageHex="0001"+a+c}
-function _rsasign_getHexPaddedDigestInfoForStringHEX(a,b,c){b/=4;a=(0,_RSASIGN_HASHHEXFUNC[c])(a);c="00"+_RSASIGN_DIHEAD[c]+a;a="";b=b-4-c.length;for(var d=0;d<b;d+=2)a+="ff";return sPaddedMessageHex="0001"+a+c}function _rsasign_getHexPaddedDigestInfoForByteArray(a,b,c){b/=4;a=(0,_RSASIGN_HASHBYTEFUNC[c])(a);c="00"+_RSASIGN_DIHEAD[c]+a;a="";b=b-4-c.length;for(var d=0;d<b;d+=2)a+="ff";return sPaddedMessageHex="0001"+a+c}
-function _zeroPaddingOfSignature(a,b){for(var c="",d=b/4-a.length,e=0;e<d;e++)c+="0";return c+a}function _rsasign_signString(a,b){var c=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),b),c=parseBigInt(c,16),c=this.doPrivate(c).toString(16);return _zeroPaddingOfSignature(c,this.n.bitLength())}
-function _rsasign_signStringHEX(a,b){var c=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),b),c=parseBigInt(c,16),c=this.doPrivate(c).toString(16);return _zeroPaddingOfSignature(c,this.n.bitLength())}function _rsasign_signByteArray(a,b,c){a=_rsasign_getHexPaddedDigestInfoForByteArray(a,c.n.bitLength(),b);a=parseBigInt(a,16);a=c.doPrivate(a).toString(16);return _zeroPaddingOfSignature(a,c.n.bitLength())}
-function _rsasign_signByteArrayWithSHA256(a){return _rsasign_signByteArray(a,"sha256",this)}function _rsasign_signStringWithSHA1(a){return _rsasign_signString(a,"sha1")}function _rsasign_signStringWithSHA256(a){return _rsasign_signString(a,"sha256")}function _rsasign_getDecryptSignatureBI(a,b,c){var d=new RSAKey;d.setPublic(b,c);return d.doPublic(a)}function _rsasign_getHexDigestInfoFromSig(a,b,c){return _rsasign_getDecryptSignatureBI(a,b,c).toString(16).replace(/^1f+00/,"")}
-function _rsasign_getAlgNameAndHashFromHexDisgestInfo(a){for(var b in _RSASIGN_DIHEAD){var c=_RSASIGN_DIHEAD[b],d=c.length;if(a.substring(0,d)==c)return[b,a.substring(d)]}return[]}function _rsasign_verifySignatureWithArgs(a,b,c,d){b=_rsasign_getHexDigestInfoFromSig(b,c,d);c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(b);if(0==c.length)return!1;b=c[1];a=(0,_RSASIGN_HASHHEXFUNC[c[0]])(a);return b==a}
-function _rsasign_verifyHexSignatureForMessage(a,b){var c=parseBigInt(a,16);return _rsasign_verifySignatureWithArgs(b,c,this.n.toString(16),this.e.toString(16))}
-function _rsasign_verifyString(a,b){b=b.replace(_RE_HEXDECONLY,"");3<LOG&&console.log("n is "+this.n);3<LOG&&console.log("e is "+this.e);if(b.length!=this.n.bitLength()/4)return 0;b=b.replace(/[ \n]+/g,"");var c=parseBigInt(b,16),c=this.doPublic(c).toString(16).replace(/^1f+00/,""),d=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);if(0==d.length)return!1;c=d[1];d=(0,_RSASIGN_HASHHEXFUNC[d[0]])(a);return c==d}
-function _rsasign_verifyByteArray(a,b,c){c=c.replace(_RE_HEXDECONLY,"");3<LOG&&console.log("n is "+this.n);3<LOG&&console.log("e is "+this.e);if(c.length!=this.n.bitLength()/4)return 0;c=c.replace(/[ \n]+/g,"");c=parseBigInt(c,16);c=this.doPublic(c).toString(16).replace(/^1f+00/,"");c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);if(0==c.length)return!1;var d=c[0];c=c[1];var e=null;if(null==b)e=(0,_RSASIGN_HASHBYTEFUNC[d])(a);else{a=hex_sha256_from_bytes(a);d=b.path.index;for(e=b.path.digestList.length-
-1;0<=e;e--){var f="",f=0==d%2?a+b.path.digestList[e]:b.path.digestList[e]+a;a=hex_sha256_from_bytes(DataUtils.toNumbers(f));d=Math.floor(d/2)}e=hex_sha256_from_bytes(DataUtils.toNumbers(a))}return c==e}RSAKey.prototype.signString=_rsasign_signString;RSAKey.prototype.signByteArray=_rsasign_signByteArray;RSAKey.prototype.signByteArrayWithSHA256=_rsasign_signByteArrayWithSHA256;RSAKey.prototype.signStringWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signStringWithSHA256=_rsasign_signStringWithSHA256;
-RSAKey.prototype.sign=_rsasign_signString;RSAKey.prototype.signWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signWithSHA256=_rsasign_signStringWithSHA256;RSAKey.prototype.verifyByteArray=_rsasign_verifyByteArray;RSAKey.prototype.verifyString=_rsasign_verifyString;RSAKey.prototype.verifyHexSignatureForMessage=_rsasign_verifyHexSignatureForMessage;RSAKey.prototype.verify=_rsasign_verifyString;RSAKey.prototype.verifyHexSignatureForByteArrayMessage=_rsasign_verifyHexSignatureForMessage;
-function _asnhex_getByteLengthOfL_AtObj(a,b){if("8"!=a.substring(b+2,b+3))return 1;var c=parseInt(a.substring(b+3,b+4));return 0==c?-1:0<c&&10>c?c+1:-2}function _asnhex_getHexOfL_AtObj(a,b){var c=_asnhex_getByteLengthOfL_AtObj(a,b);return 1>c?"":a.substring(b+2,b+2+2*c)}function _asnhex_getIntOfL_AtObj(a,b){var c=_asnhex_getHexOfL_AtObj(a,b);return""==c?-1:(8>parseInt(c.substring(0,1))?parseBigInt(c,16):parseBigInt(c.substring(2),16)).intValue()}
-function _asnhex_getStartPosOfV_AtObj(a,b){var c=_asnhex_getByteLengthOfL_AtObj(a,b);return 0>c?c:b+2*(c+1)}function _asnhex_getHexOfV_AtObj(a,b){var c=_asnhex_getStartPosOfV_AtObj(a,b),d=_asnhex_getIntOfL_AtObj(a,b);return a.substring(c,c+2*d)}function _asnhex_getHexOfTLV_AtObj(a,b){var c=a.substr(b,2),d=_asnhex_getHexOfL_AtObj(a,b),e=_asnhex_getHexOfV_AtObj(a,b);return c+d+e}
-function _asnhex_getPosOfNextSibling_AtObj(a,b){var c=_asnhex_getStartPosOfV_AtObj(a,b),d=_asnhex_getIntOfL_AtObj(a,b);return c+2*d}function _asnhex_getPosArrayOfChildren_AtObj(a,b){var c=[],d=_asnhex_getStartPosOfV_AtObj(a,b);c.push(d);for(var e=_asnhex_getIntOfL_AtObj(a,b),f=d,g=0;;){f=_asnhex_getPosOfNextSibling_AtObj(a,f);if(null==f||f-d>=2*e)break;if(200<=g)break;c.push(f);g++}return c}function _asnhex_getNthChildIndex_AtObj(a,b,c){return _asnhex_getPosArrayOfChildren_AtObj(a,b)[c]}
-function _asnhex_getDecendantIndexByNthList(a,b,c){if(0==c.length)return b;var d=c.shift();b=_asnhex_getPosArrayOfChildren_AtObj(a,b);return _asnhex_getDecendantIndexByNthList(a,b[d],c)}function _asnhex_getDecendantHexTLVByNthList(a,b,c){b=_asnhex_getDecendantIndexByNthList(a,b,c);return _asnhex_getHexOfTLV_AtObj(a,b)}function _asnhex_getDecendantHexVByNthList(a,b,c){b=_asnhex_getDecendantIndexByNthList(a,b,c);return _asnhex_getHexOfV_AtObj(a,b)}function ASN1HEX(){return ASN1HEX}
-ASN1HEX.getByteLengthOfL_AtObj=_asnhex_getByteLengthOfL_AtObj;ASN1HEX.getHexOfL_AtObj=_asnhex_getHexOfL_AtObj;ASN1HEX.getIntOfL_AtObj=_asnhex_getIntOfL_AtObj;ASN1HEX.getStartPosOfV_AtObj=_asnhex_getStartPosOfV_AtObj;ASN1HEX.getHexOfV_AtObj=_asnhex_getHexOfV_AtObj;ASN1HEX.getHexOfTLV_AtObj=_asnhex_getHexOfTLV_AtObj;ASN1HEX.getPosOfNextSibling_AtObj=_asnhex_getPosOfNextSibling_AtObj;ASN1HEX.getPosArrayOfChildren_AtObj=_asnhex_getPosArrayOfChildren_AtObj;ASN1HEX.getNthChildIndex_AtObj=_asnhex_getNthChildIndex_AtObj;
-ASN1HEX.getDecendantIndexByNthList=_asnhex_getDecendantIndexByNthList;ASN1HEX.getDecendantHexVByNthList=_asnhex_getDecendantHexVByNthList;ASN1HEX.getDecendantHexTLVByNthList=_asnhex_getDecendantHexTLVByNthList;function _x509_pemToBase64(a){a=a.replace("-----BEGIN CERTIFICATE-----","");a=a.replace("-----END CERTIFICATE-----","");return a=a.replace(/[ \n]+/g,"")}function _x509_pemToHex(a){a=_x509_pemToBase64(a);return b64tohex(a)}
-function _x509_getHexTbsCertificateFromCert(a){return ASN1HEX.getStartPosOfV_AtObj(a,0)}function _x509_getSubjectPublicKeyInfoPosFromCertHex(a){var b=ASN1HEX.getStartPosOfV_AtObj(a,0),b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);return 1>b.length?-1:"a003020102"==a.substring(b[0],b[0]+10)?6>b.length?-1:b[6]:5>b.length?-1:b[5]}
-function _x509_getSubjectPublicKeyPosFromCertHex(a,b){null==b&&(b=_x509_getSubjectPublicKeyInfoPosFromCertHex(a));if(-1==b)return-1;var c=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);if(2!=c.length)return-1;c=c[1];if("03"!=a.substring(c,c+2))return-1;c=ASN1HEX.getStartPosOfV_AtObj(a,c);return"00"!=a.substring(c,c+2)?-1:c+2}
-function _x509_getPublicKeyHexArrayFromCertHex(a,b){null==b&&(b=_x509_getSubjectPublicKeyPosFromCertHex(a));var c=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);4<LOG&&(console.log("a is now"),console.log(c));if(2>c.length)return[];var d=ASN1HEX.getHexOfV_AtObj(a,c[0]),c=ASN1HEX.getHexOfV_AtObj(a,c[1]);return null!=d&&null!=c?[d,c]:[]}function _x509_getPublicKeyHexArrayFromCertPEM(a){a=_x509_pemToHex(a);return _x509_getPublicKeyHexArrayFromCertHex(a)}
-function _x509_getSerialNumberHex(){return ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,1])}function _x509_getIssuerHex(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3])}function _x509_getIssuerString(){return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3]))}function _x509_getSubjectHex(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5])}function _x509_getSubjectString(){return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5]))}
-function _x509_getNotBefore(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,0]),a=a.replace(/(..)/g,"%$1");return a=decodeURIComponent(a)}function _x509_getNotAfter(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,1]),a=a.replace(/(..)/g,"%$1");return a=decodeURIComponent(a)}_x509_DN_ATTRHEX={"0603550406":"C","060355040a":"O","060355040b":"OU","0603550403":"CN","0603550405":"SN","0603550408":"ST","0603550407":"L"};
-function _x509_hex2dn(a){for(var b="",c=ASN1HEX.getPosArrayOfChildren_AtObj(a,0),d=0;d<c.length;d++)var e=ASN1HEX.getHexOfTLV_AtObj(a,c[d]),b=b+"/"+_x509_hex2rdn(e);return b}function _x509_hex2rdn(a){var b=ASN1HEX.getDecendantHexTLVByNthList(a,0,[0,0]),c=ASN1HEX.getDecendantHexVByNthList(a,0,[0,1]);a="";try{a=_x509_DN_ATTRHEX[b]}catch(d){a=b}c=c.replace(/(..)/g,"%$1");b=decodeURIComponent(c);return a+"="+b}
-function _x509_readCertPEM(a){a=_x509_pemToHex(a);var b=_x509_getPublicKeyHexArrayFromCertHex(a);4<LOG&&(console.log("HEX VALUE IS "+a),console.log("type of a"+typeof b),console.log("a VALUE IS "),console.log(b),console.log("a[0] VALUE IS "+b[0]),console.log("a[1] VALUE IS "+b[1]));var c=new RSAKey;c.setPublic(b[0],b[1]);this.subjectPublicKeyRSA=c;this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a}
-function _x509_readCertHex(a){a=a.toLowerCase();var b=_x509_getPublicKeyHexArrayFromCertHex(a),c=new RSAKey;c.setPublic(b[0],b[1]);this.subjectPublicKeyRSA=c;this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a}function _x509_readCertPEMWithoutRSAInit(a){a=_x509_pemToHex(a);var b=_x509_getPublicKeyHexArrayFromCertHex(a);this.subjectPublicKeyRSA.setPublic(b[0],b[1]);this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a}
-function X509(){this.hex=this.subjectPublicKeyRSA_hE=this.subjectPublicKeyRSA_hN=this.subjectPublicKeyRSA=null}X509.prototype.readCertPEM=_x509_readCertPEM;X509.prototype.readCertHex=_x509_readCertHex;X509.prototype.readCertPEMWithoutRSAInit=_x509_readCertPEMWithoutRSAInit;X509.prototype.getSerialNumberHex=_x509_getSerialNumberHex;X509.prototype.getIssuerHex=_x509_getIssuerHex;X509.prototype.getSubjectHex=_x509_getSubjectHex;X509.prototype.getIssuerString=_x509_getIssuerString;
-X509.prototype.getSubjectString=_x509_getSubjectString;X509.prototype.getNotBefore=_x509_getNotBefore;X509.prototype.getNotAfter=_x509_getNotAfter;var dbits,canary=0xdeadbeefcafe,j_lm=15715070==(canary&16777215);function BigInteger(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}
-function am1(a,b,c,d,e,f){for(;0<=--f;){var g=b*this[a++]+c[d]+e;e=Math.floor(g/67108864);c[d++]=g&67108863}return e}function am2(a,b,c,d,e,f){var g=b&32767;for(b>>=15;0<=--f;){var h=this[a]&32767,j=this[a++]>>15,l=b*h+j*g,h=g*h+((l&32767)<<15)+c[d]+(e&1073741823);e=(h>>>30)+(l>>>15)+b*j+(e>>>30);c[d++]=h&1073741823}return e}
-function am3(a,b,c,d,e,f){var g=b&16383;for(b>>=14;0<=--f;){var h=this[a]&16383,j=this[a++]>>14,l=b*h+j*g,h=g*h+((l&16383)<<14)+c[d]+e;e=(h>>28)+(l>>14)+b*j;c[d++]=h&268435455}return e}j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28);BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;
+function oaep_mgf1_str(a,b,c){for(var d="",e=0;d.length<b;)d+=c(a+String.fromCharCode.apply(String,[(e&4278190080)>>24,(e&16711680)>>16,(e&65280)>>8,e&255])),e+=1;return d}SHA1_SIZE=20;
+function oaep_unpad(a,b,c){a=a.toByteArray();var d;for(d=0;d<a.length;d+=1)a[d]&=255;for(;a.length<b;)a.unshift(0);a=String.fromCharCode.apply(String,a);if(a.length<2*SHA1_SIZE+2)throw"Cipher too short";var e=a.substr(1,SHA1_SIZE);b=a.substr(SHA1_SIZE+1);c=oaep_mgf1_str(b,SHA1_SIZE,c||rstr_sha1);var f=[];for(d=0;d<e.length;d+=1)f[d]=e.charCodeAt(d)^c.charCodeAt(d);e=oaep_mgf1_str(String.fromCharCode.apply(String,f),a.length-SHA1_SIZE,rstr_sha1);a=[];for(d=0;d<b.length;d+=1)a[d]=b.charCodeAt(d)^e.charCodeAt(d);
+a=String.fromCharCode.apply(String,a);if(a.substr(0,SHA1_SIZE)!==rstr_sha1(""))throw"Hash mismatch";a=a.substr(SHA1_SIZE);d=a.indexOf("\u0001");if((-1!=d?a.substr(0,d).lastIndexOf("\x00"):-1)+1!=d)throw"Malformed data";return a.substr(d+1)}function RSASetPrivate(a,b,c){this.isPrivate=!0;"string"!==typeof a?(this.n=a,this.e=b,this.d=c):null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16)):alert("Invalid RSA private key")}
+function RSASetPrivateEx(a,b,c,d,e,f,g,h){this.isPrivate=!0;if(null==a)throw"RSASetPrivateEx N == null";if(null==b)throw"RSASetPrivateEx E == null";if(0==a.length)throw"RSASetPrivateEx N.length == 0";if(0==b.length)throw"RSASetPrivateEx E.length == 0";null!=a&&null!=b&&0<a.length&&0<b.length?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16),this.p=parseBigInt(d,16),this.q=parseBigInt(e,16),this.dmp1=parseBigInt(f,16),this.dmq1=parseBigInt(g,16),this.coeff=parseBigInt(h,16)):
+alert("Invalid RSA private key in RSASetPrivateEx")}
+function RSAGenerate(a,b){var c=new SecureRandom,d=a>>1;this.e=parseInt(b,16);for(var e=new BigInteger(b,16);;){for(;this.p=new BigInteger(a-d,1,c),0!=this.p.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)||!this.p.isProbablePrime(10););for(;this.q=new BigInteger(d,1,c),0!=this.q.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)||!this.q.isProbablePrime(10););if(0>=this.p.compareTo(this.q)){var f=this.p;this.p=this.q;this.q=f}var f=this.p.subtract(BigInteger.ONE),g=this.q.subtract(BigInteger.ONE),
+h=f.multiply(g);if(0==h.gcd(e).compareTo(BigInteger.ONE)){this.n=this.p.multiply(this.q);this.d=e.modInverse(h);this.dmp1=this.d.mod(f);this.dmq1=this.d.mod(g);this.coeff=this.q.modInverse(this.p);break}}this.isPrivate=!0}
+function RSADoPrivate(a){if(null==this.p||null==this.q)return a.modPow(this.d,this.n);var b=a.mod(this.p).modPow(this.dmp1,this.p);for(a=a.mod(this.q).modPow(this.dmq1,this.q);0>b.compareTo(a);)b=b.add(this.p);return b.subtract(a).multiply(this.coeff).mod(this.p).multiply(this.q).add(a)}function RSADecrypt(a){a=parseBigInt(a,16);a=this.doPrivate(a);return null==a?null:pkcs1unpad2(a,this.n.bitLength()+7>>3)}
+function RSADecryptOAEP(a,b){var c=parseBigInt(a,16),c=this.doPrivate(c);return null==c?null:oaep_unpad(c,this.n.bitLength()+7>>3,b)}RSAKey.prototype.doPrivate=RSADoPrivate;RSAKey.prototype.setPrivate=RSASetPrivate;RSAKey.prototype.setPrivateEx=RSASetPrivateEx;RSAKey.prototype.generate=RSAGenerate;RSAKey.prototype.decrypt=RSADecrypt;RSAKey.prototype.decryptOAEP=RSADecryptOAEP;exports.RSAKey=RSAKey;module.exports=exports;CryptoJS=require("./sha256.js").CryptoJS;intShim=require("jsbn");
+"undefined"!=typeof KJUR&&KJUR||(KJUR={});"undefined"!=typeof KJUR.crypto&&KJUR.crypto||(KJUR.crypto={});
+KJUR.crypto.Util=new function(){this.DIGESTINFOHEAD={sha1:"3021300906052b0e03021a05000414",sha224:"302d300d06096086480165030402040500041c",sha256:"3031300d060960864801650304020105000420",sha384:"3041300d060960864801650304020205000430",sha512:"3051300d060960864801650304020305000440",md2:"3020300c06082a864886f70d020205000410",md5:"3020300c06082a864886f70d020505000410",ripemd160:"3021300906052b2403020105000414"};this.DEFAULTPROVIDER={md5:"cryptojs",sha1:"cryptojs",sha224:"cryptojs",sha256:"cryptojs",
+sha384:"cryptojs",sha512:"cryptojs",ripemd160:"cryptojs",hmacmd5:"cryptojs",hmacsha1:"cryptojs",hmacsha224:"cryptojs",hmacsha256:"cryptojs",hmacsha384:"cryptojs",hmacsha512:"cryptojs",hmacripemd160:"cryptojs",MD5withRSA:"cryptojs/jsrsa",SHA1withRSA:"cryptojs/jsrsa",SHA224withRSA:"cryptojs/jsrsa",SHA256withRSA:"cryptojs/jsrsa",SHA384withRSA:"cryptojs/jsrsa",SHA512withRSA:"cryptojs/jsrsa",RIPEMD160withRSA:"cryptojs/jsrsa",MD5withECDSA:"cryptojs/jsrsa",SHA1withECDSA:"cryptojs/jsrsa",SHA224withECDSA:"cryptojs/jsrsa",
+SHA256withECDSA:"cryptojs/jsrsa",SHA384withECDSA:"cryptojs/jsrsa",SHA512withECDSA:"cryptojs/jsrsa",RIPEMD160withECDSA:"cryptojs/jsrsa",SHA1withDSA:"cryptojs/jsrsa",SHA224withDSA:"cryptojs/jsrsa",SHA256withDSA:"cryptojs/jsrsa",MD5withRSAandMGF1:"cryptojs/jsrsa",SHA1withRSAandMGF1:"cryptojs/jsrsa",SHA224withRSAandMGF1:"cryptojs/jsrsa",SHA256withRSAandMGF1:"cryptojs/jsrsa",SHA384withRSAandMGF1:"cryptojs/jsrsa",SHA512withRSAandMGF1:"cryptojs/jsrsa",RIPEMD160withRSAandMGF1:"cryptojs/jsrsa"};this.CRYPTOJSMESSAGEDIGESTNAME=
+{md5:"CryptoJS.algo.MD5",sha1:"CryptoJS.algo.SHA1",sha224:"CryptoJS.algo.SHA224",sha256:"CryptoJS.algo.SHA256",sha384:"CryptoJS.algo.SHA384",sha512:"CryptoJS.algo.SHA512",ripemd160:"CryptoJS.algo.RIPEMD160"};this.getDigestInfoHex=function(a,b){if("undefined"==typeof this.DIGESTINFOHEAD[b])throw"alg not supported in Util.DIGESTINFOHEAD: "+b;return this.DIGESTINFOHEAD[b]+a};this.getPaddedDigestInfoHex=function(a,b,c){var d=this.getDigestInfoHex(a,b);a=c/4;if(d.length+22>a)throw"key is too short for SigAlg: keylen="+
+c+","+b;b="00"+d;c="";a=a-4-b.length;for(d=0;d<a;d+=2)c+="ff";return"0001"+c+b};this.hashString=function(a,b){return(new KJUR.crypto.MessageDigest({alg:b})).digestString(a)};this.hashHex=function(a,b){return(new KJUR.crypto.MessageDigest({alg:b})).digestHex(a)};this.sha1=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha1",prov:"cryptojs"})).digestString(a)};this.sha256=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha256",prov:"cryptojs"})).digestString(a)};this.sha256Hex=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha256",
+prov:"cryptojs"})).digestHex(a)};this.sha512=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha512",prov:"cryptojs"})).digestString(a)};this.sha512Hex=function(a){return(new KJUR.crypto.MessageDigest({alg:"sha512",prov:"cryptojs"})).digestHex(a)};this.md5=function(a){return(new KJUR.crypto.MessageDigest({alg:"md5",prov:"cryptojs"})).digestString(a)};this.ripemd160=function(a){return(new KJUR.crypto.MessageDigest({alg:"ripemd160",prov:"cryptojs"})).digestString(a)};this.getCryptoJSMDByName=
+function(a){}};
+KJUR.crypto.MessageDigest=function(a){this.setAlgAndProvider=function(a,c){null!=a&&void 0===c&&(c=KJUR.crypto.Util.DEFAULTPROVIDER[a]);if(-1!=":md5:sha1:sha224:sha256:sha384:sha512:ripemd160:".indexOf(a)&&"cryptojs"==c){try{this.md=eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[a]).create()}catch(d){throw"setAlgAndProvider hash alg set fail alg="+a+"/"+d;}this.updateString=function(a){this.md.update(a)};this.updateHex=function(a){a=CryptoJS.enc.Hex.parse(a);this.md.update(a)};this.digest=function(){return this.md.finalize().toString(CryptoJS.enc.Hex)};
+this.digestString=function(a){this.updateString(a);return this.digest()};this.digestHex=function(a){this.updateHex(a);return this.digest()}}if(-1!=":sha256:".indexOf(a)&&"sjcl"==c){try{this.md=new sjcl.hash.sha256}catch(e){throw"setAlgAndProvider hash alg set fail alg="+a+"/"+e;}this.updateString=function(a){this.md.update(a)};this.updateHex=function(a){a=sjcl.codec.hex.toBits(a);this.md.update(a)};this.digest=function(){var a=this.md.finalize();return sjcl.codec.hex.fromBits(a)};this.digestString=
+function(a){this.updateString(a);return this.digest()};this.digestHex=function(a){this.updateHex(a);return this.digest()}}};this.updateString=function(a){throw"updateString(str) not supported for this alg/prov: "+this.algName+"/"+this.provName;};this.updateHex=function(a){throw"updateHex(hex) not supported for this alg/prov: "+this.algName+"/"+this.provName;};this.digest=function(){throw"digest() not supported for this alg/prov: "+this.algName+"/"+this.provName;};this.digestString=function(a){throw"digestString(str) not supported for this alg/prov: "+
+this.algName+"/"+this.provName;};this.digestHex=function(a){throw"digestHex(hex) not supported for this alg/prov: "+this.algName+"/"+this.provName;};void 0!==a&&void 0!==a.alg&&(this.algName=a.alg,void 0===a.prov&&(this.provName=KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]),this.setAlgAndProvider(this.algName,this.provName))};
+KJUR.crypto.Mac=function(a){this.setAlgAndProvider=function(a,c){a=a.toLowerCase();null==a&&(a="hmacsha1");a=a.toLowerCase();if("hmac"!=a.substr(0,4))throw"setAlgAndProvider unsupported HMAC alg: "+a;void 0===c&&(c=KJUR.crypto.Util.DEFAULTPROVIDER[a]);this.algProv=a+"/"+c;var d=a.substr(4);if(-1!=":md5:sha1:sha224:sha256:sha384:sha512:ripemd160:".indexOf(d)&&"cryptojs"==c){try{var e=eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[d]);this.mac=CryptoJS.algo.HMAC.create(e,this.pass)}catch(f){throw"setAlgAndProvider hash alg set fail hashAlg="+
+d+"/"+f;}this.updateString=function(a){this.mac.update(a)};this.updateHex=function(a){a=CryptoJS.enc.Hex.parse(a);this.mac.update(a)};this.doFinal=function(){return this.mac.finalize().toString(CryptoJS.enc.Hex)};this.doFinalString=function(a){this.updateString(a);return this.doFinal()};this.doFinalHex=function(a){this.updateHex(a);return this.doFinal()}}};this.updateString=function(a){throw"updateString(str) not supported for this alg/prov: "+this.algProv;};this.updateHex=function(a){throw"updateHex(hex) not supported for this alg/prov: "+
+this.algProv;};this.doFinal=function(){throw"digest() not supported for this alg/prov: "+this.algProv;};this.doFinalString=function(a){throw"digestString(str) not supported for this alg/prov: "+this.algProv;};this.doFinalHex=function(a){throw"digestHex(hex) not supported for this alg/prov: "+this.algProv;};this.setPassword=function(a){if("string"==typeof a){var c=a;1!=a.length%2&&a.match(/^[0-9A-Fa-f]+$/)||(c=rstrtohex(a))}else{if("object"!=typeof a)throw"KJUR.crypto.Mac unsupported password type: "+
+a;c=null;if(void 0!==a.hex){if(0!=a.hex.length%2||!a.hex.match(/^[0-9A-Fa-f]+$/))throw"Mac: wrong hex password: "+a.hex;c=a.hex}void 0!==a.utf8&&(c=utf8tohex(a.utf8));void 0!==a.rstr&&(c=rstrtohex(a.rstr));void 0!==a.b64&&(c=b64tohex(a.b64));void 0!==a.b64u&&(c=b64utohex(a.b64u));if(null==c)throw"KJUR.crypto.Mac unsupported password type: "+a;}this.pass=CryptoJS.enc.Hex.parse(c)};void 0!==a&&(void 0!==a.pass&&this.setPassword(a.pass),void 0!==a.alg&&(this.algName=a.alg,void 0===a.prov&&(this.provName=
+KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]),this.setAlgAndProvider(this.algName,this.provName)))};
+KJUR.crypto.Signature=function(a){var b=null;this._setAlgNames=function(){this.algName.match(/^(.+)with(.+)$/)&&(this.mdAlgName=RegExp.$1.toLowerCase(),this.pubkeyAlgName=RegExp.$2.toLowerCase())};this._zeroPaddingOfSignature=function(a,b){for(var c="",g=b/4-a.length,h=0;h<g;h++)c+="0";return c+a};this.setAlgAndProvider=function(a,b){this._setAlgNames();if("cryptojs/jsrsa"!=b)throw"provider not supported: "+b;if(-1!=":md5:sha1:sha224:sha256:sha384:sha512:ripemd160:".indexOf(this.mdAlgName)){try{this.md=
+new KJUR.crypto.MessageDigest({alg:this.mdAlgName})}catch(c){throw"setAlgAndProvider hash alg set fail alg="+this.mdAlgName+"/"+c;}this.init=function(a,b){var c=null;try{c=void 0===b?KEYUTIL.getKey(a):KEYUTIL.getKey(a,b)}catch(d){throw"init failed:"+d;}if(!0===c.isPrivate)this.prvKey=c,this.state="SIGN";else if(!0===c.isPublic)this.pubKey=c,this.state="VERIFY";else throw"init failed.:"+c;};this.initSign=function(a){"string"==typeof a.ecprvhex&&"string"==typeof a.eccurvename?(this.ecprvhex=a.ecprvhex,
+this.eccurvename=a.eccurvename):this.prvKey=a;this.state="SIGN"};this.initVerifyByPublicKey=function(a){"string"==typeof a.ecpubhex&&"string"==typeof a.eccurvename?(this.ecpubhex=a.ecpubhex,this.eccurvename=a.eccurvename):a instanceof KJUR.crypto.ECDSA?this.pubKey=a:a instanceof RSAKey&&(this.pubKey=a);this.state="VERIFY"};this.initVerifyByCertificatePEM=function(a){var b=new X509;b.readCertPEM(a);this.pubKey=b.subjectPublicKeyRSA;this.state="VERIFY"};this.updateString=function(a){this.md.updateString(a)};
+this.updateHex=function(a){this.md.updateHex(a)};this.sign=function(){this.sHashHex=this.md.digest();if("undefined"!=typeof this.ecprvhex&&"undefined"!=typeof this.eccurvename)this.hSign=(new KJUR.crypto.ECDSA({curve:this.eccurvename})).signHex(this.sHashHex,this.ecprvhex);else if(this.prvKey instanceof RSAKey&&"rsaandmgf1"==this.pubkeyAlgName)this.hSign=this.prvKey.signWithMessageHashPSS(this.sHashHex,this.mdAlgName,this.pssSaltLen);else if(this.prvKey instanceof RSAKey&&"rsa"==this.pubkeyAlgName)this.hSign=
+this.prvKey.signWithMessageHash(this.sHashHex,this.mdAlgName);else if(this.prvKey instanceof KJUR.crypto.ECDSA)this.hSign=this.prvKey.signWithMessageHash(this.sHashHex);else if(this.prvKey instanceof KJUR.crypto.DSA)this.hSign=this.prvKey.signWithMessageHash(this.sHashHex);else throw"Signature: unsupported public key alg: "+this.pubkeyAlgName;return this.hSign};this.signString=function(a){this.updateString(a);return this.sign()};this.signHex=function(a){this.updateHex(a);return this.sign()};this.verify=
+function(a){this.sHashHex=this.md.digest();if("undefined"!=typeof this.ecpubhex&&"undefined"!=typeof this.eccurvename)return(new KJUR.crypto.ECDSA({curve:this.eccurvename})).verifyHex(this.sHashHex,a,this.ecpubhex);if(this.pubKey instanceof RSAKey&&"rsaandmgf1"==this.pubkeyAlgName)return this.pubKey.verifyWithMessageHashPSS(this.sHashHex,a,this.mdAlgName,this.pssSaltLen);if(this.pubKey instanceof RSAKey&&"rsa"==this.pubkeyAlgName||this.pubKey instanceof KJUR.crypto.ECDSA||this.pubKey instanceof KJUR.crypto.DSA)return this.pubKey.verifyWithMessageHash(this.sHashHex,
+a);throw"Signature: unsupported public key alg: "+this.pubkeyAlgName;}}};this.init=function(a,b){throw"init(key, pass) not supported for this alg:prov="+this.algProvName;};this.initVerifyByPublicKey=function(a){throw"initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov="+this.algProvName;};this.initVerifyByCertificatePEM=function(a){throw"initVerifyByCertificatePEM(certPEM) not supported for this alg:prov="+this.algProvName;};this.initSign=function(a){throw"initSign(prvKey) not supported for this alg:prov="+
+this.algProvName;};this.updateString=function(a){throw"updateString(str) not supported for this alg:prov="+this.algProvName;};this.updateHex=function(a){throw"updateHex(hex) not supported for this alg:prov="+this.algProvName;};this.sign=function(){throw"sign() not supported for this alg:prov="+this.algProvName;};this.signString=function(a){throw"digestString(str) not supported for this alg:prov="+this.algProvName;};this.signHex=function(a){throw"digestHex(hex) not supported for this alg:prov="+this.algProvName;
+};this.verify=function(a){throw"verify(hSigVal) not supported for this alg:prov="+this.algProvName;};this.initParams=a;if(void 0!==a&&(void 0!==a.alg&&(this.algName=a.alg,this.provName=void 0===a.prov?KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]:a.prov,this.algProvName=this.algName+":"+this.provName,this.setAlgAndProvider(this.algName,this.provName),this._setAlgNames()),void 0!==a.psssaltlen&&(this.pssSaltLen=a.psssaltlen),void 0!==a.prvkeypem)){if(void 0!==a.prvkeypas)throw"both prvkeypem and prvkeypas parameters not supported";
+try{b=new RSAKey,b.readPrivateKeyFromPEMString(a.prvkeypem),this.initSign(b)}catch(c){throw"fatal error to load pem private key: "+c;}}};
+KJUR.crypto.OID=new function(){this.oidhex2name={"2a864886f70d010101":"rsaEncryption","2a8648ce3d0201":"ecPublicKey","2a8648ce380401":"dsa","2a8648ce3d030107":"secp256r1","2b8104001f":"secp192k1","2b81040021":"secp224r1","2b8104000a":"secp256k1","2b81040023":"secp521r1","2b81040022":"secp384r1","2a8648ce380403":"SHA1withDSA","608648016503040301":"SHA224withDSA","608648016503040302":"SHA256withDSA"}};exports.KJUR=KJUR;module.exports=exports;
+var ASN1HEX=require("./asn1hex-1.1.js").ASN1HEX,b64tohex=require("./base64.js").b64tohex,RSAKey=require("./rsa2.js").RSAKey;function _rsapem_pemToBase64(a){a=a.replace("-----BEGIN RSA PRIVATE KEY-----","");a=a.replace("-----END RSA PRIVATE KEY-----","");return a=a.replace(/[ \n]+/g,"")}
+function _rsapem_getPosArrayOfChildrenFromHex(a){var b=[],c=ASN1HEX.getStartPosOfV_AtObj(a,0),d=ASN1HEX.getPosOfNextSibling_AtObj(a,c),e=ASN1HEX.getPosOfNextSibling_AtObj(a,d),f=ASN1HEX.getPosOfNextSibling_AtObj(a,e),g=ASN1HEX.getPosOfNextSibling_AtObj(a,f),h=ASN1HEX.getPosOfNextSibling_AtObj(a,g),k=ASN1HEX.getPosOfNextSibling_AtObj(a,h),l=ASN1HEX.getPosOfNextSibling_AtObj(a,k);a=ASN1HEX.getPosOfNextSibling_AtObj(a,l);b.push(c,d,e,f,g,h,k,l,a);return b}
+function _rsapem_getHexValueArrayOfChildrenFromHex(a){var b=_rsapem_getPosArrayOfChildrenFromHex(a),c=ASN1HEX.getHexOfV_AtObj(a,b[0]),d=ASN1HEX.getHexOfV_AtObj(a,b[1]),e=ASN1HEX.getHexOfV_AtObj(a,b[2]),f=ASN1HEX.getHexOfV_AtObj(a,b[3]),g=ASN1HEX.getHexOfV_AtObj(a,b[4]),h=ASN1HEX.getHexOfV_AtObj(a,b[5]),k=ASN1HEX.getHexOfV_AtObj(a,b[6]),l=ASN1HEX.getHexOfV_AtObj(a,b[7]);a=ASN1HEX.getHexOfV_AtObj(a,b[8]);b=[];b.push(c,d,e,f,g,h,k,l,a);return b}
+function _rsapem_readPrivateKeyFromASN1HexString(a){a=_rsapem_getHexValueArrayOfChildrenFromHex(a);this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])}function _rsapem_readPrivateKeyFromPEMString(a){a=_rsapem_pemToBase64(a);a=b64tohex(a);a=_rsapem_getHexValueArrayOfChildrenFromHex(a);this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])}RSAKey.prototype.readPrivateKeyFromPEMString=_rsapem_readPrivateKeyFromPEMString;RSAKey.prototype.readPrivateKeyFromASN1HexString=_rsapem_readPrivateKeyFromASN1HexString;
+exports.RSAKey=RSAKey;module.exports=exports;var intShim=require("jsbn"),BigInteger=intShim.BigInteger?intShim.BigInteger:intShim,RSAKey=require("./rsapem-1.1.js").RSAKey,_RE_HEXDECONLY=RegExp("");_RE_HEXDECONLY.compile("[^0-9a-f]","gi");function _rsasign_getHexPaddedDigestInfoForString(a,b,c){a=KJUR.crypto.Util.hashString(a,c);return KJUR.crypto.Util.getPaddedDigestInfoHex(a,c,b)}function _zeroPaddingOfSignature(a,b){for(var c="",d=b/4-a.length,e=0;e<d;e++)c+="0";return c+a}
+function _rsasign_signString(a,b){var c=KJUR.crypto.Util.hashString(a,b);return this.signWithMessageHash(c,b)}function _rsasign_signWithMessageHash(a,b){var c=KJUR.crypto.Util.getPaddedDigestInfoHex(a,b,this.n.bitLength()),c=parseBigInt(c,16),c=this.doPrivate(c).toString(16);return _zeroPaddingOfSignature(c,this.n.bitLength())}function _rsasign_signStringWithSHA1(a){return _rsasign_signString.call(this,a,"sha1")}
+function _rsasign_signStringWithSHA256(a){return _rsasign_signString.call(this,a,"sha256")}function pss_mgf1_str(a,b,c){for(var d="",e=0;d.length<b;)d+=hextorstr(c(rstrtohex(a+String.fromCharCode.apply(String,[(e&4278190080)>>24,(e&16711680)>>16,(e&65280)>>8,e&255])))),e+=1;return d}function _rsasign_signStringPSS(a,b,c){a=rstrtohex(a);a=KJUR.crypto.Util.hashHex(a,b);void 0===c&&(c=-1);return this.signWithMessageHashPSS(a,b,c)}
+function _rsasign_signWithMessageHashPSS(a,b,c){var d=hextorstr(a);a=d.length;var e=this.n.bitLength()-1,f=Math.ceil(e/8),g=function(a){return KJUR.crypto.Util.hashHex(a,b)};if(-1===c||void 0===c)c=a;else if(-2===c)c=f-a-2;else if(-2>c)throw"invalid salt length";if(f<a+c+2)throw"data too long";var h="";0<c&&(h=Array(c),(new SecureRandom).nextBytes(h),h=String.fromCharCode.apply(String,h));for(var k=hextorstr(g(rstrtohex("\x00\x00\x00\x00\x00\x00\x00\x00"+d+h))),l=[],d=0;d<f-c-a-2;d+=1)l[d]=0;c=String.fromCharCode.apply(String,
+l)+"\u0001"+h;g=pss_mgf1_str(k,c.length,g);h=[];for(d=0;d<c.length;d+=1)h[d]=c.charCodeAt(d)^g.charCodeAt(d);h[0]&=~(65280>>8*f-e&255);for(d=0;d<a;d++)h.push(k.charCodeAt(d));h.push(188);return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(h)).toString(16),this.n.bitLength())}function _rsasign_getDecryptSignatureBI(a,b,c){var d=new RSAKey;d.setPublic(b,c);return d.doPublic(a)}
+function _rsasign_getHexDigestInfoFromSig(a,b,c){return _rsasign_getDecryptSignatureBI(a,b,c).toString(16).replace(/^1f+00/,"")}function _rsasign_getAlgNameAndHashFromHexDisgestInfo(a){for(var b in KJUR.crypto.Util.DIGESTINFOHEAD){var c=KJUR.crypto.Util.DIGESTINFOHEAD[b],d=c.length;if(a.substring(0,d)==c)return[b,a.substring(d)]}return[]}
+function _rsasign_verifySignatureWithArgs(a,b,c,d){b=_rsasign_getHexDigestInfoFromSig(b,c,d);c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(b);if(0==c.length)return!1;b=c[1];a=KJUR.crypto.Util.hashString(a,c[0]);return b==a}function _rsasign_verifyHexSignatureForMessage(a,b){var c=parseBigInt(a,16);return _rsasign_verifySignatureWithArgs(b,c,this.n.toString(16),this.e.toString(16))}
+function _rsasign_verifyString(a,b){b=b.replace(_RE_HEXDECONLY,"");b=b.replace(/[ \n]+/g,"");var c=parseBigInt(b,16);if(c.bitLength()>this.n.bitLength())return 0;var c=this.doPublic(c).toString(16).replace(/^1f+00/,""),d=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);if(0==d.length)return!1;c=d[1];d=KJUR.crypto.Util.hashString(a,d[0]);return c==d}
+function _rsasign_verifyWithMessageHash(a,b){b=b.replace(_RE_HEXDECONLY,"");b=b.replace(/[ \n]+/g,"");var c=parseBigInt(b,16);if(c.bitLength()>this.n.bitLength())return 0;c=this.doPublic(c).toString(16).replace(/^1f+00/,"");c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);return 0==c.length?!1:c[1]==a}function _rsasign_verifyStringPSS(a,b,c,d){a=rstrtohex(a);a=KJUR.crypto.Util.hashHex(a,c);void 0===d&&(d=-1);return this.verifyWithMessageHashPSS(a,b,c,d)}
+function _rsasign_verifyWithMessageHashPSS(a,b,c,d){var e=new BigInteger(b,16);if(e.bitLength()>this.n.bitLength())return!1;b=function(a){return KJUR.crypto.Util.hashHex(a,c)};a=hextorstr(a);var f=a.length,g=this.n.bitLength()-1,h=Math.ceil(g/8);if(-1===d||void 0===d)d=f;else if(-2===d)d=h-f-2;else if(-2>d)throw"invalid salt length";if(h<f+d+2)throw"data too long";for(var k=this.doPublic(e).toByteArray(),e=0;e<k.length;e+=1)k[e]&=255;for(;k.length<h;)k.unshift(0);if(188!==k[h-1])throw"encoded message does not end in 0xbc";
+var k=String.fromCharCode.apply(String,k),l=k.substr(0,h-f-1),k=k.substr(l.length,f),m=65280>>8*h-g&255;if(0!==(l.charCodeAt(0)&m))throw"bits beyond keysize not zero";for(var q=pss_mgf1_str(k,l.length,b),g=[],e=0;e<l.length;e+=1)g[e]=l.charCodeAt(e)^q.charCodeAt(e);g[0]&=~m;f=h-f-d-2;for(e=0;e<f;e+=1)if(0!==g[e])throw"leftmost octets not zero";if(1!==g[f])throw"0x01 marker not found";return k===hextorstr(b(rstrtohex("\x00\x00\x00\x00\x00\x00\x00\x00"+a+String.fromCharCode.apply(String,g.slice(-d)))))}
+RSAKey.prototype.signWithMessageHash=_rsasign_signWithMessageHash;RSAKey.prototype.signString=_rsasign_signString;RSAKey.prototype.signStringWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signStringWithSHA256=_rsasign_signStringWithSHA256;RSAKey.prototype.sign=_rsasign_signString;RSAKey.prototype.signWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signWithSHA256=_rsasign_signStringWithSHA256;RSAKey.prototype.signWithMessageHashPSS=_rsasign_signWithMessageHashPSS;
+RSAKey.prototype.signStringPSS=_rsasign_signStringPSS;RSAKey.prototype.signPSS=_rsasign_signStringPSS;RSAKey.SALT_LEN_HLEN=-1;RSAKey.SALT_LEN_MAX=-2;RSAKey.prototype.verifyWithMessageHash=_rsasign_verifyWithMessageHash;RSAKey.prototype.verifyString=_rsasign_verifyString;RSAKey.prototype.verifyHexSignatureForMessage=_rsasign_verifyHexSignatureForMessage;RSAKey.prototype.verify=_rsasign_verifyString;RSAKey.prototype.verifyHexSignatureForByteArrayMessage=_rsasign_verifyHexSignatureForMessage;
+RSAKey.prototype.verifyWithMessageHashPSS=_rsasign_verifyWithMessageHashPSS;RSAKey.prototype.verifyStringPSS=_rsasign_verifyStringPSS;RSAKey.prototype.verifyPSS=_rsasign_verifyStringPSS;RSAKey.SALT_LEN_RECOVER=-2;exports.RSAKey=RSAKey;module.exports=exports;"undefined"!=typeof KJUR&&KJUR||(KJUR={});"undefined"!=typeof KJUR.crypto&&KJUR.crypto||(KJUR.crypto={});
+KJUR.crypto.ECDSA=function(a){var b=new SecureRandom;this.type="EC";this.getBigRandom=function(a){return(new BigInteger(a.bitLength(),b)).mod(a.subtract(BigInteger.ONE)).add(BigInteger.ONE)};this.setNamedCurve=function(a){this.ecparams=KJUR.crypto.ECParameterDB.getByName(a);this.pubKeyHex=this.prvKeyHex=null;this.curveName=a};this.setPrivateKeyHex=function(a){this.isPrivate=!0;this.prvKeyHex=a};this.setPublicKeyHex=function(a){this.isPublic=!0;this.pubKeyHex=a};this.generateKeyPairHex=function(){var a=
+this.getBigRandom(this.ecparams.n),b=this.ecparams.G.multiply(a),e=b.getX().toBigInteger(),b=b.getY().toBigInteger(),f=this.ecparams.keylen/4,a=("0000000000"+a.toString(16)).slice(-f),e=("0000000000"+e.toString(16)).slice(-f),b=("0000000000"+b.toString(16)).slice(-f),e="04"+e+b;this.setPrivateKeyHex(a);this.setPublicKeyHex(e);return{ecprvhex:a,ecpubhex:e}};this.signWithMessageHash=function(a){return this.signHex(a,this.prvKeyHex)};this.signHex=function(a,b){var e=new BigInteger(b,16),f=this.ecparams.n,
+g=new BigInteger(a,16);do var h=this.getBigRandom(f),k=this.ecparams.G.multiply(h).getX().toBigInteger().mod(f);while(0>=k.compareTo(BigInteger.ZERO));e=h.modInverse(f).multiply(g.add(e.multiply(k))).mod(f);return KJUR.crypto.ECDSA.biRSSigToASN1Sig(k,e)};this.sign=function(a,b){var e=this.ecparams.n,f=BigInteger.fromByteArrayUnsigned(a);do var g=this.getBigRandom(e),h=this.ecparams.G.multiply(g).getX().toBigInteger().mod(e);while(0>=h.compareTo(BigInteger.ZERO));e=g.modInverse(e).multiply(f.add(b.multiply(h))).mod(e);
+return this.serializeSig(h,e)};this.verifyWithMessageHash=function(a,b){return this.verifyHex(a,b,this.pubKeyHex)};this.verifyHex=function(a,b,e){var f;f=KJUR.crypto.ECDSA.parseSigHex(b);b=f.r;f=f.s;e=ECPointFp.decodeFromHex(this.ecparams.curve,e);a=new BigInteger(a,16);return this.verifyRaw(a,b,f,e)};this.verify=function(a,b,e){var f;if(Bitcoin.Util.isArray(b))b=this.parseSig(b),f=b.r,b=b.s;else if("object"===typeof b&&b.r&&b.s)f=b.r,b=b.s;else throw"Invalid value for signature";if(!(e instanceof
+ECPointFp))if(Bitcoin.Util.isArray(e))e=ECPointFp.decodeFrom(this.ecparams.curve,e);else throw"Invalid format for pubkey value, must be byte array or ECPointFp";a=BigInteger.fromByteArrayUnsigned(a);return this.verifyRaw(a,f,b,e)};this.verifyRaw=function(a,b,e,f){var g=this.ecparams.n,h=this.ecparams.G;if(0>b.compareTo(BigInteger.ONE)||0<=b.compareTo(g)||0>e.compareTo(BigInteger.ONE)||0<=e.compareTo(g))return!1;e=e.modInverse(g);a=a.multiply(e).mod(g);e=b.multiply(e).mod(g);return h.multiply(a).add(f.multiply(e)).getX().toBigInteger().mod(g).equals(b)};
+this.serializeSig=function(a,b){var e=a.toByteArraySigned(),f=b.toByteArraySigned(),g=[];g.push(2);g.push(e.length);g=g.concat(e);g.push(2);g.push(f.length);g=g.concat(f);g.unshift(g.length);g.unshift(48);return g};this.parseSig=function(a){var b;if(48!=a[0])throw Error("Signature not a valid DERSequence");b=2;if(2!=a[b])throw Error("First element in signature must be a DERInteger");var e=a.slice(b+2,b+2+a[b+1]);b+=2+a[b+1];if(2!=a[b])throw Error("Second element in signature must be a DERInteger");
+a=a.slice(b+2,b+2+a[b+1]);e=BigInteger.fromByteArrayUnsigned(e);a=BigInteger.fromByteArrayUnsigned(a);return{r:e,s:a}};this.parseSigCompact=function(a){if(65!==a.length)throw"Signature has the wrong length";var b=a[0]-27;if(0>b||7<b)throw"Invalid signature type";var e=this.ecparams.n,f=BigInteger.fromByteArrayUnsigned(a.slice(1,33)).mod(e);a=BigInteger.fromByteArrayUnsigned(a.slice(33,65)).mod(e);return{r:f,s:a,i:b}};void 0!==a&&void 0!==a.curve&&(this.curveName=a.curve);void 0===this.curveName&&
+(this.curveName="secp256r1");this.setNamedCurve(this.curveName);void 0!==a&&(void 0!==a.prv&&this.setPrivateKeyHex(a.prv),void 0!==a.pub&&this.setPublicKeyHex(a.pub))};KJUR.crypto.ECDSA.parseSigHex=function(a){var b=KJUR.crypto.ECDSA.parseSigHexInHexRS(a);a=new BigInteger(b.r,16);b=new BigInteger(b.s,16);return{r:a,s:b}};
+KJUR.crypto.ECDSA.parseSigHexInHexRS=function(a){if("30"!=a.substr(0,2))throw"signature is not a ASN.1 sequence";var b=ASN1HEX.getPosArrayOfChildren_AtObj(a,0);if(2!=b.length)throw"number of signature ASN.1 sequence elements seem wrong";var c=b[0],b=b[1];if("02"!=a.substr(c,2))throw"1st item of sequene of signature is not ASN.1 integer";if("02"!=a.substr(b,2))throw"2nd item of sequene of signature is not ASN.1 integer";c=ASN1HEX.getHexOfV_AtObj(a,c);a=ASN1HEX.getHexOfV_AtObj(a,b);return{r:c,s:a}};
+KJUR.crypto.ECDSA.asn1SigToConcatSig=function(a){var b=KJUR.crypto.ECDSA.parseSigHexInHexRS(a);a=b.r;b=b.s;"00"==a.substr(0,2)&&8==a.length/2*8%128&&(a=a.substr(2));"00"==b.substr(0,2)&&8==b.length/2*8%128&&(b=b.substr(2));if(0!=a.length/2*8%128)throw"unknown ECDSA sig r length error";if(0!=b.length/2*8%128)throw"unknown ECDSA sig s length error";return a+b};
+KJUR.crypto.ECDSA.concatSigToASN1Sig=function(a){if(0!=a.length/2*8%128)throw"unknown ECDSA concatinated r-s sig  length error";var b=a.substr(0,a.length/2);a=a.substr(a.length/2);return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(b,a)};KJUR.crypto.ECDSA.hexRSSigToASN1Sig=function(a,b){var c=new BigInteger(a,16),d=new BigInteger(b,16);return KJUR.crypto.ECDSA.biRSSigToASN1Sig(c,d)};
+KJUR.crypto.ECDSA.biRSSigToASN1Sig=function(a,b){var c=new KJUR.asn1.DERInteger({bigint:a}),d=new KJUR.asn1.DERInteger({bigint:b});return(new KJUR.asn1.DERSequence({array:[c,d]})).getEncodedHex()};intShim=require("jsbn");
+ASN1HEX=new function(){this.getByteLengthOfL_AtObj=function(a,b){if("8"!=a.substring(b+2,b+3))return 1;var c=parseInt(a.substring(b+3,b+4));return 0==c?-1:0<c&&10>c?c+1:-2};this.getHexOfL_AtObj=function(a,b){var c=this.getByteLengthOfL_AtObj(a,b);return 1>c?"":a.substring(b+2,b+2+2*c)};this.getIntOfL_AtObj=function(a,b){var c=this.getHexOfL_AtObj(a,b);return""==c?-1:(8>parseInt(c.substring(0,1))?new BigInteger(c,16):new BigInteger(c.substring(2),16)).intValue()};this.getStartPosOfV_AtObj=function(a,
+b){var c=this.getByteLengthOfL_AtObj(a,b);return 0>c?c:b+2*(c+1)};this.getHexOfV_AtObj=function(a,b){var c=this.getStartPosOfV_AtObj(a,b),d=this.getIntOfL_AtObj(a,b);return a.substring(c,c+2*d)};this.getHexOfTLV_AtObj=function(a,b){var c=a.substr(b,2),d=this.getHexOfL_AtObj(a,b),e=this.getHexOfV_AtObj(a,b);return c+d+e};this.getPosOfNextSibling_AtObj=function(a,b){var c=this.getStartPosOfV_AtObj(a,b),d=this.getIntOfL_AtObj(a,b);return c+2*d};this.getPosArrayOfChildren_AtObj=function(a,b){var c=[],
+d=this.getStartPosOfV_AtObj(a,b);c.push(d);for(var e=this.getIntOfL_AtObj(a,b),f=d,g=0;;){f=this.getPosOfNextSibling_AtObj(a,f);if(null==f||f-d>=2*e)break;if(200<=g)break;c.push(f);g++}return c};this.getNthChildIndex_AtObj=function(a,b,c){return this.getPosArrayOfChildren_AtObj(a,b)[c]};this.getDecendantIndexByNthList=function(a,b,c){if(0==c.length)return b;var d=c.shift();b=this.getPosArrayOfChildren_AtObj(a,b);return this.getDecendantIndexByNthList(a,b[d],c)};this.getDecendantHexTLVByNthList=function(a,
+b,c){b=this.getDecendantIndexByNthList(a,b,c);return this.getHexOfTLV_AtObj(a,b)};this.getDecendantHexVByNthList=function(a,b,c){b=this.getDecendantIndexByNthList(a,b,c);return this.getHexOfV_AtObj(a,b)}};ASN1HEX.getVbyList=function(a,b,c,d){b=this.getDecendantIndexByNthList(a,b,c);if(void 0===b)throw"can't find nthList object";if(void 0!==d&&a.substr(b,2)!=d)throw"checking tag doesn't match: "+a.substr(b,2)+"!="+d;return this.getHexOfV_AtObj(a,b)};
+ASN1HEX.hextooidstr=function(a){var b=function(a,b){return a.length>=b?a:Array(b-a.length+1).join("0")+a},c=[],d=a.substr(0,2),d=parseInt(d,16);c[0]=new String(Math.floor(d/40));c[1]=new String(d%40);var e=a.substr(2);a=[];for(d=0;d<e.length/2;d++)a.push(parseInt(e.substr(2*d,2),16));for(var e=[],f="",d=0;d<a.length;d++)a[d]&128?f+=b((a[d]&127).toString(2),7):(f+=b((a[d]&127).toString(2),7),e.push(new String(parseInt(f,2))),f="");b=c.join(".");0<e.length&&(b=b+"."+e.join("."));return b};
+ASN1HEX.dump=function(a,b,c,d){var e=function(a,b){return a.length<=2*b?a:a.substr(0,b)+"..(total "+a.length/2+"bytes).."+a.substr(a.length-b,b)};void 0===b&&(b={ommit_long_octet:32});void 0===c&&(c=0);void 0===d&&(d="");var f=b.ommit_long_octet;if("01"==a.substr(c,2))return a=ASN1HEX.getHexOfV_AtObj(a,c),"00"==a?d+"BOOLEAN FALSE\n":d+"BOOLEAN TRUE\n";if("02"==a.substr(c,2))return a=ASN1HEX.getHexOfV_AtObj(a,c),d+"INTEGER "+e(a,f)+"\n";if("03"==a.substr(c,2))return a=ASN1HEX.getHexOfV_AtObj(a,c),
+d+"BITSTRING "+e(a,f)+"\n";if("04"==a.substr(c,2))return a=ASN1HEX.getHexOfV_AtObj(a,c),ASN1HEX.isASN1HEX(a)?e=d+"OCTETSTRING, encapsulates\n"+ASN1HEX.dump(a,b,0,d+"  "):d+"OCTETSTRING "+e(a,f)+"\n";if("05"==a.substr(c,2))return d+"NULL\n";if("06"==a.substr(c,2)){a=ASN1HEX.getHexOfV_AtObj(a,c);var g=KJUR.asn1.ASN1Util.oidHexToInt(a),f=KJUR.asn1.x509.OID.oid2name(g);a=g.replace(/\./g," ");return""!=f?d+"ObjectIdentifier "+f+" ("+a+")\n":d+"ObjectIdentifier ("+a+")\n"}if("0c"==a.substr(c,2))return d+
+"UTF8String '"+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"'\n";if("13"==a.substr(c,2))return d+"PrintableString '"+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"'\n";if("14"==a.substr(c,2))return d+"TeletexString '"+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"'\n";if("16"==a.substr(c,2))return d+"IA5String '"+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"'\n";if("17"==a.substr(c,2))return d+"UTCTime "+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,c))+"\n";if("18"==a.substr(c,2))return d+"GeneralizedTime "+hextoutf8(ASN1HEX.getHexOfV_AtObj(a,
+c))+"\n";if("30"==a.substr(c,2)){if("3000"==a.substr(c,4))return d+"SEQUENCE {}\n";e=d+"SEQUENCE\n";c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c);f=b;2!=c.length&&3!=c.length||"06"!=a.substr(c[0],2)||"04"!=a.substr(c[c.length-1],2)||(f=ASN1HEX.getHexOfV_AtObj(a,c[0]),g=KJUR.asn1.ASN1Util.oidHexToInt(f),f=KJUR.asn1.x509.OID.oid2name(g),b=JSON.parse(JSON.stringify(b)),b.x509ExtName=f,f=b);for(g=0;g<c.length;g++)e+=ASN1HEX.dump(a,f,c[g],d+"  ");return e}if("31"==a.substr(c,2)){e=d+"SET\n";c=ASN1HEX.getPosArrayOfChildren_AtObj(a,
+c);for(g=0;g<c.length;g++)e+=ASN1HEX.dump(a,b,c[g],d+"  ");return e}f=parseInt(a.substr(c,2),16);if(0!=(f&128)){e=f&31;if(0!=(f&32))for(e=d+"["+e+"]\n",c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c),g=0;g<c.length;g++)e+=ASN1HEX.dump(a,b,c[g],d+"  ");else a=ASN1HEX.getHexOfV_AtObj(a,c),"68747470"==a.substr(0,8)&&(a=hextoutf8(a)),"subjectAltName"===b.x509ExtName&&2==e&&(a=hextoutf8(a)),e=d+"["+e+"] "+a+"\n";return e}return d+"UNKNOWN("+a.substr(c,2)+") "+ASN1HEX.getHexOfV_AtObj(a,c)+"\n"};
+ASN1HEX.isASN1HEX=function(a){if(1==a.length%2)return!1;var b=ASN1HEX.getIntOfL_AtObj(a,0),c=a.substr(0,2),d=ASN1HEX.getHexOfL_AtObj(a,0);return a.length-c.length-d.length==2*b?!0:!1};exports.ASN1HEX=ASN1HEX;module.exports=exports;b64tohex=require("./base64.js").b64tohex;RSAKey=require("./rsa.js").RSAKey;ASN1HEX=require("./asn1hex-1.1.js").ASN1HEX;
+function X509(){this.hex=this.subjectPublicKeyRSA_hE=this.subjectPublicKeyRSA_hN=this.subjectPublicKeyRSA=null;this.getSerialNumberHex=function(){return ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,1])};this.getIssuerHex=function(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3])};this.getIssuerString=function(){return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,3]))};this.getSubjectHex=function(){return ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5])};this.getSubjectString=
+function(){return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex,0,[0,5]))};this.getNotBefore=function(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,0]),a=a.replace(/(..)/g,"%$1");return a=decodeURIComponent(a)};this.getNotAfter=function(){var a=ASN1HEX.getDecendantHexVByNthList(this.hex,0,[0,4,1]),a=a.replace(/(..)/g,"%$1");return a=decodeURIComponent(a)};this.readCertPEM=function(a){a=X509.pemToHex(a);var b=X509.getPublicKeyHexArrayFromCertHex(a),c=new RSAKey;c.setPublic(b[0],
+b[1]);this.subjectPublicKeyRSA=c;this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a};this.readCertPEMWithoutRSAInit=function(a){a=X509.pemToHex(a);var b=X509.getPublicKeyHexArrayFromCertHex(a);this.subjectPublicKeyRSA.setPublic(b[0],b[1]);this.subjectPublicKeyRSA_hN=b[0];this.subjectPublicKeyRSA_hE=b[1];this.hex=a}}X509.pemToBase64=function(a){a=a.replace("-----BEGIN CERTIFICATE-----","");a=a.replace("-----END CERTIFICATE-----","");return a=a.replace(/[ \n]+/g,"")};
+X509.pemToHex=function(a){a=X509.pemToBase64(a);return b64tohex(a)};X509.getSubjectPublicKeyPosFromCertHex=function(a){var b=X509.getSubjectPublicKeyInfoPosFromCertHex(a);if(-1==b)return-1;b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);if(2!=b.length)return-1;b=b[1];if("03"!=a.substring(b,b+2))return-1;b=ASN1HEX.getStartPosOfV_AtObj(a,b);return"00"!=a.substring(b,b+2)?-1:b+2};
+X509.getSubjectPublicKeyInfoPosFromCertHex=function(a){var b=ASN1HEX.getStartPosOfV_AtObj(a,0),b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);return 1>b.length?-1:"a003020102"==a.substring(b[0],b[0]+10)?6>b.length?-1:b[6]:5>b.length?-1:b[5]};X509.getPublicKeyHexArrayFromCertHex=function(a){var b=X509.getSubjectPublicKeyPosFromCertHex(a),c=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);if(2!=c.length)return[];b=ASN1HEX.getHexOfV_AtObj(a,c[0]);a=ASN1HEX.getHexOfV_AtObj(a,c[1]);return null!=b&&null!=a?[b,a]:[]};
+X509.getHexTbsCertificateFromCert=function(a){return ASN1HEX.getStartPosOfV_AtObj(a,0)};X509.getPublicKeyHexArrayFromCertPEM=function(a){a=X509.pemToHex(a);return X509.getPublicKeyHexArrayFromCertHex(a)};X509.hex2dn=function(a){for(var b="",c=ASN1HEX.getPosArrayOfChildren_AtObj(a,0),d=0;d<c.length;d++)var e=ASN1HEX.getHexOfTLV_AtObj(a,c[d]),b=b+"/"+X509.hex2rdn(e);return b};
+X509.hex2rdn=function(a){var b=ASN1HEX.getDecendantHexTLVByNthList(a,0,[0,0]),c=ASN1HEX.getDecendantHexVByNthList(a,0,[0,1]);a="";try{a=X509.DN_ATTRHEX[b]}catch(d){a=b}c=c.replace(/(..)/g,"%$1");b=decodeURIComponent(c);return a+"="+b};X509.DN_ATTRHEX={"0603550406":"C","060355040a":"O","060355040b":"OU","0603550403":"CN","0603550405":"SN","0603550408":"ST","0603550407":"L"};
+X509.getPublicKeyFromCertPEM=function(a){var b=X509.getPublicKeyInfoPropOfCertPEM(a);if("2a864886f70d010101"==b.algoid){var c=KEYUTIL.parsePublicRawRSAKeyHex(b.keyhex);a=new RSAKey;a.setPublic(c.n,c.e);return a}if("2a8648ce3d0201"==b.algoid)return a=new KJUR.crypto.ECDSA({curve:KJUR.crypto.OID.oidhex2name[b.algparam],info:b.keyhex}),a.setPublicKeyHex(b.keyhex),a;if("2a8648ce380401"==b.algoid){var c=ASN1HEX.getVbyList(b.algparam,0,[0],"02"),d=ASN1HEX.getVbyList(b.algparam,0,[1],"02"),e=ASN1HEX.getVbyList(b.algparam,
+0,[2],"02"),b=ASN1HEX.getHexOfV_AtObj(b.keyhex,0),b=b.substr(2);a=new KJUR.crypto.DSA;a.setPublic(new BigInteger(c,16),new BigInteger(d,16),new BigInteger(e,16),new BigInteger(b,16));return a}throw"unsupported key";};
+X509.getPublicKeyInfoPropOfCertPEM=function(a){var b={algparam:null};a=X509.pemToHex(a);var c=ASN1HEX.getPosArrayOfChildren_AtObj(a,0);if(3!=c.length)throw"malformed X.509 certificate PEM (code:001)";if("30"!=a.substr(c[0],2))throw"malformed X.509 certificate PEM (code:002)";c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c[0]);if(7>c.length)throw"malformed X.509 certificate PEM (code:003)";c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c[6]);if(2!=c.length)throw"malformed X.509 certificate PEM (code:004)";var d=
+ASN1HEX.getPosArrayOfChildren_AtObj(a,c[0]);if(2!=d.length)throw"malformed X.509 certificate PEM (code:005)";b.algoid=ASN1HEX.getHexOfV_AtObj(a,d[0]);"06"==a.substr(d[1],2)?b.algparam=ASN1HEX.getHexOfV_AtObj(a,d[1]):"30"==a.substr(d[1],2)&&(b.algparam=ASN1HEX.getHexOfTLV_AtObj(a,d[1]));if("03"!=a.substr(c[1],2))throw"malformed X.509 certificate PEM (code:006)";a=ASN1HEX.getHexOfV_AtObj(a,c[1]);b.keyhex=a.substr(2);return b};
+X509.getPublicKeyInfoPosOfCertHEX=function(a){var b=ASN1HEX.getPosArrayOfChildren_AtObj(a,0);if(3!=b.length)throw"malformed X.509 certificate PEM (code:001)";if("30"!=a.substr(b[0],2))throw"malformed X.509 certificate PEM (code:002)";a=ASN1HEX.getPosArrayOfChildren_AtObj(a,b[0]);if(7>a.length)throw"malformed X.509 certificate PEM (code:003)";return a[6]};
+X509.getV3ExtInfoListOfCertHex=function(a){var b=ASN1HEX.getPosArrayOfChildren_AtObj(a,0);if(3!=b.length)throw"malformed X.509 certificate PEM (code:001)";if("30"!=a.substr(b[0],2))throw"malformed X.509 certificate PEM (code:002)";b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b[0]);if(8>b.length)throw"malformed X.509 certificate PEM (code:003)";if("a3"!=a.substr(b[7],2))throw"malformed X.509 certificate PEM (code:004)";b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b[7]);if(1!=b.length)throw"malformed X.509 certificate PEM (code:005)";
+if("30"!=a.substr(b[0],2))throw"malformed X.509 certificate PEM (code:006)";for(var b=ASN1HEX.getPosArrayOfChildren_AtObj(a,b[0]),c=b.length,d=Array(c),e=0;e<c;e++)d[e]=X509.getV3ExtItemInfo_AtObj(a,b[e]);return d};
+X509.getV3ExtItemInfo_AtObj=function(a,b){var c={};c.posTLV=b;var d=ASN1HEX.getPosArrayOfChildren_AtObj(a,b);if(2!=d.length&&3!=d.length)throw"malformed X.509v3 Ext (code:001)";if("06"!=a.substr(d[0],2))throw"malformed X.509v3 Ext (code:002)";var e=ASN1HEX.getHexOfV_AtObj(a,d[0]);c.oid=ASN1HEX.hextooidstr(e);c.critical=!1;3==d.length&&(c.critical=!0);d=d[d.length-1];if("04"!=a.substr(d,2))throw"malformed X.509v3 Ext (code:003)";c.posV=ASN1HEX.getStartPosOfV_AtObj(a,d);return c};
+X509.getHexOfTLV_V3ExtValue=function(a,b){var c=X509.getPosOfTLV_V3ExtValue(a,b);return-1==c?"":ASN1HEX.getHexOfTLV_AtObj(a,c)};X509.getHexOfV_V3ExtValue=function(a,b){var c=X509.getPosOfTLV_V3ExtValue(a,b);return-1==c?"":ASN1HEX.getHexOfV_AtObj(a,c)};X509.getPosOfTLV_V3ExtValue=function(a,b){var c=b;b.match(/^[0-9.]+$/)||(c=KJUR.asn1.x509.OID.name2oid(b));if(""==c)return-1;for(var d=X509.getV3ExtInfoListOfCertHex(a),e=0;e<d.length;e++){var f=d[e];if(f.oid==c)return f.posV}return-1};
+X509.KEYUSAGE_NAME="digitalSignature nonRepudiation keyEncipherment dataEncipherment keyAgreement keyCertSign cRLSign encipherOnly decipherOnly".split(" ");X509.getExtKeyUsageBin=function(a){var b=X509.getHexOfV_V3ExtValue(a,"keyUsage");if(""==b)return"";if(0!=b.length%2||2>=b.length)throw"malformed key usage value";a=parseInt(b.substr(0,2));b=parseInt(b.substr(2),16).toString(2);return b.substr(0,b.length-a)};
+X509.getExtKeyUsageString=function(a){a=X509.getExtKeyUsageBin(a);for(var b=[],c=0;c<a.length;c++)"1"==a.substr(c,1)&&b.push(X509.KEYUSAGE_NAME[c]);return b.join(",")};
+X509.getExtAIAInfo=function(a){var b={ocsp:[],caissuer:[]},c=X509.getPosOfTLV_V3ExtValue(a,"authorityInfoAccess");if(-1==c)return null;if("30"!=a.substr(c,2))throw"malformed AIA Extn Value";for(var c=ASN1HEX.getPosArrayOfChildren_AtObj(a,c),d=0;d<c.length;d++){var e=ASN1HEX.getPosArrayOfChildren_AtObj(a,c[d]);if(2!=e.length)throw"malformed AccessDescription of AIA Extn";var f=e[0],e=e[1];"2b06010505073001"==ASN1HEX.getHexOfV_AtObj(a,f)&&"86"==a.substr(e,2)&&b.ocsp.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(a,
+e)));"2b06010505073002"==ASN1HEX.getHexOfV_AtObj(a,f)&&"86"==a.substr(e,2)&&b.caissuer.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(a,e)))}return b};exports.X509=X509;module.exports=exports;var dbits,canary=0xdeadbeefcafe,j_lm=15715070==(canary&16777215),BigInteger=function(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))};function nbi(){return new BigInteger(null)}
+function am1(a,b,c,d,e,f){for(;0<=--f;){var g=b*this[a++]+c[d]+e;e=Math.floor(g/67108864);c[d++]=g&67108863}return e}function am2(a,b,c,d,e,f){var g=b&32767;for(b>>=15;0<=--f;){var h=this[a]&32767,k=this[a++]>>15,l=b*h+k*g,h=g*h+((l&32767)<<15)+c[d]+(e&1073741823);e=(h>>>30)+(l>>>15)+b*k+(e>>>30);c[d++]=h&1073741823}return e}
+function am3(a,b,c,d,e,f){var g=b&16383;for(b>>=14;0<=--f;){var h=this[a]&16383,k=this[a++]>>14,l=b*h+k*g,h=g*h+((l&16383)<<14)+c[d]+e;e=(h>>28)+(l>>14)+b*k;c[d++]=h&268435455}return e}j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28);BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;
 var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz",BI_RC=[],rr,vv;rr=48;for(vv=0;9>=vv;++vv)BI_RC[rr++]=vv;rr=97;for(vv=10;36>vv;++vv)BI_RC[rr++]=vv;rr=65;for(vv=10;36>vv;++vv)BI_RC[rr++]=vv;function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return null==c?-1:c}
-function bnpCopyTo(a){for(var b=this.t-1;0<=b;--b)a[b]=this[b];a.t=this.t;a.s=this.s}function bnpFromInt(a){this.t=1;this.s=0>a?-1:0;0<a?this[0]=a:-1>a?this[0]=a+DV:this.t=0}function nbv(a){var b=nbi();b.fromInt(a);return b}
+function bnpCopyTo(a){for(var b=this.t-1;0<=b;--b)a[b]=this[b];a.t=this.t;a.s=this.s}function bnpFromInt(a){this.t=1;this.s=0>a?-1:0;0<a?this[0]=a:-1>a?this[0]=a+this.DV:this.t=0}function nbv(a){var b=nbi();b.fromInt(a);return b}
 function bnpFromString(a,b){var c;if(16==b)c=4;else if(8==b)c=3;else if(256==b)c=8;else if(2==b)c=1;else if(32==b)c=5;else if(4==b)c=2;else{this.fromRadix(a,b);return}this.s=this.t=0;for(var d=a.length,e=!1,f=0;0<=--d;){var g=8==c?a[d]&255:intAt(a,d);0>g?"-"==a.charAt(d)&&(e=!0):(e=!1,0==f?this[this.t++]=g:f+c>this.DB?(this[this.t-1]|=(g&(1<<this.DB-f)-1)<<f,this[this.t++]=g>>this.DB-f):this[this.t-1]|=g<<f,f+=c,f>=this.DB&&(f-=this.DB))}8==c&&0!=(a[0]&128)&&(this.s=-1,0<f&&(this[this.t-1]|=(1<<this.DB-
 f)-1<<f));this.clamp();e&&BigInteger.ZERO.subTo(this,this)}function bnpClamp(){for(var a=this.s&this.DM;0<this.t&&this[this.t-1]==a;)--this.t}
-function bnToString(a){if(0>this.s)return"-"+this.negate().toString(a);if(16==a)a=4;else if(8==a)a=3;else if(2==a)a=1;else if(32==a)a=5;else if(4==a)a=2;else return this.toRadix(a);var b=(1<<a)-1,c,d=!1,e="",f=this.t,g=this.DB-f*this.DB%a;if(0<f--){if(g<this.DB&&0<(c=this[f]>>g))d=!0,e=int2char(c);for(;0<=f;)g<a?(c=(this[f]&(1<<g)-1)<<a-g,c|=this[--f]>>(g+=this.DB-a)):(c=this[f]>>(g-=a)&b,0>=g&&(g+=this.DB,--f)),0<c&&(d=!0),d&&(e+=int2char(c))}return d?e:"0"}
-function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return 0>this.s?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t,b=c-a.t;if(0!=b)return b;for(;0<=--c;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b=1,c;if(0!=(c=a>>>16))a=c,b+=16;if(0!=(c=a>>8))a=c,b+=8;if(0!=(c=a>>4))a=c,b+=4;if(0!=(c=a>>2))a=c,b+=2;0!=a>>1&&(b+=1);return b}
+function bnToString(a){if(0>this.s)return"-"+this.negate().toString(a);if(16==a)a=4;else if(8==a)a=3;else if(2==a)a=1;else if(32==a)a=5;else if(4==a)a=2;else return this.toRadix(a);var b=(1<<a)-1,c,d=!1,e="",f=this.t,g=this.DB-f*this.DB%a;if(0<f--)for(g<this.DB&&0<(c=this[f]>>g)&&(d=!0,e=int2char(c));0<=f;)g<a?(c=(this[f]&(1<<g)-1)<<a-g,c|=this[--f]>>(g+=this.DB-a)):(c=this[f]>>(g-=a)&b,0>=g&&(g+=this.DB,--f)),0<c&&(d=!0),d&&(e+=int2char(c));return d?e:"0"}
+function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return 0>this.s?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t,b=c-a.t;if(0!=b)return 0>this.s?-b:b;for(;0<=--c;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b=1,c;0!=(c=a>>>16)&&(a=c,b+=16);0!=(c=a>>8)&&(a=c,b+=8);0!=(c=a>>4)&&(a=c,b+=4);0!=(c=a>>2)&&(a=c,b+=2);0!=a>>1&&(b+=1);return b}
 function bnBitLength(){return 0>=this.t?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;0<=c;--c)b[c+a]=this[c];for(c=a-1;0<=c;--c)b[c]=0;b.t=this.t+a;b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c<this.t;++c)b[c-a]=this[c];b.t=Math.max(this.t-a,0);b.s=this.s}
 function bnpLShiftTo(a,b){var c=a%this.DB,d=this.DB-c,e=(1<<d)-1,f=Math.floor(a/this.DB),g=this.s<<c&this.DM,h;for(h=this.t-1;0<=h;--h)b[h+f+1]=this[h]>>d|g,g=(this[h]&e)<<c;for(h=f-1;0<=h;--h)b[h]=0;b[f]=g;b.t=this.t+f+1;b.s=this.s;b.clamp()}
 function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)b.t=0;else{var d=a%this.DB,e=this.DB-d,f=(1<<d)-1;b[0]=this[c]>>d;for(var g=c+1;g<this.t;++g)b[g-c-1]|=(this[g]&f)<<e,b[g-c]=this[g]>>d;0<d&&(b[this.t-c-1]|=(this.s&f)<<e);b.t=this.t-c;b.clamp()}}
 function bnpSubTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d-=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d-=a[c],b[c++]=d&this.DM,d>>=this.DB;d-=a.s}b.s=0>d?-1:0;-1>d?b[c++]=this.DV+d:0<d&&(b[c++]=d);b.t=c;b.clamp()}
-function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;0<=--e;)b[e]=0;for(e=0;e<d.t;++e)b[e+c.t]=c.am(0,d[e],b,e,0,c.t);b.s=0;b.clamp();this.s!=a.s&&BigInteger.ZERO.subTo(b,b)}function bnpSquareTo(a){for(var b=this.abs(),c=a.t=2*b.t;0<=--c;)a[c]=0;for(c=0;c<b.t-1;++c){var d=b.am(c,b[c],a,2*c,0,1);if((a[c+b.t]+=b.am(c+1,2*b[c],a,2*c+1,d,b.t-c-1))>=b.DV)a[c+b.t]-=b.DV,a[c+b.t+1]=1}0<a.t&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1));a.s=0;a.clamp()}
-function bnpDivRemTo(a,b,c){var d=a.abs();if(!(0>=d.t)){var e=this.abs();if(e.t<d.t)null!=b&&b.fromInt(0),null!=c&&this.copyTo(c);else{null==c&&(c=nbi());var f=nbi(),g=this.s;a=a.s;var h=this.DB-nbits(d[d.t-1]);0<h?(d.lShiftTo(h,f),e.lShiftTo(h,c)):(d.copyTo(f),e.copyTo(c));d=f.t;e=f[d-1];if(0!=e){var j=e*(1<<this.F1)+(1<d?f[d-2]>>this.F2:0),l=this.FV/j,j=(1<<this.F1)/j,n=1<<this.F2,m=c.t,p=m-d,k=null==b?nbi():b;f.dlShiftTo(p,k);0<=c.compareTo(k)&&(c[c.t++]=1,c.subTo(k,c));BigInteger.ONE.dlShiftTo(d,
-k);for(k.subTo(f,f);f.t<d;)f[f.t++]=0;for(;0<=--p;){var q=c[--m]==e?this.DM:Math.floor(c[m]*l+(c[m-1]+n)*j);if((c[m]+=f.am(0,q,c,p,0,d))<q){f.dlShiftTo(p,k);for(c.subTo(k,c);c[m]<--q;)c.subTo(k,c)}}null!=b&&(c.drShiftTo(d,b),g!=a&&BigInteger.ZERO.subTo(b,b));c.t=d;c.clamp();0<h&&c.rShiftTo(h,c);0>g&&BigInteger.ZERO.subTo(c,c)}}}}function bnMod(a){var b=nbi();this.abs().divRemTo(a,null,b);0>this.s&&0<b.compareTo(BigInteger.ZERO)&&a.subTo(b,b);return b}function Classic(a){this.m=a}
+function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;0<=--e;)b[e]=0;for(e=0;e<d.t;++e)b[e+c.t]=c.am(0,d[e],b,e,0,c.t);b.s=0;b.clamp();this.s!=a.s&&BigInteger.ZERO.subTo(b,b)}function bnpSquareTo(a){for(var b=this.abs(),c=a.t=2*b.t;0<=--c;)a[c]=0;for(c=0;c<b.t-1;++c){var d=b.am(c,b[c],a,2*c,0,1);(a[c+b.t]+=b.am(c+1,2*b[c],a,2*c+1,d,b.t-c-1))>=b.DV&&(a[c+b.t]-=b.DV,a[c+b.t+1]=1)}0<a.t&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1));a.s=0;a.clamp()}
+function bnpDivRemTo(a,b,c){var d=a.abs();if(!(0>=d.t)){var e=this.abs();if(e.t<d.t)null!=b&&b.fromInt(0),null!=c&&this.copyTo(c);else{null==c&&(c=nbi());var f=nbi(),g=this.s;a=a.s;var h=this.DB-nbits(d[d.t-1]);0<h?(d.lShiftTo(h,f),e.lShiftTo(h,c)):(d.copyTo(f),e.copyTo(c));d=f.t;e=f[d-1];if(0!=e){var k=e*(1<<this.F1)+(1<d?f[d-2]>>this.F2:0),l=this.FV/k,k=(1<<this.F1)/k,m=1<<this.F2,q=c.t,p=q-d,s=null==b?nbi():b;f.dlShiftTo(p,s);0<=c.compareTo(s)&&(c[c.t++]=1,c.subTo(s,c));BigInteger.ONE.dlShiftTo(d,
+s);for(s.subTo(f,f);f.t<d;)f[f.t++]=0;for(;0<=--p;){var w=c[--q]==e?this.DM:Math.floor(c[q]*l+(c[q-1]+m)*k);if((c[q]+=f.am(0,w,c,p,0,d))<w)for(f.dlShiftTo(p,s),c.subTo(s,c);c[q]<--w;)c.subTo(s,c)}null!=b&&(c.drShiftTo(d,b),g!=a&&BigInteger.ZERO.subTo(b,b));c.t=d;c.clamp();0<h&&c.rShiftTo(h,c);0>g&&BigInteger.ZERO.subTo(c,c)}}}}function bnMod(a){var b=nbi();this.abs().divRemTo(a,null,b);0>this.s&&0<b.compareTo(BigInteger.ZERO)&&a.subTo(b,b);return b}function Classic(a){this.m=a}
 function cConvert(a){return 0>a.s||0<=a.compareTo(this.m)?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}function cSqrTo(a,b){a.squareTo(b);this.reduce(b)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;
 function bnpInvDigit(){if(1>this.t)return 0;var a=this[0];if(0==(a&1))return 0;var b=a&3,b=b*(2-(a&15)*b)&15,b=b*(2-(a&255)*b)&255,b=b*(2-((a&65535)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV;return 0<b?this.DV-b:-b}function Montgomery(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<a.DB-15)-1;this.mt2=2*a.t}
 function montConvert(a){var b=nbi();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);0>a.s&&0<b.compareTo(BigInteger.ZERO)&&this.m.subTo(b,b);return b}function montRevert(a){var b=nbi();a.copyTo(b);this.reduce(b);return b}
@@ -228,56 +169,952 @@
 BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;
 BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnClone(){var a=nbi();this.copyTo(a);return a}function bnIntValue(){if(0>this.s){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnByteValue(){return 0==this.t?this.s:this[0]<<24>>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}
 function bnSigNum(){return 0>this.s?-1:0>=this.t||1==this.t&&0>=this[0]?0:1}function bnpToRadix(a){null==a&&(a=10);if(0==this.signum()||2>a||36<a)return"0";var b=this.chunkSize(a),b=Math.pow(a,b),c=nbv(b),d=nbi(),e=nbi(),f="";for(this.divRemTo(c,d,e);0<d.signum();)f=(b+e.intValue()).toString(a).substr(1)+f,d.divRemTo(c,d,e);return e.intValue().toString(a)+f}
-function bnpFromRadix(a,b){this.fromInt(0);null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,g=0,h=0;h<a.length;++h){var j=intAt(a,h);0>j?"-"==a.charAt(h)&&0==this.signum()&&(e=!0):(g=b*g+j,++f>=c&&(this.dMultiply(d),this.dAddOffset(g,0),g=f=0))}0<f&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(g,0));e&&BigInteger.ZERO.subTo(this,this)}
-function bnpFromNumber(a,b,c){if("number"==typeof b)if(2>a)this.fromInt(1);else{this.fromNumber(a,c);this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);for(this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this)}else{c=[];var d=a&7;c.length=(a>>3)+1;b.nextBytes(c);c[0]=0<d?c[0]&(1<<d)-1:0;this.fromString(c,256)}}
-function bnToByteArray(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,d,e=0;if(0<a--){if(c<this.DB&&(d=this[a]>>c)!=(this.s&this.DM)>>c)b[e++]=d|this.s<<this.DB-c;for(;0<=a;)if(8>c?(d=(this[a]&(1<<c)-1)<<8-c,d|=this[--a]>>(c+=this.DB-8)):(d=this[a]>>(c-=8)&255,0>=c&&(c+=this.DB,--a)),0!=(d&128)&&(d|=-256),0==e&&(this.s&128)!=(d&128)&&++e,0<e||d!=this.s)b[e++]=d}return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return 0>this.compareTo(a)?this:a}
+function bnpFromRadix(a,b){this.fromInt(0);null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,g=0,h=0;h<a.length;++h){var k=intAt(a,h);0>k?"-"==a.charAt(h)&&0==this.signum()&&(e=!0):(g=b*g+k,++f>=c&&(this.dMultiply(d),this.dAddOffset(g,0),g=f=0))}0<f&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(g,0));e&&BigInteger.ZERO.subTo(this,this)}
+function bnpFromNumber(a,b,c){if("number"==typeof b)if(2>a)this.fromInt(1);else for(this.fromNumber(a,c),this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this);else{c=[];var d=a&7;c.length=(a>>3)+1;b.nextBytes(c);c[0]=0<d?c[0]&(1<<d)-1:0;this.fromString(c,256)}}
+function bnToByteArray(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,d,e=0;if(0<a--)for(c<this.DB&&(d=this[a]>>c)!=(this.s&this.DM)>>c&&(b[e++]=d|this.s<<this.DB-c);0<=a;)if(8>c?(d=(this[a]&(1<<c)-1)<<8-c,d|=this[--a]>>(c+=this.DB-8)):(d=this[a]>>(c-=8)&255,0>=c&&(c+=this.DB,--a)),0!=(d&128)&&(d|=-256),0==e&&(this.s&128)!=(d&128)&&++e,0<e||d!=this.s)b[e++]=d;return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return 0>this.compareTo(a)?this:a}
 function bnMax(a){return 0<this.compareTo(a)?this:a}function bnpBitwiseTo(a,b,c){var d,e,f=Math.min(a.t,this.t);for(d=0;d<f;++d)c[d]=b(this[d],a[d]);if(a.t<this.t){e=a.s&this.DM;for(d=f;d<this.t;++d)c[d]=b(this[d],e);c.t=this.t}else{e=this.s&this.DM;for(d=f;d<a.t;++d)c[d]=b(e,a[d]);c.t=a.t}c.s=b(this.s,a.s);c.clamp()}function op_and(a,b){return a&b}function bnAnd(a){var b=nbi();this.bitwiseTo(a,op_and,b);return b}function op_or(a,b){return a|b}
 function bnOr(a){var b=nbi();this.bitwiseTo(a,op_or,b);return b}function op_xor(a,b){return a^b}function bnXor(a){var b=nbi();this.bitwiseTo(a,op_xor,b);return b}function op_andnot(a,b){return a&~b}function bnAndNot(a){var b=nbi();this.bitwiseTo(a,op_andnot,b);return b}function bnNot(){for(var a=nbi(),b=0;b<this.t;++b)a[b]=this.DM&~this[b];a.t=this.t;a.s=~this.s;return a}function bnShiftLeft(a){var b=nbi();0>a?this.rShiftTo(-a,b):this.lShiftTo(a,b);return b}
 function bnShiftRight(a){var b=nbi();0>a?this.lShiftTo(-a,b):this.rShiftTo(a,b);return b}function lbit(a){if(0==a)return-1;var b=0;0==(a&65535)&&(a>>=16,b+=16);0==(a&255)&&(a>>=8,b+=8);0==(a&15)&&(a>>=4,b+=4);0==(a&3)&&(a>>=2,b+=2);0==(a&1)&&++b;return b}function bnGetLowestSetBit(){for(var a=0;a<this.t;++a)if(0!=this[a])return a*this.DB+lbit(this[a]);return 0>this.s?this.t*this.DB:-1}function cbit(a){for(var b=0;0!=a;)a&=a-1,++b;return b}
 function bnBitCount(){for(var a=0,b=this.s&this.DM,c=0;c<this.t;++c)a+=cbit(this[c]^b);return a}function bnTestBit(a){var b=Math.floor(a/this.DB);return b>=this.t?0!=this.s:0!=(this[b]&1<<a%this.DB)}function bnpChangeBit(a,b){var c=BigInteger.ONE.shiftLeft(a);this.bitwiseTo(c,b,c);return c}function bnSetBit(a){return this.changeBit(a,op_or)}function bnClearBit(a){return this.changeBit(a,op_andnot)}function bnFlipBit(a){return this.changeBit(a,op_xor)}
 function bnpAddTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]+a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d+=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d+=a[c],b[c++]=d&this.DM,d>>=this.DB;d+=a.s}b.s=0>d?-1:0;0<d?b[c++]=d:-1>d&&(b[c++]=this.DV+d);b.t=c;b.clamp()}function bnAdd(a){var b=nbi();this.addTo(a,b);return b}function bnSubtract(a){var b=nbi();this.subTo(a,b);return b}
-function bnMultiply(a){var b=nbi();this.multiplyTo(a,b);return b}function bnDivide(a){var b=nbi();this.divRemTo(a,b,null);return b}function bnRemainder(a){var b=nbi();this.divRemTo(a,null,b);return b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();this.divRemTo(a,b,c);return[b,c]}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()}
+function bnMultiply(a){var b=nbi();this.multiplyTo(a,b);return b}function bnSquare(){var a=nbi();this.squareTo(a);return a}function bnDivide(a){var b=nbi();this.divRemTo(a,b,null);return b}function bnRemainder(a){var b=nbi();this.divRemTo(a,null,b);return b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();this.divRemTo(a,b,c);return[b,c]}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()}
 function bnpDAddOffset(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}NullExp.prototype.convert=nNop;NullExp.prototype.revert=nNop;NullExp.prototype.mulTo=nMulTo;NullExp.prototype.sqrTo=nSqrTo;function bnPow(a){return this.exp(a,new NullExp)}
 function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);c.s=0;for(c.t=d;0<d;)c[--d]=0;var e;for(e=c.t-this.t;d<e;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);d<e;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function bnpMultiplyUpperTo(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;0<=--d;)c[d]=0;for(d=Math.max(b-this.t,0);d<a.t;++d)c[this.t+d-b]=this.am(b-d,a[d],c,0,0,this.t+d-b);c.clamp();c.drShiftTo(1,c)}
 function Barrett(a){this.r2=nbi();this.q3=nbi();BigInteger.ONE.dlShiftTo(2*a.t,this.r2);this.mu=this.r2.divide(a);this.m=a}function barrettConvert(a){if(0>a.s||a.t>2*this.m.t)return a.mod(this.m);if(0>a.compareTo(this.m))return a;var b=nbi();a.copyTo(b);this.reduce(b);return b}function barrettRevert(a){return a}
 function barrettReduce(a){a.drShiftTo(this.m.t-1,this.r2);a.t>this.m.t+1&&(a.t=this.m.t+1,a.clamp());this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);for(this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);0>a.compareTo(this.r2);)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);0<=a.compareTo(this.m);)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b);this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Barrett.prototype.convert=barrettConvert;
 Barrett.prototype.revert=barrettRevert;Barrett.prototype.reduce=barrettReduce;Barrett.prototype.mulTo=barrettMulTo;Barrett.prototype.sqrTo=barrettSqrTo;
-function bnModPow(a,b){var c=a.bitLength(),d,e=nbv(1),f;if(0>=c)return e;d=18>c?1:48>c?3:144>c?4:768>c?5:6;f=8>c?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var g=[],h=3,j=d-1,l=(1<<d)-1;g[1]=f.convert(this);if(1<d){c=nbi();for(f.sqrTo(g[1],c);h<=l;)g[h]=nbi(),f.mulTo(c,g[h-2],g[h]),h+=2}for(var n=a.t-1,m,p=!0,k=nbi(),c=nbits(a[n])-1;0<=n;){c>=j?m=a[n]>>c-j&l:(m=(a[n]&(1<<c+1)-1)<<j-c,0<n&&(m|=a[n-1]>>this.DB+c-j));for(h=d;0==(m&1);)m>>=1,--h;if(0>(c-=h))c+=this.DB,--n;if(p)g[m].copyTo(e),
-p=!1;else{for(;1<h;)f.sqrTo(e,k),f.sqrTo(k,e),h-=2;0<h?f.sqrTo(e,k):(h=e,e=k,k=h);f.mulTo(k,g[m],e)}for(;0<=n&&0==(a[n]&1<<c);)f.sqrTo(e,k),h=e,e=k,k=h,0>--c&&(c=this.DB-1,--n)}return f.revert(e)}
+function bnModPow(a,b){var c=a.bitLength(),d,e=nbv(1),f;if(0>=c)return e;d=18>c?1:48>c?3:144>c?4:768>c?5:6;f=8>c?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var g=[],h=3,k=d-1,l=(1<<d)-1;g[1]=f.convert(this);if(1<d)for(c=nbi(),f.sqrTo(g[1],c);h<=l;)g[h]=nbi(),f.mulTo(c,g[h-2],g[h]),h+=2;for(var m=a.t-1,q,p=!0,s=nbi(),c=nbits(a[m])-1;0<=m;){c>=k?q=a[m]>>c-k&l:(q=(a[m]&(1<<c+1)-1)<<k-c,0<m&&(q|=a[m-1]>>this.DB+c-k));for(h=d;0==(q&1);)q>>=1,--h;0>(c-=h)&&(c+=this.DB,--m);if(p)g[q].copyTo(e),
+p=!1;else{for(;1<h;)f.sqrTo(e,s),f.sqrTo(s,e),h-=2;0<h?f.sqrTo(e,s):(h=e,e=s,s=h);f.mulTo(s,g[q],e)}for(;0<=m&&0==(a[m]&1<<c);)f.sqrTo(e,s),h=e,e=s,s=h,0>--c&&(c=this.DB-1,--m)}return f.revert(e)}
 function bnGCD(a){var b=0>this.s?this.negate():this.clone();a=0>a.s?a.negate():a.clone();if(0>b.compareTo(a)){var c=b,b=a;a=c}var c=b.getLowestSetBit(),d=a.getLowestSetBit();if(0>d)return b;c<d&&(d=c);0<d&&(b.rShiftTo(d,b),a.rShiftTo(d,a));for(;0<b.signum();)0<(c=b.getLowestSetBit())&&b.rShiftTo(c,b),0<(c=a.getLowestSetBit())&&a.rShiftTo(c,a),0<=b.compareTo(a)?(b.subTo(a,b),b.rShiftTo(1,b)):(a.subTo(b,a),a.rShiftTo(1,a));0<d&&a.lShiftTo(d,a);return a}
 function bnpModInt(a){if(0>=a)return 0;var b=this.DV%a,c=0>this.s?a-1:0;if(0<this.t)if(0==b)c=this[0]%a;else for(var d=this.t-1;0<=d;--d)c=(b*c+this[d])%a;return c}
-function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),f=nbv(0),g=nbv(0),h=nbv(1);0!=c.signum();){for(;c.isEven();){c.rShiftTo(1,c);if(b){if(!e.isEven()||!f.isEven())e.addTo(this,e),f.subTo(a,f);e.rShiftTo(1,e)}else f.isEven()||f.subTo(a,f);f.rShiftTo(1,f)}for(;d.isEven();){d.rShiftTo(1,d);if(b){if(!g.isEven()||!h.isEven())g.addTo(this,g),h.subTo(a,h);g.rShiftTo(1,g)}else h.isEven()||h.subTo(a,h);h.rShiftTo(1,
-h)}0<=c.compareTo(d)?(c.subTo(d,c),b&&e.subTo(g,e),f.subTo(h,f)):(d.subTo(c,d),b&&g.subTo(e,g),h.subTo(f,h))}if(0!=d.compareTo(BigInteger.ONE))return BigInteger.ZERO;if(0<=h.compareTo(a))return h.subtract(a);if(0>h.signum())h.addTo(a,h);else return h;return 0>h.signum()?h.add(a):h}
-var lowprimes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509],lplim=67108864/lowprimes[lowprimes.length-1];
+function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),f=nbv(0),g=nbv(0),h=nbv(1);0!=c.signum();){for(;c.isEven();)c.rShiftTo(1,c),b?(e.isEven()&&f.isEven()||(e.addTo(this,e),f.subTo(a,f)),e.rShiftTo(1,e)):f.isEven()||f.subTo(a,f),f.rShiftTo(1,f);for(;d.isEven();)d.rShiftTo(1,d),b?(g.isEven()&&h.isEven()||(g.addTo(this,g),h.subTo(a,h)),g.rShiftTo(1,g)):h.isEven()||h.subTo(a,h),h.rShiftTo(1,h);0<=c.compareTo(d)?
+(c.subTo(d,c),b&&e.subTo(g,e),f.subTo(h,f)):(d.subTo(c,d),b&&g.subTo(e,g),h.subTo(f,h))}if(0!=d.compareTo(BigInteger.ONE))return BigInteger.ZERO;if(0<=h.compareTo(a))return h.subtract(a);if(0>h.signum())h.addTo(a,h);else return h;return 0>h.signum()?h.add(a):h}
+var lowprimes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,
+733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],lplim=67108864/lowprimes[lowprimes.length-1];
 function bnIsProbablePrime(a){var b,c=this.abs();if(1==c.t&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;b<lowprimes.length;++b)if(c[0]==lowprimes[b])return!0;return!1}if(c.isEven())return!1;for(b=1;b<lowprimes.length;){for(var d=lowprimes[b],e=b+1;e<lowprimes.length&&d<lplim;)d*=lowprimes[e++];for(d=c.modInt(d);b<e;)if(0==d%lowprimes[b++])return!1}return c.millerRabin(a)}
-function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(0>=c)return!1;var d=b.shiftRight(c);a=a+1>>1;a>lowprimes.length&&(a=lowprimes.length);for(var e=nbi(),f=0;f<a;++f){e.fromInt(lowprimes[f]);var g=e.modPow(d,this);if(0!=g.compareTo(BigInteger.ONE)&&0!=g.compareTo(b)){for(var h=1;h++<c&&0!=g.compareTo(b);)if(g=g.modPowInt(2,this),0==g.compareTo(BigInteger.ONE))return!1;if(0!=g.compareTo(b))return!1}}return!0}BigInteger.prototype.chunkSize=bnpChunkSize;
-BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.fromNumber=bnpFromNumber;BigInteger.prototype.bitwiseTo=bnpBitwiseTo;BigInteger.prototype.changeBit=bnpChangeBit;BigInteger.prototype.addTo=bnpAddTo;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo;BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo;BigInteger.prototype.modInt=bnpModInt;
-BigInteger.prototype.millerRabin=bnpMillerRabin;BigInteger.prototype.clone=bnClone;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.byteValue=bnByteValue;BigInteger.prototype.shortValue=bnShortValue;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.toByteArray=bnToByteArray;BigInteger.prototype.equals=bnEquals;BigInteger.prototype.min=bnMin;BigInteger.prototype.max=bnMax;BigInteger.prototype.and=bnAnd;BigInteger.prototype.or=bnOr;BigInteger.prototype.xor=bnXor;
-BigInteger.prototype.andNot=bnAndNot;BigInteger.prototype.not=bnNot;BigInteger.prototype.shiftLeft=bnShiftLeft;BigInteger.prototype.shiftRight=bnShiftRight;BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit;BigInteger.prototype.bitCount=bnBitCount;BigInteger.prototype.testBit=bnTestBit;BigInteger.prototype.setBit=bnSetBit;BigInteger.prototype.clearBit=bnClearBit;BigInteger.prototype.flipBit=bnFlipBit;BigInteger.prototype.add=bnAdd;BigInteger.prototype.subtract=bnSubtract;
-BigInteger.prototype.multiply=bnMultiply;BigInteger.prototype.divide=bnDivide;BigInteger.prototype.remainder=bnRemainder;BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder;BigInteger.prototype.modPow=bnModPow;BigInteger.prototype.modInverse=bnModInverse;BigInteger.prototype.pow=bnPow;BigInteger.prototype.gcd=bnGCD;BigInteger.prototype.isProbablePrime=bnIsProbablePrime;
-var LOG=0,NDN=function NDN(b){if(!NDN.supported)throw Error("The necessary JavaScript support is not available on this platform.");b=b||{};this.transport=(b.getTransport||function(){return new WebSocketTransport})();this.getHostAndPort=b.getHostAndPort||this.transport.defaultGetHostAndPort;this.host=void 0!==b.host?b.host:null;this.port=b.port||9696;this.readyStatus=NDN.UNOPEN;this.verify=void 0!==b.verify?b.verify:!0;this.onopen=b.onopen||function(){3<LOG&&console.log("NDN connection established.")};
-this.onclose=b.onclose||function(){3<LOG&&console.log("NDN connection closed.")};this.ndndid=null};NDN.UNOPEN=0;NDN.OPENED=1;NDN.CLOSED=2;NDN.getSupported=function(){try{(new Uint8Array(1)).subarray(0,1)}catch(a){return console.log("NDN not available: Uint8Array not supported. "+a),!1}return!0};NDN.supported=NDN.getSupported();NDN.ndndIdFetcher=new Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY");NDN.prototype.createRoute=function(a,b){this.host=a;this.port=b};NDN.KeyStore=[];
-var KeyStoreEntry=function(a,b,c){this.keyName=a;this.rsaKey=b;this.timeStamp=c};NDN.addKeyEntry=function(a){null==NDN.getKeyByName(a.keyName)&&NDN.KeyStore.push(a)};NDN.getKeyByName=function(a){for(var b=null,c=0;c<NDN.KeyStore.length;c++)if(NDN.KeyStore[c].keyName.contentName.match(a.contentName)&&(null==b||NDN.KeyStore[c].keyName.contentName.components.length>b.keyName.contentName.components.length))b=NDN.KeyStore[c];return b};NDN.PITTable=[];
-var PITEntry=function(a,b){this.interest=a;this.closure=b;this.timerID=-1};NDN.getEntryForExpressedInterest=function(a){for(var b=null,c=0;c<NDN.PITTable.length;c++)if(NDN.PITTable[c].interest.matches_name(a)&&(null==b||NDN.PITTable[c].interest.name.components.length>b.interest.name.components.length))b=NDN.PITTable[c];return b};NDN.CSTable=[];var CSEntry=function(a,b){this.name=a;this.closure=b};
-function getEntryForRegisteredPrefix(a){for(var b=0;b<NDN.CSTable.length;b++)if(null!=NDN.CSTable[b].name.match(a))return NDN.CSTable[b];return null}NDN.makeShuffledGetHostAndPort=function(a,b){a=a.slice(0,a.length);DataUtils.shuffle(a);return function(){return 0==a.length?null:{host:a.splice(0,1)[0],port:b}}};
-NDN.prototype.expressInterest=function(a,b,c){var d=new Interest(a);null!=c?(d.minSuffixComponents=c.minSuffixComponents,d.maxSuffixComponents=c.maxSuffixComponents,d.publisherPublicKeyDigest=c.publisherPublicKeyDigest,d.exclude=c.exclude,d.childSelector=c.childSelector,d.answerOriginKind=c.answerOriginKind,d.scope=c.scope,d.interestLifetime=c.interestLifetime):d.interestLifetime=4E3;if(null==this.host||null==this.port)if(null==this.getHostAndPort)console.log("ERROR: host OR port NOT SET");else{var e=
-this;this.connectAndExecute(function(){e.reconnectAndExpressInterest(d,b)})}else this.reconnectAndExpressInterest(d,b)};NDN.prototype.reconnectAndExpressInterest=function(a,b){if(this.transport.connectedHost!=this.host||this.transport.connectedPort!=this.port){var c=this;this.transport.connect(c,function(){c.expressInterestHelper(a,b)})}else this.expressInterestHelper(a,b)};
-NDN.prototype.expressInterestHelper=function(a,b){var c=encodeToBinaryInterest(a),d=this;if(null!=b){var e=new PITEntry(a,b);NDN.PITTable.push(e);b.pitEntry=e;var f=a.interestLifetime||4E3,g=function(){3<LOG&&console.log("Interest time out: "+a.name.to_uri());var h=NDN.PITTable.indexOf(e);0<=h&&NDN.PITTable.splice(h,1);b.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,new UpcallInfo(d,a,0,null))==Closure.RESULT_REEXPRESS&&(3<LOG&&console.log("Re-express interest: "+a.name.to_uri()),e.timerID=setTimeout(g,
-f),NDN.PITTable.push(e),d.transport.send(c))};e.timerID=setTimeout(g,f)}this.transport.send(c)};
-NDN.prototype.registerPrefix=function(a,b,c){var d=this,e=function(){if(null==d.ndndid){var e=new Interest(NDN.ndndIdFetcher);e.interestLifetime=4E3;3<LOG&&console.log("Expressing interest for ndndid from ndnd.");d.reconnectAndExpressInterest(e,new NDN.FetchNdndidClosure(d,a,b,c))}else d.registerPrefixHelper(a,b,c)};null==this.host||null==this.port?null==this.getHostAndPort?console.log("ERROR: host OR port NOT SET"):this.connectAndExecute(e):e()};
-NDN.FetchNdndidClosure=function(a,b,c,d){Closure.call(this);this.ndn=a;this.name=b;this.callerClosure=c;this.flag=d};
-NDN.FetchNdndidClosure.prototype.upcall=function(a,b){if(a==Closure.UPCALL_INTEREST_TIMED_OUT)return console.log("Timeout while requesting the ndndid.  Cannot registerPrefix for "+this.name.to_uri()+" ."),Closure.RESULT_OK;if(!(a==Closure.UPCALL_CONTENT||a==Closure.UPCALL_CONTENT_UNVERIFIED))return Closure.RESULT_ERR;var c=b.contentObject;!c.signedInfo||!c.signedInfo.publisher||!c.signedInfo.publisher.publisherPublicKeyDigest?console.log("ContentObject doesn't have a publisherPublicKeyDigest. Cannot set ndndid and registerPrefix for "+
-this.name.to_uri()+" ."):(3<LOG&&console.log("Got ndndid from ndnd."),this.ndn.ndndid=c.signedInfo.publisher.publisherPublicKeyDigest,3<LOG&&console.log(this.ndn.ndndid),this.ndn.registerPrefixHelper(this.name,this.callerClosure,this.flag));return Closure.RESULT_OK};
-NDN.prototype.registerPrefixHelper=function(a,b){var c=new ForwardingEntry("selfreg",a,null,null,3,2147483647),c=encodeForwardingEntry(c),d=new SignedInfo;d.setFields();c=new ContentObject(new Name,d,c,new Signature);c.sign();c=encodeToBinaryContentObject(c);c=new Name(["ndnx",this.ndndid,"selfreg",c]);c=new Interest(c);c.scope=1;3<LOG&&console.log("Send Interest registration packet.");d=new CSEntry(a.getName(),b);NDN.CSTable.push(d);this.transport.send(encodeToBinaryInterest(c))};
-NDN.prototype.onReceivedElement=function(a){3<LOG&&console.log("Complete element received. Length "+a.length+". Start decoding.");var b=new BinaryXMLDecoder(a);if(b.peekStartElement(NDNProtocolDTags.Interest))3<LOG&&console.log("Interest packet received."),a=new Interest,a.from_ndnb(b),3<LOG&&console.log(a),b=escape(a.name.getName()),3<LOG&&console.log(b),b=getEntryForRegisteredPrefix(b),null!=b&&(a=new UpcallInfo(this,a,0,null),b.closure.upcall(Closure.UPCALL_INTEREST,a)==Closure.RESULT_INTEREST_CONSUMED&&
-null!=a.contentObject&&this.transport.send(encodeToBinaryContentObject(a.contentObject)));else if(b.peekStartElement(NDNProtocolDTags.ContentObject)){if(3<LOG&&console.log("ContentObject packet received."),a=new ContentObject,a.from_ndnb(b),b=NDN.getEntryForExpressedInterest(a.name),null!=b){clearTimeout(b.timerID);var c=NDN.PITTable.indexOf(b);0<=c&&NDN.PITTable.splice(c,1);c=b.closure;if(!1==this.verify)c.upcall(Closure.UPCALL_CONTENT_UNVERIFIED,new UpcallInfo(this,b.interest,0,a));else{var d=function(a,
-b,c,d,e){this.contentObject=a;this.closure=b;this.keyName=c;this.sigHex=d;this.witness=e;Closure.call(this)},e=this;d.prototype.upcall=function(a,b){if(a==Closure.UPCALL_INTEREST_TIMED_OUT)console.log("In KeyFetchClosure.upcall: interest time out."),console.log(this.keyName.contentName.getName());else if(a==Closure.UPCALL_CONTENT){var c=decodeSubjectPublicKeyInfo(b.contentObject.content),d=!0==c.verifyByteArray(this.contentObject.rawSignatureData,this.witness,this.sigHex)?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD;
-this.closure.upcall(d,new UpcallInfo(e,null,0,this.contentObject));c=new KeyStoreEntry(h.keyName,c,(new Date).getTime());NDN.addKeyEntry(c)}else a==Closure.UPCALL_CONTENT_BAD&&console.log("In KeyFetchClosure.upcall: signature verification failed")};if(a.signedInfo&&a.signedInfo.locator&&a.signature){3<LOG&&console.log("Key verification...");var f=DataUtils.toHex(a.signature.signature).toLowerCase(),g=null;null!=a.signature.Witness&&(g=new Witness,g.decode(a.signature.Witness));var h=a.signedInfo.locator;
-if(h.type==KeyLocatorType.KEYNAME)if(3<LOG&&console.log("KeyLocator contains KEYNAME"),h.keyName.contentName.match(a.name))3<LOG&&console.log("Content is key itself"),d=decodeSubjectPublicKeyInfo(a.content),f=d.verifyByteArray(a.rawSignatureData,g,f),f=!0==f?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD,c.upcall(f,new UpcallInfo(this,b.interest,0,a));else{var j=NDN.getKeyByName(h.keyName);j?(3<LOG&&console.log("Local key cache hit"),d=j.rsaKey,f=d.verifyByteArray(a.rawSignatureData,g,f),f=!0==
-f?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD,c.upcall(f,new UpcallInfo(this,b.interest,0,a))):(3<LOG&&console.log("Fetch key according to keylocator"),a=new d(a,c,h.keyName,f,g),this.expressInterest(h.keyName.contentName.getPrefix(4),a))}else h.type==KeyLocatorType.KEY?(3<LOG&&console.log("Keylocator contains KEY"),d=decodeSubjectPublicKeyInfo(a.signedInfo.locator.publicKey),f=d.verifyByteArray(a.rawSignatureData,g,f),f=!0==f?Closure.UPCALL_CONTENT:Closure.UPCALL_CONTENT_BAD,c.upcall(Closure.UPCALL_CONTENT,
-new UpcallInfo(this,b.interest,0,a))):(a=h.certificate,console.log("KeyLocator contains CERT"),console.log(a))}}}}else console.log("Incoming packet is not Interest or ContentObject. Discard now.")};
-NDN.prototype.connectAndExecute=function(a){var b=this.getHostAndPort();if(null==b)console.log("ERROR: No more hosts from getHostAndPort"),this.host=null;else if(b.host==this.host&&b.port==this.port)console.log("ERROR: The host returned by getHostAndPort is not alive: "+this.host+":"+this.port);else{this.host=b.host;this.port=b.port;3<LOG&&console.log("Connect: trying host from getHostAndPort: "+this.host);b=new Interest(new Name("/"));b.interestLifetime=4E3;var c=this,d=setTimeout(function(){3<LOG&&
-console.log("Connect: timeout waiting for host "+c.host);c.connectAndExecute(a)},3E3);this.reconnectAndExpressInterest(b,new NDN.ConnectClosure(this,a,d))}};NDN.ConnectClosure=function(a,b,c){Closure.call(this);this.ndn=a;this.onConnected=b;this.timerID=c};NDN.ConnectClosure.prototype.upcall=function(a){if(!(a==Closure.UPCALL_CONTENT||a==Closure.UPCALL_CONTENT_UNVERIFIED))return Closure.RESULT_ERR;clearTimeout(this.timerID);this.ndn.readyStatus=NDN.OPENED;this.ndn.onopen();this.onConnected();return Closure.RESULT_OK};
-var BinaryXmlElementReader=function(a){this.elementListener=a;this.dataParts=[];this.structureDecoder=new BinaryXMLStructureDecoder};
-BinaryXmlElementReader.prototype.onReceivedData=function(a){for(;;)if(this.structureDecoder.seek(0),this.structureDecoder.findElementEnd(a)){this.dataParts.push(a.subarray(0,this.structureDecoder.offset));var b=DataUtils.concatArrays(this.dataParts);this.dataParts=[];try{this.elementListener.onReceivedElement(b)}catch(c){console.log("BinaryXmlElementReader: ignoring exception from onReceivedElement: "+c)}a=a.subarray(this.structureDecoder.offset,a.length);this.structureDecoder=new BinaryXMLStructureDecoder;
-if(0==a.length)break}else{this.dataParts.push(a);3<LOG&&console.log("Incomplete packet received. Length "+a.length+". Wait for more input.");break}};
+function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(0>=c)return!1;var d=b.shiftRight(c);a=a+1>>1;a>lowprimes.length&&(a=lowprimes.length);for(var e=nbi(),f=0;f<a;++f){e.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);var g=e.modPow(d,this);if(0!=g.compareTo(BigInteger.ONE)&&0!=g.compareTo(b)){for(var h=1;h++<c&&0!=g.compareTo(b);)if(g=g.modPowInt(2,this),0==g.compareTo(BigInteger.ONE))return!1;if(0!=g.compareTo(b))return!1}}return!0}
+BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.fromNumber=bnpFromNumber;BigInteger.prototype.bitwiseTo=bnpBitwiseTo;BigInteger.prototype.changeBit=bnpChangeBit;BigInteger.prototype.addTo=bnpAddTo;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo;BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo;
+BigInteger.prototype.modInt=bnpModInt;BigInteger.prototype.millerRabin=bnpMillerRabin;BigInteger.prototype.clone=bnClone;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.byteValue=bnByteValue;BigInteger.prototype.shortValue=bnShortValue;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.toByteArray=bnToByteArray;BigInteger.prototype.equals=bnEquals;BigInteger.prototype.min=bnMin;BigInteger.prototype.max=bnMax;BigInteger.prototype.and=bnAnd;BigInteger.prototype.or=bnOr;
+BigInteger.prototype.xor=bnXor;BigInteger.prototype.andNot=bnAndNot;BigInteger.prototype.not=bnNot;BigInteger.prototype.shiftLeft=bnShiftLeft;BigInteger.prototype.shiftRight=bnShiftRight;BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit;BigInteger.prototype.bitCount=bnBitCount;BigInteger.prototype.testBit=bnTestBit;BigInteger.prototype.setBit=bnSetBit;BigInteger.prototype.clearBit=bnClearBit;BigInteger.prototype.flipBit=bnFlipBit;BigInteger.prototype.add=bnAdd;BigInteger.prototype.subtract=bnSubtract;
+BigInteger.prototype.multiply=bnMultiply;BigInteger.prototype.divide=bnDivide;BigInteger.prototype.remainder=bnRemainder;BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder;BigInteger.prototype.modPow=bnModPow;BigInteger.prototype.modInverse=bnModInverse;BigInteger.prototype.pow=bnPow;BigInteger.prototype.gcd=bnGCD;BigInteger.prototype.isProbablePrime=bnIsProbablePrime;BigInteger.prototype.square=bnSquare;exports.BigInteger=BigInteger;module.exports=exports;
+var ASN1HEX=require("../contrib/securityLib/asn1hex-1.1.js").ASN1HEX,KJUR=require("../contrib/securityLib/crypto-1.0.js").KJUR,RSAKey=require("../contrib/securityLib/rsasign-1.2.js").RSAKey,b64tohex=require("../contrib/securityLib/base64.js").b64tohex,exports=ndn=ndn||{};
+exports.createHash=function(a){if("sha256"!=a)throw Error("createHash: unsupported algorithm.");a={};a.md=new KJUR.crypto.MessageDigest({alg:"sha256",prov:"cryptojs"});a.update=function(a){this.md.updateHex(a.toString("hex"))};a.digest=function(a){var c=this.md.digest();return"hex"==a?c:"base64"==a?(new Buffer(c,"hex")).toString("base64"):new Buffer(c,"hex")};return a};
+exports.createHmac=function(a,b){if("sha256"!==a)throw Error("createHmac: unsupported algorithm.");var c={};c.md=new KJUR.crypto.Mac({alg:"HmacSHA256",pass:{hex:b.toString("hex")}});c.update=function(a){this.md.updateHex(a.toString("hex"))};c.digest=function(a){var b=this.md.doFinal();return"hex"==a?b:"base64"==a?(new Buffer(b,"hex")).toString("base64"):new Buffer(b,"hex")};return c};
+exports.createSign=function(a){if("RSA-SHA256"!=a)throw Error("createSign: unsupported algorithm.");return{arr:[],update:function(a){this.arr.push(a)},sign:function(a){var c=new RSAKey;c.readPrivateKeyFromPEMString(a);a=new KJUR.crypto.Signature({alg:"SHA256withRSA",prov:"cryptojs/jsrsa"});a.initSign(c);for(c=0;c<this.arr.length;++c)a.updateHex(this.arr[c].toString("hex"));return new Buffer(a.sign(),"hex")}}};
+exports.createVerify=function(a){if("RSA-SHA256"!=a)throw Error("createSign: unsupported algorithm.");return{arr:[],update:function(a){this.arr.push(a)},verify:function(a,c){for(var d=a.split("\n"),e="",f=1;f<d.length-1;f++)e+=d[f];d=(new Buffer(e,"base64")).toString("hex");e=ASN1HEX.getPosArrayOfChildren_AtObj(d,0);2!=e.length?e=-1:(e=e[1],"03"!=d.substring(e,e+2)?e=-1:(e=ASN1HEX.getStartPosOfV_AtObj(d,e),e="00"!=d.substring(e,e+2)?-1:e+2));f=ASN1HEX.getPosArrayOfChildren_AtObj(d,e);2!=f.length?
+e=null:(e=ASN1HEX.getHexOfV_AtObj(d,f[0]),d=ASN1HEX.getHexOfV_AtObj(d,f[1]),f=new RSAKey,f.setPublic(e,d),e=f);d=new KJUR.crypto.Signature({alg:"SHA256withRSA",prov:"cryptojs/jsrsa"});d.initVerifyByPublicKey(e);for(e=0;e<this.arr.length;e++)d.updateHex(this.arr[e].toString("hex"));e=c.toString("hex");return d.verify(e)}}};exports.randomBytes=function(a){for(var b=new Buffer(a),c=0;c<a;++c)b[c]=Math.floor(256*Math.random());return b};
+exports.toByteArray=function(a){var b=[];b64tohex(a).replace(/(..)/g,function(a){b.push(parseInt(a,16))});return b};module.exports=exports;var lookup="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",base64js={};
+(function(a){function b(a){a=a.charCodeAt(0);if(a===d)return 62;if(a===e)return 63;if(a<f)return-1;if(a<f+10)return a-f+52;if(a<h+26)return a-h;if(a<g+26)return a-g+26}var c="undefined"!==typeof Uint8Array?Uint8Array:Array,d=43,e=47,f=48,g=97,h=65;a.toByteArray=function(a){function d(a){w[M++]=a}var e,f,g,h,w;if(0<a.length%4)throw Error("Invalid string. Length must be a multiple of 4");e=a.length;h="="===a.charAt(e-2)?2:"="===a.charAt(e-1)?1:0;w=new c(3*a.length/4-h);f=0<h?a.length-4:a.length;var M=
+0;for(e=0;e<f;e+=4)g=b(a.charAt(e))<<18|b(a.charAt(e+1))<<12|b(a.charAt(e+2))<<6|b(a.charAt(e+3)),d((g&16711680)>>16),d((g&65280)>>8),d(g&255);2===h?(g=b(a.charAt(e))<<2|b(a.charAt(e+1))>>4,d(g&255)):1===h&&(g=b(a.charAt(e))<<10|b(a.charAt(e+1))<<4|b(a.charAt(e+2))>>2,d(g>>8&255),d(g&255));return w};a.fromByteArray=function(a){var b,c=a.length%3,d="",e,f;b=0;for(f=a.length-c;b<f;b+=3)e=(a[b]<<16)+(a[b+1]<<8)+a[b+2],e=lookup.charAt(e>>18&63)+lookup.charAt(e>>12&63)+lookup.charAt(e>>6&63)+lookup.charAt(e&
+63),d+=e;switch(c){case 1:e=a[a.length-1];d+=lookup.charAt(e>>2);d+=lookup.charAt(e<<4&63);d+="==";break;case 2:e=(a[a.length-2]<<8)+a[a.length-1],d+=lookup.charAt(e>>10),d+=lookup.charAt(e>>4&63),d+=lookup.charAt(e<<2&63),d+="="}return d}})(base64js);
+var ieee={read:function(a,b,c,d,e){var f;f=8*e-d-1;var g=(1<<f)-1,h=g>>1,k=-7;e=c?e-1:0;var l=c?-1:1,m=a[b+e];e+=l;c=m&(1<<-k)-1;m>>=-k;for(k+=f;0<k;c=256*c+a[b+e],e+=l,k-=8);f=c&(1<<-k)-1;c>>=-k;for(k+=d;0<k;f=256*f+a[b+e],e+=l,k-=8);if(0===c)c=1-h;else{if(c===g)return f?NaN:Infinity*(m?-1:1);f+=Math.pow(2,d);c-=h}return(m?-1:1)*f*Math.pow(2,c-d)},write:function(a,b,c,d,e,f){var g,h=8*f-e-1,k=(1<<h)-1,l=k>>1,m=23===e?Math.pow(2,-24)-Math.pow(2,-77):0;f=d?0:f-1;var q=d?1:-1,p=0>b||0===b&&0>1/b?1:
+0;b=Math.abs(b);isNaN(b)||Infinity===b?(b=isNaN(b)?1:0,d=k):(d=Math.floor(Math.log(b)/Math.LN2),1>b*(g=Math.pow(2,-d))&&(d--,g*=2),b=1<=d+l?b+m/g:b+m*Math.pow(2,1-l),2<=b*g&&(d++,g/=2),d+l>=k?(b=0,d=k):1<=d+l?(b=(b*g-1)*Math.pow(2,e),d+=l):(b=b*Math.pow(2,l-1)*Math.pow(2,e),d=0));for(;8<=e;a[c+f]=b&255,f+=q,b/=256,e-=8);d=d<<e|b;for(h+=e;0<h;a[c+f]=d&255,f+=q,d/=256,h-=8);a[c+f-q]|=128*p}};exports.ieee=ieee;var base64=base64js,ieee754=require("./ieee754.js").ieee;exports.Buffer=Buffer;
+exports.SlowBuffer=Buffer;exports.INSPECT_MAX_BYTES=50;Buffer.poolSize=8192;Buffer._useTypedArrays=function(){try{var a=new ArrayBuffer(0),b=new Uint8Array(a);b.foo=function(){return 42};return 42===b.foo()&&"function"===typeof b.subarray}catch(c){return!1}}();
+function Buffer(a,b,c){if(!(this instanceof Buffer))return new Buffer(a,b,c);var d=typeof a;if("base64"===b&&"string"===d)for(a=Buffer.stringtrim(a);0!==a.length%4;)a+="=";var e;if("number"===d)e=Buffer.coerce(a);else if("string"===d)e=Buffer.byteLength(a,b);else if("object"===d)e=Buffer.coerce(a.length);else throw Error("First argument needs to be a number, array or string.");var f;Buffer._useTypedArrays?f=Buffer._augment(new Uint8Array(e)):(f=this,f.length=e,f._isBuffer=!0);if(Buffer._useTypedArrays&&
+"number"===typeof a.byteLength)f._set(a);else if(Buffer.isArrayish(a))if(Buffer.isBuffer(a))for(b=0;b<e;b++)f[b]=a.readUInt8(b);else for(b=0;b<e;b++)f[b]=(a[b]%256+256)%256;else if("string"===d)f.write(a,0,b);else if("number"===d&&!Buffer._useTypedArrays&&!c)for(b=0;b<e;b++)f[b]=0;return f}
+Buffer.isEncoding=function(a){switch(String(a).toLowerCase()){case "hex":case "utf8":case "utf-8":case "ascii":case "binary":case "base64":case "raw":case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":return!0;default:return!1}};Buffer.isBuffer=function(a){return!(null===a||void 0===a||!a._isBuffer)};
+Buffer.byteLength=function(a,b){var c;a=a.toString();switch(b||"utf8"){case "hex":c=a.length/2;break;case "utf8":case "utf-8":c=Buffer.utf8ToBytes(a).length;break;case "ascii":case "binary":case "raw":c=a.length;break;case "base64":c=Buffer.base64ToBytes(a).length;break;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":c=2*a.length;break;default:throw Error("Unknown encoding");}return c};
+Buffer.concat=function(a,b){Buffer.assert(Buffer.isArray(a),"Usage: Buffer.concat(list[, length])");if(0===a.length)return new Buffer(0);if(1===a.length)return a[0];var c;if(void 0===b)for(c=b=0;c<a.length;c++)b+=a[c].length;var d=new Buffer(b),e=0;for(c=0;c<a.length;c++){var f=a[c];f.copy(d,e);e+=f.length}return d};
+Buffer.compare=function(a,b){Buffer.assert(Buffer.isBuffer(a)&&Buffer.isBuffer(b),"Arguments must be Buffers");for(var c=a.length,d=b.length,e=0,f=Math.min(c,d);e<f&&a[e]===b[e];e++);e!==f&&(c=a[e],d=b[e]);return c<d?-1:d<c?1:0};
+Buffer.hexWrite=function(a,b,c,d){c=Number(c)||0;var e=a.length-c;d?(d=Number(d),d>e&&(d=e)):d=e;e=b.length;Buffer.assert(0===e%2,"Invalid hex string");d>e/2&&(d=e/2);for(e=0;e<d;e++){var f=parseInt(b.substr(2*e,2),16);Buffer.assert(!isNaN(f),"Invalid hex string");a[c+e]=f}return e};Buffer.utf8Write=function(a,b,c,d){return Buffer.blitBuffer(Buffer.utf8ToBytes(b),a,c,d)};Buffer.asciiWrite=function(a,b,c,d){return Buffer.blitBuffer(Buffer.asciiToBytes(b),a,c,d)};
+Buffer.binaryWrite=function(a,b,c,d){return Buffer.asciiWrite(a,b,c,d)};Buffer.base64Write=function(a,b,c,d){return Buffer.blitBuffer(Buffer.base64ToBytes(b),a,c,d)};Buffer.utf16leWrite=function(a,b,c,d){return Buffer.blitBuffer(Buffer.utf16leToBytes(b),a,c,d)};
+Buffer.prototype.write=function(a,b,c,d){if(isFinite(b))isFinite(c)||(d=c,c=void 0);else{var e=d;d=b;b=c;c=e}b=Number(b)||0;e=this.length-b;c?(c=Number(c),c>e&&(c=e)):c=e;d=String(d||"utf8").toLowerCase();switch(d){case "hex":a=Buffer.hexWrite(this,a,b,c);break;case "utf8":case "utf-8":a=Buffer.utf8Write(this,a,b,c);break;case "ascii":a=Buffer.asciiWrite(this,a,b,c);break;case "binary":a=Buffer.binaryWrite(this,a,b,c);break;case "base64":a=Buffer.base64Write(this,a,b,c);break;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":a=
+Buffer.utf16leWrite(this,a,b,c);break;default:throw Error("Unknown encoding");}return a};
+Buffer.prototype.toString=function(a,b,c){a=String(a||"utf8").toLowerCase();b=Number(b)||0;c=void 0===c?this.length:Number(c);if(c===b)return"";switch(a){case "hex":a=Buffer.hexSlice(this,b,c);break;case "utf8":case "utf-8":a=Buffer.utf8Slice(this,b,c);break;case "ascii":a=Buffer.asciiSlice(this,b,c);break;case "binary":a=Buffer.binarySlice(this,b,c);break;case "base64":a=Buffer.base64Slice(this,b,c);break;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":a=utf16leSlice(this,b,c);break;default:throw Error("Unknown encoding");
+}return a};Buffer.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};Buffer.prototype.equals=function(a){Buffer.assert(Buffer.isBuffer(a),"Argument must be a Buffer");return 0===Buffer.compare(this,a)};Buffer.prototype.compare=function(a){Buffer.assert(Buffer.isBuffer(a),"Argument must be a Buffer");return Buffer.compare(this,a)};
+Buffer.prototype.copy=function(a,b,c,d){c||(c=0);d||0===d||(d=this.length);b||(b=0);if(d!==c&&0!==a.length&&0!==this.length)if(Buffer.assert(d>=c,"sourceEnd < sourceStart"),Buffer.assert(0<=b&&b<a.length,"targetStart out of bounds"),Buffer.assert(0<=c&&c<this.length,"sourceStart out of bounds"),Buffer.assert(0<=d&&d<=this.length,"sourceEnd out of bounds"),d>this.length&&(d=this.length),a.length-b<d-c&&(d=a.length-b+c),d-=c,100>d||!Buffer._useTypedArrays)for(var e=0;e<d;e++)a[e+b]=this[e+c];else a._set(this.subarray(c,
+c+d),b)};Buffer.base64Slice=function(a,b,c){return 0===b&&c===a.length?base64.fromByteArray(a):base64.fromByteArray(a.slice(b,c))};Buffer.utf8Slice=function(a,b,c){var d="",e="";for(c=Math.min(a.length,c);b<c;b++)127>=a[b]?(d+=Buffer.decodeUtf8Char(e)+String.fromCharCode(a[b]),e=""):e+="%"+a[b].toString(16);return d+Buffer.decodeUtf8Char(e)};Buffer.asciiSlice=function(a,b,c){var d="";for(c=Math.min(a.length,c);b<c;b++)d+=String.fromCharCode(a[b]);return d};
+Buffer.binarySlice=function(a,b,c){return Buffer.asciiSlice(a,b,c)};Buffer.hexSlice=function(a,b,c){var d=a.length;if(!b||0>b)b=0;if(!c||0>c||c>d)c=d;for(d="";b<c;b++)d+=Buffer.toHex(a[b]);return d};function utf16leSlice(a,b,c){a=a.slice(b,c);b="";for(c=0;c<a.length;c+=2)b+=String.fromCharCode(a[c]+256*a[c+1]);return b}
+Buffer.prototype.slice=function(a,b){var c=this.length;a=Buffer.clamp(a,c,0);b=Buffer.clamp(b,c,c);if(Buffer._useTypedArrays)return Buffer._augment(this.subarray(a,b));for(var c=b-a,d=new Buffer(c,void 0,!0),e=0;e<c;e++)d[e]=this[e+a];return d};Buffer.prototype.get=function(a){console.log(".get() is deprecated. Access using array indexes instead.");return this.readUInt8(a)};
+Buffer.prototype.set=function(a,b){console.log(".set() is deprecated. Access using array indexes instead.");return this.writeUInt8(a,b)};Buffer.prototype.readUInt8=function(a,b){b||(Buffer.assert(void 0!==a&&null!==a,"missing offset"),Buffer.assert(a<this.length,"Trying to read beyond buffer length"));if(!(a>=this.length))return this[a]};
+Buffer.readUInt16=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b+1<a.length,"Trying to read beyond buffer length"));d=a.length;if(!(b>=d))return c?(c=a[b],b+1<d&&(c|=a[b+1]<<8)):(c=a[b]<<8,b+1<d&&(c|=a[b+1])),c};Buffer.prototype.readUInt16LE=function(a,b){return Buffer.readUInt16(this,a,!0,b)};Buffer.prototype.readUInt16BE=function(a,b){return Buffer.readUInt16(this,a,!1,b)};
+Buffer.readUInt32=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b+3<a.length,"Trying to read beyond buffer length"));d=a.length;if(!(b>=d)){var e;c?(b+2<d&&(e=a[b+2]<<16),b+1<d&&(e|=a[b+1]<<8),e|=a[b],b+3<d&&(e+=a[b+3]<<24>>>0)):(b+1<d&&(e=a[b+1]<<16),b+2<d&&(e|=a[b+2]<<8),b+3<d&&(e|=a[b+3]),e+=a[b]<<24>>>0);return e}};
+Buffer.prototype.readUInt32LE=function(a,b){return Buffer.readUInt32(this,a,!0,b)};Buffer.prototype.readUInt32BE=function(a,b){return Buffer.readUInt32(this,a,!1,b)};Buffer.prototype.readInt8=function(a,b){b||(Buffer.assert(void 0!==a&&null!==a,"missing offset"),Buffer.assert(a<this.length,"Trying to read beyond buffer length"));if(!(a>=this.length))return this[a]&128?-1*(255-this[a]+1):this[a]};
+Buffer.readInt16=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b+1<a.length,"Trying to read beyond buffer length"));if(!(b>=a.length))return a=Buffer.readUInt16(a,b,c,!0),a&32768?-1*(65535-a+1):a};Buffer.prototype.readInt16LE=function(a,b){return Buffer.readInt16(this,a,!0,b)};Buffer.prototype.readInt16BE=function(a,b){return Buffer.readInt16(this,a,!1,b)};
+Buffer.readInt32=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b+3<a.length,"Trying to read beyond buffer length"));if(!(b>=a.length))return a=Buffer.readUInt32(a,b,c,!0),a&2147483648?-1*(4294967295-a+1):a};Buffer.prototype.readInt32LE=function(a,b){return Buffer.readInt32(this,a,!0,b)};Buffer.prototype.readInt32BE=function(a,b){return Buffer.readInt32(this,a,!1,b)};
+Buffer.readFloat=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(b+3<a.length,"Trying to read beyond buffer length"));return ieee754.read(a,b,c,23,4)};Buffer.prototype.readFloatLE=function(a,b){return Buffer.readFloat(this,a,!0,b)};Buffer.prototype.readFloatBE=function(a,b){return Buffer.readFloat(this,a,!1,b)};
+Buffer.readDouble=function(a,b,c,d){d||(Buffer.assert("boolean"===typeof c,"missing or invalid endian"),Buffer.assert(b+7<a.length,"Trying to read beyond buffer length"));return ieee754.read(a,b,c,52,8)};Buffer.prototype.readDoubleLE=function(a,b){return Buffer.readDouble(this,a,!0,b)};Buffer.prototype.readDoubleBE=function(a,b){return Buffer.readDouble(this,a,!1,b)};
+Buffer.prototype.writeUInt8=function(a,b,c){c||(Buffer.assert(void 0!==a&&null!==a,"missing value"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b<this.length,"trying to write beyond buffer length"),Buffer.verifuint(a,255));if(!(b>=this.length))return this[b]=a,b+1};
+Buffer.writeUInt16=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+1<a.length,"trying to write beyond buffer length"),Buffer.verifuint(b,65535));var f=a.length;if(!(c>=f)){e=0;for(f=Math.min(f-c,2);e<f;e++)a[c+e]=(b&255<<8*(d?e:1-e))>>>8*(d?e:1-e);return c+2}};
+Buffer.prototype.writeUInt16LE=function(a,b,c){return Buffer.writeUInt16(this,a,b,!0,c)};Buffer.prototype.writeUInt16BE=function(a,b,c){return Buffer.writeUInt16(this,a,b,!1,c)};
+Buffer.writeUInt32=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+3<a.length,"trying to write beyond buffer length"),Buffer.verifuint(b,4294967295));var f=a.length;if(!(c>=f)){e=0;for(f=Math.min(f-c,4);e<f;e++)a[c+e]=b>>>8*(d?e:3-e)&255;return c+4}};Buffer.prototype.writeUInt32LE=function(a,b,c){return Buffer.writeUInt32(this,a,b,!0,c)};
+Buffer.prototype.writeUInt32BE=function(a,b,c){return Buffer.writeUInt32(this,a,b,!1,c)};Buffer.prototype.writeInt8=function(a,b,c){c||(Buffer.assert(void 0!==a&&null!==a,"missing value"),Buffer.assert(void 0!==b&&null!==b,"missing offset"),Buffer.assert(b<this.length,"Trying to write beyond buffer length"),Buffer.verifsint(a,127,-128));if(!(b>=this.length))return 0<=a?this.writeUInt8(a,b,c):this.writeUInt8(255+a+1,b,c),b+1};
+Buffer.writeInt16=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+1<a.length,"Trying to write beyond buffer length"),Buffer.verifsint(b,32767,-32768));if(!(c>=a.length))return 0<=b?Buffer.writeUInt16(a,b,c,d,e):Buffer.writeUInt16(a,65535+b+1,c,d,e),c+2};Buffer.prototype.writeInt16LE=function(a,b,c){return Buffer.writeInt16(this,a,b,!0,c)};
+Buffer.prototype.writeInt16BE=function(a,b,c){return Buffer.writeInt16(this,a,b,!1,c)};
+Buffer.writeInt32=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+3<a.length,"Trying to write beyond buffer length"),Buffer.verifsint(b,2147483647,-2147483648));if(!(c>=a.length))return 0<=b?Buffer.writeUInt32(a,b,c,d,e):Buffer.writeUInt32(a,4294967295+b+1,c,d,e),c+4};
+Buffer.prototype.writeInt32LE=function(a,b,c){return Buffer.writeInt32(this,a,b,!0,c)};Buffer.prototype.writeInt32BE=function(a,b,c){return Buffer.writeInt32(this,a,b,!1,c)};
+Buffer.writeFloat=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+3<a.length,"Trying to write beyond buffer length"),Buffer.verifIEEE754(b,3.4028234663852886E38,-3.4028234663852886E38));if(!(c>=a.length))return ieee754.write(a,b,c,d,23,4),c+4};Buffer.prototype.writeFloatLE=function(a,b,c){return Buffer.writeFloat(this,a,b,!0,c)};
+Buffer.prototype.writeFloatBE=function(a,b,c){return Buffer.writeFloat(this,a,b,!1,c)};Buffer.writeDouble=function(a,b,c,d,e){e||(Buffer.assert(void 0!==b&&null!==b,"missing value"),Buffer.assert("boolean"===typeof d,"missing or invalid endian"),Buffer.assert(void 0!==c&&null!==c,"missing offset"),Buffer.assert(c+7<a.length,"Trying to write beyond buffer length"),Buffer.verifIEEE754(b,1.7976931348623157E308,-1.7976931348623157E308));if(!(c>=a.length))return ieee754.write(a,b,c,d,52,8),c+8};
+Buffer.prototype.writeDoubleLE=function(a,b,c){return Buffer.writeDouble(this,a,b,!0,c)};Buffer.prototype.writeDoubleBE=function(a,b,c){return Buffer.writeDouble(this,a,b,!1,c)};
+Buffer.prototype.fill=function(a,b,c){a||(a=0);b||(b=0);c||(c=this.length);Buffer.assert(c>=b,"end < start");if(c!==b&&0!==this.length){Buffer.assert(0<=b&&b<this.length,"start out of bounds");Buffer.assert(0<=c&&c<=this.length,"end out of bounds");if("number"===typeof a)for(;b<c;b++)this[b]=a;else{a=Buffer.utf8ToBytes(a.toString());for(var d=a.length;b<c;b++)this[b]=a[b%d]}return this}};
+Buffer.prototype.inspect=function(){for(var a=[],b=this.length,c=0;c<b;c++)if(a[c]=Buffer.toHex(this[c]),c===exports.INSPECT_MAX_BYTES){a[c+1]="...";break}return"<Buffer "+a.join(" ")+">"};Buffer.prototype.toArrayBuffer=function(){if("undefined"!==typeof Uint8Array){if(Buffer._useTypedArrays)return(new Buffer(this)).buffer;for(var a=new Uint8Array(this.length),b=0,c=a.length;b<c;b+=1)a[b]=this[b];return a.buffer}throw Error("Buffer.toArrayBuffer not supported in this browser");};var BP=Buffer.prototype;
+Buffer._augment=function(a){a._isBuffer=!0;a._get=a.get;a._set=a.set;a.get=BP.get;a.set=BP.set;a.write=BP.write;a.toString=BP.toString;a.toLocaleString=BP.toString;a.toJSON=BP.toJSON;a.equals=BP.equals;a.compare=BP.compare;a.copy=BP.copy;a.slice=BP.slice;a.readUInt8=BP.readUInt8;a.readUInt16LE=BP.readUInt16LE;a.readUInt16BE=BP.readUInt16BE;a.readUInt32LE=BP.readUInt32LE;a.readUInt32BE=BP.readUInt32BE;a.readInt8=BP.readInt8;a.readInt16LE=BP.readInt16LE;a.readInt16BE=BP.readInt16BE;a.readInt32LE=BP.readInt32LE;
+a.readInt32BE=BP.readInt32BE;a.readFloatLE=BP.readFloatLE;a.readFloatBE=BP.readFloatBE;a.readDoubleLE=BP.readDoubleLE;a.readDoubleBE=BP.readDoubleBE;a.writeUInt8=BP.writeUInt8;a.writeUInt16LE=BP.writeUInt16LE;a.writeUInt16BE=BP.writeUInt16BE;a.writeUInt32LE=BP.writeUInt32LE;a.writeUInt32BE=BP.writeUInt32BE;a.writeInt8=BP.writeInt8;a.writeInt16LE=BP.writeInt16LE;a.writeInt16BE=BP.writeInt16BE;a.writeInt32LE=BP.writeInt32LE;a.writeInt32BE=BP.writeInt32BE;a.writeFloatLE=BP.writeFloatLE;a.writeFloatBE=
+BP.writeFloatBE;a.writeDoubleLE=BP.writeDoubleLE;a.writeDoubleBE=BP.writeDoubleBE;a.fill=BP.fill;a.inspect=BP.inspect;a.toArrayBuffer=BP.toArrayBuffer;return a};Buffer.stringtrim=function(a){return a.trim?a.trim():a.replace(/^\s+|\s+$/g,"")};Buffer.clamp=function(a,b,c){if("number"!==typeof a)return c;a=~~a;if(a>=b)return b;if(0<=a)return a;a+=b;return 0<=a?a:0};Buffer.coerce=function(a){a=~~Math.ceil(+a);return 0>a?0:a};
+Buffer.isArray=function(a){return(Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)})(a)};Buffer.isArrayish=function(a){return Buffer.isArray(a)||Buffer.isBuffer(a)||a&&"object"===typeof a&&"number"===typeof a.length};Buffer.toHex=function(a){return 16>a?"0"+a.toString(16):a.toString(16)};
+Buffer.utf8ToBytes=function(a){for(var b=[],c=0;c<a.length;c++){var d=a.charCodeAt(c);if(127>=d)b.push(d);else{var e=c;55296<=d&&57343>=d&&c++;d=encodeURIComponent(a.slice(e,c+1)).substr(1).split("%");for(e=0;e<d.length;e++)b.push(parseInt(d[e],16))}}return b};Buffer.asciiToBytes=function(a){for(var b=[],c=0;c<a.length;c++)b.push(a.charCodeAt(c)&255);return b};Buffer.utf16leToBytes=function(a){for(var b,c,d=[],e=0;e<a.length;e++)b=a.charCodeAt(e),c=b>>8,b%=256,d.push(b),d.push(c);return d};
+Buffer.base64ToBytes=function(a){return base64.toByteArray(a)};Buffer.blitBuffer=function(a,b,c,d){for(var e=0;e<d&&!(e+c>=b.length||e>=a.length);e++)b[e+c]=a[e];return e};Buffer.decodeUtf8Char=function(a){try{return decodeURIComponent(a)}catch(b){return String.fromCharCode(65533)}};
+Buffer.verifuint=function(a,b){Buffer.assert("number"===typeof a,"cannot write a non-number as a number");Buffer.assert(0<=a,"specified a negative value for writing an unsigned value");Buffer.assert(a<=b,"value is larger than maximum value for type");Buffer.assert(Math.floor(a)===a,"value has a fractional component")};
+Buffer.verifsint=function(a,b,c){Buffer.assert("number"===typeof a,"cannot write a non-number as a number");Buffer.assert(a<=b,"value larger than maximum allowed value");Buffer.assert(a>=c,"value smaller than minimum allowed value");Buffer.assert(Math.floor(a)===a,"value has a fractional component")};Buffer.verifIEEE754=function(a,b,c){Buffer.assert("number"===typeof a,"cannot write a non-number as a number");Buffer.assert(a<=b,"value larger than maximum allowed value");Buffer.assert(a>=c,"value smaller than minimum allowed value")};
+Buffer.assert=function(a,b){if(!a)throw Error(b||"Failed assertion");};var Log=function(){};exports.Log=Log;Log.LOG=0;var printStackTrace=require("../../contrib/stacktrace/stacktrace.js").printStackTrace,NdnCommon={};exports.NdnCommon=NdnCommon;NdnCommon.MAX_NDN_PACKET_SIZE=8800;NdnCommon.getErrorWithStackTrace=function(a){return a+"\n"+printStackTrace({e:a}).join("\n")};
+NdnCommon.checkIndexedDb=function(a){try{var b=new Dexie("test-Dexie-support");b.version(1).stores({});b.open();setTimeout(function(){try{a(b.isOpen())}catch(c){a(!1)}},200)}catch(c){a(!1)}};var NdnCommon=require("./ndn-common.js").NdnCommon,ExponentialReExpress=function(a,b,c,d){d=d||{};this.face=a;this.callerOnData=b;this.callerOnTimeout=c;this.maxInterestLifetime=d.maxInterestLifetime||16E3};exports.ExponentialReExpress=ExponentialReExpress;
+ExponentialReExpress.makeOnTimeout=function(a,b,c,d){var e=new ExponentialReExpress(a,b,c,d);return function(a){e.onTimeout(a)}};
+ExponentialReExpress.prototype.onTimeout=function(a){var b=a.getInterestLifetimeMilliseconds();if(null==b){if(this.callerOnTimeout)try{this.callerOnTimeout(a)}catch(c){console.log("Error in onTimeout: "+NdnCommon.getErrorWithStackTrace(c))}}else if(b*=2,b>this.maxInterestLifetime){if(this.callerOnTimeout)try{this.callerOnTimeout(a)}catch(d){console.log("Error in onTimeout: "+NdnCommon.getErrorWithStackTrace(d))}}else{a=a.clone();a.setInterestLifetimeMilliseconds(b);var e=this;this.face.expressInterest(a,
+this.callerOnData,function(a){e.onTimeout(a)})}};var Blob=function Blob(b,c){null==c&&(c=!0);null==b?this.buffer=null:"object"===typeof b&&b instanceof Blob?this.buffer=b.buffer:"string"===typeof b?this.buffer=new Buffer(b,"utf8"):c?this.buffer=new Buffer(b):Buffer.isBuffer(b)?this.buffer=b:this.buffer=new Buffer(b);this.length=null!=this.buffer?this.buffer.length:0};exports.Blob=Blob;Blob.prototype.size=function(){return null!=this.buffer?this.buffer.length:0};Blob.prototype.buf=function(){return this.buffer};
+Blob.prototype.isNull=function(){return null==this.buffer};Blob.prototype.toHex=function(){return null==this.buffer?"":this.buffer.toString("hex")};Blob.prototype.toString=function(){return null==this.buffer?"":this.buffer.toString("utf8")};Blob.prototype.equals=function(a){if(this.isNull())return a.isNull();if(a.isNull()||this.buffer.length!=a.buffer.length)return!1;for(var b=0;b<this.buffer.length;++b)if(this.buffer[b]!=a.buffer[b])return!1;return!0};
+var Blob=require("./blob.js").Blob,SignedBlob=function SignedBlob(b,c,d){Blob.call(this,b);null==this.buffer?this.signedPortionEndOffset=this.signedPortionBeginOffset=0:"object"===typeof b&&b instanceof SignedBlob?(this.signedPortionBeginOffset=null==c?b.signedPortionBeginOffset:c,this.signedPortionEndOffset=null==d?b.signedPortionEndOffset:d):(this.signedPortionBeginOffset=c||0,this.signedPortionEndOffset=d||0);this.signedBuffer=null==this.buffer?null:this.buffer.slice(this.signedPortionBeginOffset,
+this.signedPortionEndOffset)};SignedBlob.prototype=new Blob;SignedBlob.prototype.name="SignedBlob";exports.SignedBlob=SignedBlob;SignedBlob.prototype.signedSize=function(){return null!=this.signedBuffer?this.signedBuffer.length:0};SignedBlob.prototype.signedBuf=function(){return this.signedBuffer};SignedBlob.prototype.getSignedPortionBeginOffset=function(){return this.signedPortionBeginOffset};SignedBlob.prototype.getSignedPortionEndOffset=function(){return this.signedPortionEndOffset};
+var DynamicBuffer=function(a){a||(a=16);this.array=new Buffer(a)};exports.DynamicBuffer=DynamicBuffer;DynamicBuffer.prototype.ensureLength=function(a){if(!(this.array.length>=a)){var b=2*this.array.length;a>b&&(b=a);a=new Buffer(b);this.array.copy(a);this.array=a}};DynamicBuffer.prototype.copy=function(a,b){this.ensureLength(a.length+b);Buffer.isBuffer(a)?a.copy(this.array,b):(new Buffer(a)).copy(this.array,b);return b+a.length};
+DynamicBuffer.prototype.ensureLengthFromBack=function(a){if(!(this.array.length>=a)){var b=2*this.array.length;a>b&&(b=a);a=new Buffer(b);this.array.copy(a,a.length-this.array.length);this.array=a}};DynamicBuffer.prototype.copyFromBack=function(a,b){this.ensureLengthFromBack(b);Buffer.isBuffer(a)?a.copy(this.array,this.array.length-b):(new Buffer(a)).copy(this.array,this.array.length-b)};DynamicBuffer.prototype.slice=function(a,b){return void 0==b?this.array.slice(a):this.array.slice(a,b)};
+var ChangeCounter=function(a){this.target=a;this.changeCount=null==a?0:a.getChangeCount()};exports.ChangeCounter=ChangeCounter;ChangeCounter.prototype.get=function(){return this.target};ChangeCounter.prototype.set=function(a){this.target=a;this.changeCount=null==a?0:a.getChangeCount()};ChangeCounter.prototype.checkChanged=function(){if(null==this.target)return!1;var a=this.target.getChangeCount();return this.changeCount!=a?(this.changeCount=a,!0):!1};
+var NdnCommon=require("./ndn-common.js").NdnCommon,SyncPromise=function(a,b){this.value=a;this.isRejected=b};exports.SyncPromise=SyncPromise;SyncPromise.prototype.then=function(a,b){if(this.isRejected)if(b)try{return b(this.value)}catch(c){return new SyncPromise(c,!0)}else return this;else if(a)try{return a(this.value)}catch(d){return new SyncPromise(d,!0)}else return this};SyncPromise.prototype["catch"]=function(a){return this.then(void 0,a)};
+SyncPromise.resolve=function(a){return new SyncPromise(a,!1)};SyncPromise.reject=function(a){return new SyncPromise(a,!0)};SyncPromise.getValue=function(a){if(a instanceof SyncPromise){if(a.isRejected)throw a.value;return a.value}throw Error("Cannot return immediately because promise is not a SyncPromise");};
+SyncPromise.complete=function(a,b,c){var d;c?d=b:(c=b,d=null);if(a)c.then(function(b){try{a(b)}catch(c){console.log("Error in onComplete: "+NdnCommon.getErrorWithStackTrace(c))}},function(a){if(d)try{d(a)}catch(b){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(b))}else{if(c instanceof SyncPromise)throw a;console.log("Uncaught exception from a Promise: "+NdnCommon.getErrorWithStackTrace(a))}});else return SyncPromise.getValue(c)};var DataUtils={};exports.DataUtils=DataUtils;
+DataUtils.keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";DataUtils.stringtoBase64=function(a){var b="",c,d,e="",f,g,h="",k=0;do c=a.charCodeAt(k++),d=a.charCodeAt(k++),e=a.charCodeAt(k++),f=c>>2,c=(c&3)<<4|d>>4,g=(d&15)<<2|e>>6,h=e&63,isNaN(d)?g=h=64:isNaN(e)&&(h=64),b=b+DataUtils.keyStr.charAt(f)+DataUtils.keyStr.charAt(c)+DataUtils.keyStr.charAt(g)+DataUtils.keyStr.charAt(h);while(k<a.length);return b};
+DataUtils.base64toString=function(a){var b="",c,d,e="",f,g="",h=0;/[^A-Za-z0-9\+\/\=]/g.exec(a)&&alert("There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\nExpect errors in decoding.");a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do c=DataUtils.keyStr.indexOf(a.charAt(h++)),d=DataUtils.keyStr.indexOf(a.charAt(h++)),f=DataUtils.keyStr.indexOf(a.charAt(h++)),g=DataUtils.keyStr.indexOf(a.charAt(h++)),c=c<<2|d>>4,d=(d&15)<<4|f>>2,e=(f&3)<<6|g,
+b+=String.fromCharCode(c),64!=f&&(b+=String.fromCharCode(d)),64!=g&&(b+=String.fromCharCode(e));while(h<a.length);return b};DataUtils.toHex=function(a){return a.toString("hex")};DataUtils.stringToHex=function(a){for(var b="",c=0;c<a.length;++c)var d=a.charCodeAt(c),b=b+((16>d?"0":"")+d.toString(16));return b};DataUtils.toString=function(a){return a.toString("binary")};DataUtils.toNumbers=function(a){return new Buffer(a,"hex")};
+DataUtils.hexToRawString=function(a){if("string"==typeof a){var b="";a.replace(/(..)/g,function(a){b+=String.fromCharCode(parseInt(a,16))});return b}};DataUtils.toNumbersFromString=function(a){return new Buffer(a,"binary")};DataUtils.toNumbersIfString=function(a){return"string"===typeof a?new Buffer(a,"binary"):a};DataUtils.stringToUtf8Array=function(a){return new Buffer(a,"utf8")};DataUtils.concatArrays=function(a){return Buffer.concat(a)};
+DataUtils.decodeUtf8=function(a){for(var b="",c=0,d=0,e=0;c<a.length;)if(d=a.charCodeAt(c),128>d)b+=String.fromCharCode(d),c++;else if(191<d&&224>d)e=a.charCodeAt(c+1),b+=String.fromCharCode((d&31)<<6|e&63),c+=2;else var e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b=b+String.fromCharCode((d&15)<<12|(e&63)<<6|f&63),c=c+3;return b};
+DataUtils.arraysEqual=function(a,b){if(!a.slice)throw Error("DataUtils.arraysEqual: a1 is not an array");if(!b.slice)throw Error("DataUtils.arraysEqual: a2 is not an array");if(a.length!=b.length)return!1;for(var c=0;c<a.length;++c)if(a[c]!=b[c])return!1;return!0};DataUtils.bigEndianToUnsignedInt=function(a){for(var b=0,c=0;c<a.length;++c)b*=256,b+=a[c];return b};
+DataUtils.nonNegativeIntToBigEndian=function(a){a=Math.round(a);if(0>=a)return new Buffer(0);for(var b=new Buffer(8),c=0;0!=a;)++c,b[8-c]=a&255,a=Math.floor(a/256);return b.slice(8-c,8)};DataUtils.shuffle=function(a){for(var b=a.length-1;1<=b;--b){var c=Math.floor(Math.random()*(b+1)),d=a[b];a[b]=a[c];a[c]=d}};DataUtils.privateKeyPemToDer=function(a){a=a.split("\n");for(var b="",c=1;c<a.length-1;c++)b+=a[c];return new Buffer(b,"base64")};
+function DecodingException(a){if(a)return a.__proto__=DecodingException.prototype,a}DecodingException.prototype=Error();DecodingException.prototype.name="DecodingException";exports.DecodingException=DecodingException;var Tlv=function(){};exports.Tlv=Tlv;Tlv.Interest=5;Tlv.Data=6;Tlv.Name=7;Tlv.ImplicitSha256DigestComponent=1;Tlv.NameComponent=8;Tlv.Selectors=9;Tlv.Nonce=10;Tlv.InterestLifetime=12;Tlv.MinSuffixComponents=13;Tlv.MaxSuffixComponents=14;Tlv.PublisherPublicKeyLocator=15;Tlv.Exclude=16;
+Tlv.ChildSelector=17;Tlv.MustBeFresh=18;Tlv.Any=19;Tlv.MetaInfo=20;Tlv.Content=21;Tlv.SignatureInfo=22;Tlv.SignatureValue=23;Tlv.ContentType=24;Tlv.FreshnessPeriod=25;Tlv.FinalBlockId=26;Tlv.SignatureType=27;Tlv.KeyLocator=28;Tlv.KeyLocatorDigest=29;Tlv.SelectedDelegation=32;Tlv.FaceInstance=128;Tlv.ForwardingEntry=129;Tlv.StatusResponse=130;Tlv.Action=131;Tlv.FaceID=132;Tlv.IPProto=133;Tlv.Host=134;Tlv.Port=135;Tlv.MulticastInterface=136;Tlv.MulticastTTL=137;Tlv.ForwardingFlags=138;
+Tlv.StatusCode=139;Tlv.StatusText=140;Tlv.SignatureType_DigestSha256=0;Tlv.SignatureType_SignatureSha256WithRsa=1;Tlv.SignatureType_SignatureSha256WithEcdsa=3;Tlv.SignatureType_SignatureHmacWithSha256=4;Tlv.ContentType_Default=0;Tlv.ContentType_Link=1;Tlv.ContentType_Key=2;Tlv.NfdCommand_ControlResponse=101;Tlv.NfdCommand_StatusCode=102;Tlv.NfdCommand_StatusText=103;Tlv.ControlParameters_ControlParameters=104;Tlv.ControlParameters_FaceId=105;Tlv.ControlParameters_Uri=114;
+Tlv.ControlParameters_LocalControlFeature=110;Tlv.ControlParameters_Origin=111;Tlv.ControlParameters_Cost=106;Tlv.ControlParameters_Flags=108;Tlv.ControlParameters_Strategy=107;Tlv.ControlParameters_ExpirationPeriod=109;Tlv.LpPacket_LpPacket=100;Tlv.LpPacket_Fragment=80;Tlv.LpPacket_Sequence=81;Tlv.LpPacket_FragIndex=82;Tlv.LpPacket_FragCount=83;Tlv.LpPacket_Nack=800;Tlv.LpPacket_NackReason=801;Tlv.LpPacket_NextHopFaceId=816;Tlv.LpPacket_IncomingFaceId=817;Tlv.LpPacket_CachePolicy=820;
+Tlv.LpPacket_CachePolicyType=821;Tlv.LpPacket_IGNORE_MIN=800;Tlv.LpPacket_IGNORE_MAX=959;Tlv.Link_Preference=30;Tlv.Link_Delegation=31;Tlv.Encrypt_EncryptedContent=130;Tlv.Encrypt_EncryptionAlgorithm=131;Tlv.Encrypt_EncryptedPayload=132;Tlv.Encrypt_InitialVector=133;Tlv.Encrypt_StartDate=134;Tlv.Encrypt_EndDate=135;Tlv.Encrypt_IntervalStartHour=136;Tlv.Encrypt_IntervalEndHour=137;Tlv.Encrypt_NRepeats=138;Tlv.Encrypt_RepeatUnit=139;Tlv.Encrypt_RepetitiveInterval=140;Tlv.Encrypt_WhiteIntervalList=141;
+Tlv.Encrypt_BlackIntervalList=142;Tlv.Encrypt_Schedule=143;Tlv.getHighBytes=function(a){return(a-a%4294967296)/4294967296};var DynamicBuffer=require("../../util/dynamic-buffer.js").DynamicBuffer,Tlv=require("./tlv.js").Tlv,TlvEncoder=function(a){this.output=new DynamicBuffer(a||16);this.length=0};exports.TlvEncoder=TlvEncoder;TlvEncoder.prototype.getLength=function(){return this.length};
+TlvEncoder.prototype.writeVarNumber=function(a){if(253>a)this.length+=1,this.output.ensureLengthFromBack(this.length),this.output.array[this.output.array.length-this.length]=a&255;else if(65535>=a){this.length+=3;this.output.ensureLengthFromBack(this.length);var b=this.output.array.length-this.length;this.output.array[b]=253;this.output.array[b+1]=a>>8&255;this.output.array[b+2]=a&255}else if(4294967295>=a)this.length+=5,this.output.ensureLengthFromBack(this.length),b=this.output.array.length-this.length,
+this.output.array[b]=254,this.output.array[b+1]=a>>24&255,this.output.array[b+2]=a>>16&255,this.output.array[b+3]=a>>8&255,this.output.array[b+4]=a&255;else{this.length+=9;this.output.ensureLengthFromBack(this.length);b=this.output.array.length-this.length;this.output.array[b]=255;var c=Tlv.getHighBytes(a);this.output.array[b+1]=c>>24&255;this.output.array[b+2]=c>>16&255;this.output.array[b+3]=c>>8&255;this.output.array[b+4]=c&255;this.output.array[b+5]=a>>24&255;this.output.array[b+6]=a>>16&255;
+this.output.array[b+7]=a>>8&255;this.output.array[b+8]=a&255}};TlvEncoder.prototype.writeTypeAndLength=function(a,b){this.writeVarNumber(b);this.writeVarNumber(a)};
+TlvEncoder.prototype.writeNonNegativeInteger=function(a){if(0>a)throw Error("TLV integer value may not be negative");a=Math.round(a);if(255>=a)this.length+=1,this.output.ensureLengthFromBack(this.length),this.output.array[this.output.array.length-this.length]=a&255;else if(65535>=a){this.length+=2;this.output.ensureLengthFromBack(this.length);var b=this.output.array.length-this.length;this.output.array[b]=a>>8&255;this.output.array[b+1]=a&255}else if(4294967295>=a)this.length+=4,this.output.ensureLengthFromBack(this.length),
+b=this.output.array.length-this.length,this.output.array[b]=a>>24&255,this.output.array[b+1]=a>>16&255,this.output.array[b+2]=a>>8&255,this.output.array[b+3]=a&255;else{this.length+=8;this.output.ensureLengthFromBack(this.length);var b=this.output.array.length-this.length,c=Tlv.getHighBytes(a);this.output.array[b]=c>>24&255;this.output.array[b+1]=c>>16&255;this.output.array[b+2]=c>>8&255;this.output.array[b+3]=c&255;this.output.array[b+4]=a>>24&255;this.output.array[b+5]=a>>16&255;this.output.array[b+
+6]=a>>8&255;this.output.array[b+7]=a&255}};TlvEncoder.prototype.writeNonNegativeIntegerTlv=function(a,b){var c=this.length;this.writeNonNegativeInteger(b);this.writeTypeAndLength(a,this.length-c)};TlvEncoder.prototype.writeOptionalNonNegativeIntegerTlv=function(a,b){null!=b&&0<=b&&this.writeNonNegativeIntegerTlv(a,b)};TlvEncoder.prototype.writeBuffer=function(a){null!=a&&(this.length+=a.length,this.output.copyFromBack(a,this.length))};
+TlvEncoder.prototype.writeBlobTlv=function(a,b){null==b?this.writeTypeAndLength(a,0):(this.writeBuffer(b),this.writeTypeAndLength(a,b.length))};TlvEncoder.prototype.writeOptionalBlobTlv=function(a,b){null!=b&&0<b.length&&this.writeBlobTlv(a,b)};TlvEncoder.prototype.getOutput=function(){return this.output.array.slice(this.output.array.length-this.length)};var DecodingException=require("../decoding-exception.js").DecodingException,TlvDecoder=function(a){this.input=a;this.offset=0};
+exports.TlvDecoder=TlvDecoder;TlvDecoder.prototype.readVarNumber=function(){var a=this.input[this.offset];this.offset+=1;return 253>a?a:this.readExtendedVarNumber(a)};
+TlvDecoder.prototype.readExtendedVarNumber=function(a){253==a?(a=(this.input[this.offset]<<8)+this.input[this.offset+1],this.offset+=2):254==a?(a=Math.abs(this.input[this.offset]<<24)+(this.input[this.offset+1]<<16)+(this.input[this.offset+2]<<8)+this.input[this.offset+3],this.offset+=4):(a=4294967296*(Math.abs(this.input[this.offset]<<24)+(this.input[this.offset+1]<<16)+(this.input[this.offset+2]<<8)+this.input[this.offset+3])+(this.input[this.offset+4]<<24)+(this.input[this.offset+5]<<16)+(this.input[this.offset+
+6]<<8)+this.input[this.offset+7],this.offset+=8);return a};TlvDecoder.prototype.readTypeAndLength=function(a){if(this.readVarNumber()!=a)throw new DecodingException(Error("Did not get the expected TLV type"));a=this.readVarNumber();if(this.offset+a>this.input.length)throw new DecodingException(Error("TLV length exceeds the buffer length"));return a};TlvDecoder.prototype.readNestedTlvsStart=function(a){return this.readTypeAndLength(a)+this.offset};
+TlvDecoder.prototype.finishNestedTlvs=function(a){if(this.offset!=a){for(;this.offset<a;){this.readVarNumber();var b=this.readVarNumber();this.offset+=b;if(this.offset>this.input.length)throw new DecodingException(Error("TLV length exceeds the buffer length"));}if(this.offset!=a)throw new DecodingException(Error("TLV length does not equal the total length of the nested TLVs"));}};
+TlvDecoder.prototype.peekType=function(a,b){if(this.offset>=b)return!1;var c=this.offset,d=this.readVarNumber();this.offset=c;return d==a};
+TlvDecoder.prototype.readNonNegativeInteger=function(a){var b;if(1==a)b=this.input[this.offset];else if(2==a)b=(this.input[this.offset]<<8)+this.input[this.offset+1];else if(4==a)b=Math.abs(this.input[this.offset]<<24)+(this.input[this.offset+1]<<16)+(this.input[this.offset+2]<<8)+this.input[this.offset+3];else if(8==a)b=4294967296*(Math.abs(this.input[this.offset]<<24)+(this.input[this.offset+1]<<16)+(this.input[this.offset+2]<<8)+this.input[this.offset+3])+Math.abs(this.input[this.offset+4]<<24)+
+(this.input[this.offset+5]<<16)+(this.input[this.offset+6]<<8)+this.input[this.offset+7];else throw new DecodingException(Error("Invalid length for a TLV nonNegativeInteger"));this.offset+=a;return b};TlvDecoder.prototype.readNonNegativeIntegerTlv=function(a){a=this.readTypeAndLength(a);return this.readNonNegativeInteger(a)};TlvDecoder.prototype.readOptionalNonNegativeIntegerTlv=function(a,b){return this.peekType(a,b)?this.readNonNegativeIntegerTlv(a):null};
+TlvDecoder.prototype.readBlobTlv=function(a){a=this.readTypeAndLength(a);var b=this.input.slice(this.offset,this.offset+a);this.offset+=a;return b};TlvDecoder.prototype.readOptionalBlobTlv=function(a,b){return this.peekType(a,b)?this.readBlobTlv(a):null};TlvDecoder.prototype.readBooleanTlv=function(a,b){if(this.peekType(a,b)){var c=this.readTypeAndLength(a);this.offset+=c;return!0}return!1};TlvDecoder.prototype.getOffset=function(){return this.offset};
+TlvDecoder.prototype.seek=function(a){this.offset=a};TlvDecoder.prototype.getSlice=function(a,b){return this.input.slice(a,b)};var TlvDecoder=require("./tlv-decoder.js").TlvDecoder,TlvStructureDecoder=function TlvStructureDecoder(){this.gotElementEnd_=!1;this.offset_=0;this.state_=TlvStructureDecoder.READ_TYPE;this.headerLength_=0;this.useHeaderBuffer_=!1;this.headerBuffer_=new Buffer(8);this.nBytesToRead_=0};exports.TlvStructureDecoder=TlvStructureDecoder;TlvStructureDecoder.READ_TYPE=0;
+TlvStructureDecoder.READ_TYPE_BYTES=1;TlvStructureDecoder.READ_LENGTH=2;TlvStructureDecoder.READ_LENGTH_BYTES=3;TlvStructureDecoder.READ_VALUE_BYTES=4;
+TlvStructureDecoder.prototype.findElementEnd=function(a){if(this.gotElementEnd_)return!0;for(var b=new TlvDecoder(a);;){if(this.offset_>=a.length)return!1;if(this.state_==TlvStructureDecoder.READ_TYPE){var c=a[this.offset_];this.offset_+=1;253>c?this.state_=TlvStructureDecoder.READ_LENGTH:(this.nBytesToRead_=253==c?2:254==c?4:8,this.state_=TlvStructureDecoder.READ_TYPE_BYTES)}else if(this.state_==TlvStructureDecoder.READ_TYPE_BYTES){c=a.length-this.offset_;if(c<this.nBytesToRead_)return this.offset_+=
+c,this.nBytesToRead_-=c,!1;this.offset_+=this.nBytesToRead_;this.state_=TlvStructureDecoder.READ_LENGTH}else if(this.state_==TlvStructureDecoder.READ_LENGTH)if(c=a[this.offset_],this.offset_+=1,253>c){this.nBytesToRead_=c;if(0==this.nBytesToRead_)return this.gotElementEnd_=!0;this.state_=TlvStructureDecoder.READ_VALUE_BYTES}else this.nBytesToRead_=253==c?2:254==c?4:8,this.firstOctet_=c,this.state_=TlvStructureDecoder.READ_LENGTH_BYTES;else if(this.state_==TlvStructureDecoder.READ_LENGTH_BYTES){c=
+a.length-this.offset_;if(!this.useHeaderBuffer_&&c>=this.nBytesToRead_)b.seek(this.offset_),this.nBytesToRead_=b.readExtendedVarNumber(this.firstOctet_),this.offset_=b.getOffset();else{this.useHeaderBuffer_=!0;var d=this.nBytesToRead_-this.headerLength_;if(d>c){if(this.headerLength_+c>this.headerBuffer_.length)throw Error("Cannot store more header bytes than the size of headerBuffer");a.slice(this.offset_,this.offset_+c).copy(this.headerBuffer_,this.headerLength_);this.offset_+=c;this.headerLength_+=
+c;return!1}if(this.headerLength_+d>this.headerBuffer_.length)throw Error("Cannot store more header bytes than the size of headerBuffer");a.slice(this.offset_,this.offset_+d).copy(this.headerBuffer_,this.headerLength_);this.offset_+=d;this.nBytesToRead_=(new TlvDecoder(this.headerBuffer_)).readExtendedVarNumber(this.firstOctet_)}if(0==this.nBytesToRead_)return this.gotElementEnd_=!0;this.state_=TlvStructureDecoder.READ_VALUE_BYTES}else{if(this.state_==TlvStructureDecoder.READ_VALUE_BYTES){c=a.length-
+this.offset_;if(c<this.nBytesToRead_)return this.offset_+=c,this.nBytesToRead_-=c,!1;this.offset_+=this.nBytesToRead_;return this.gotElementEnd_=!0}throw Error("findElementEnd: unrecognized state");}}};TlvStructureDecoder.prototype.getOffset=function(){return this.offset_};TlvStructureDecoder.prototype.seek=function(a){this.offset_=a};
+var TlvEncoder=require("./tlv/tlv-encoder.js").TlvEncoder,TlvDecoder=require("./tlv/tlv-decoder.js").TlvDecoder,Blob=require("../util/blob.js").Blob,Name=require("../name.js").Name,ProtobufTlv=function(){};exports.ProtobufTlv=ProtobufTlv;ProtobufTlv._Field=null;ProtobufTlv.establishField=function(){if(null===ProtobufTlv._Field)try{ProtobufTlv._Field=dcodeIO.ProtoBuf.Reflect.Message.Field}catch(a){ProtobufTlv._Field=require("protobufjs").Reflect.Message.Field}};
+ProtobufTlv.encode=function(a,b){ProtobufTlv.establishField();a.encodeAB();var c=new TlvEncoder;ProtobufTlv._encodeMessageValue(a,b,c);return new Blob(c.getOutput(),!1)};ProtobufTlv.decode=function(a,b,c){ProtobufTlv.establishField();c="object"===typeof c&&c instanceof Blob?c.buf():c;var d=new TlvDecoder(c);ProtobufTlv._decodeMessageValue(a,b,d,c.length)};
+ProtobufTlv._encodeMessageValue=function(a,b,c){b=b.getChildren(ProtobufTlv._Field);for(var d=b.length-1;0<=d;--d){var e=b[d],f=e.id,g;if(e.repeated)g=a[e.name];else if(null!=a[e.name])g=[a[e.name]];else continue;for(var h=g.length-1;0<=h;--h){var k=g[h];if("message"==e.type.name){var l=c.getLength();ProtobufTlv._encodeMessageValue(k,e.resolvedType,c);c.writeTypeAndLength(f,c.getLength()-l)}else if("uint32"==e.type.name||"uint64"==e.type.name)c.writeNonNegativeIntegerTlv(f,k);else if("enum"==e.type.name){if(0>
+k)throw Error("ProtobufTlv::encode: ENUM value may not be negative");c.writeNonNegativeIntegerTlv(f,k)}else if("bytes"==e.type.name)l=k.toBuffer(),void 0==l.length&&(l=new Uint8Array(k.toArrayBuffer())),c.writeBlobTlv(f,l);else if("string"==e.type.name)c.writeBlobTlv(f,(new Blob(k,!1)).buf());else if("bool"==e.type.name)k&&c.writeTypeAndLength(f,0);else if("double"==e.type.name)l=new Buffer(8),l.writeDoubleLE(k,0),c.writeBlobTlv(f,l);else throw Error("ProtobufTlv::encode: Unknown field type");}}};
+ProtobufTlv._decodeMessageValue=function(a,b,c,d){b=b.getChildren(ProtobufTlv._Field);for(var e=0;e<b.length;++e){var f=b[e],g=f.id;if(f.required||c.peekType(g,d))if(f.repeated)for(;c.peekType(g,d);)if("message"==f.type.name){var h=c.readNestedTlvsStart(g),k=new (f.resolvedType.build());a.add(f.name,k);ProtobufTlv._decodeMessageValue(k,f.resolvedType,c,h);c.finishNestedTlvs(h)}else a.add(f.name,ProtobufTlv._decodeFieldValue(f,g,c,d));else"message"==f.type.name?(h=c.readNestedTlvsStart(g),k=new (f.resolvedType.build()),
+a.set(f.name,k),ProtobufTlv._decodeMessageValue(k,f.resolvedType,c,h),c.finishNestedTlvs(h)):a.set(f.name,ProtobufTlv._decodeFieldValue(f,g,c,d))}};
+ProtobufTlv._decodeFieldValue=function(a,b,c,d){if("uint32"==a.type.name||"uint64"==a.type.name||"enum"==a.type.name)return c.readNonNegativeIntegerTlv(b);if("bytes"==a.type.name)return c.readBlobTlv(b);if("string"==a.type.name)return c.readBlobTlv(b).toString();if("bool"==a.type.name)return c.readBooleanTlv(b,d);if("double"==a.type.name)return c.readBlobTlv(b).readDoubleLE(0);throw Error("ProtobufTlv.decode: Unknown field type");};
+ProtobufTlv.toName=function(a){for(var b=new Name,c=0;c<a.length;++c)b.append(new Blob(new Buffer(a[c].toBinary(),"binary")),!1);return b};var OID=function(a){if("string"===typeof a){a=a.split(".");this.oid=[];for(var b=0;b<a.length;++b)this.oid.push(parseInt(a[b]))}else this.oid=a.slice(0,a.length)};exports.OID=OID;OID.prototype.getIntegerList=function(){return this.oid};OID.prototype.setIntegerList=function(a){this.oid=a.slice(0,a.length)};
+OID.prototype.toString=function(){for(var a="",b=0;b<this.oid.length;++b)0!==b&&(a+="."),a+=this.oid[b];return a};OID.prototype.equals=function(a){if(!(a instanceof OID)||this.oid.length!==a.oid.length)return!1;for(var b=0;b<this.oid.length;++b)if(this.oid[b]!=a.oid[b])return!1;return!0};var WireFormat=function(){};exports.WireFormat=WireFormat;WireFormat.prototype.encodeName=function(a){throw Error("encodeName is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeName=function(a,b,c){throw Error("decodeName is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeInterest=function(a){throw Error("encodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.decodeInterest=function(a,b,c){throw Error("decodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.encodeData=function(a){throw Error("encodeData is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.decodeData=function(a,b,c){throw Error("decodeData is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeControlParameters=function(a){throw Error("encodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeControlParameters=function(a,b,c){throw Error("decodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeControlResponse=function(a){throw Error("encodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeControlResponse=function(a,b,c){throw Error("decodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeSignatureInfo=function(a){throw Error("encodeSignatureInfo is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeSignatureInfoAndValue=function(a,b,c){throw Error("decodeSignatureInfoAndValue is unimplemented in the base WireFormat class.  You should use a derived class.");};WireFormat.prototype.encodeSignatureValue=function(a){throw Error("encodeSignatureValue is unimplemented in the base WireFormat class.  You should use a derived class.");};
+WireFormat.prototype.decodeLpPacket=function(a,b,c){throw Error("decodeLpPacket is unimplemented in the base WireFormat class. You should use a derived class.");};WireFormat.prototype.encodeDelegationSet=function(a){throw Error("encodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");};
+WireFormat.prototype.decodeDelegationSet=function(a,b,c){throw Error("decodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");};WireFormat.prototype.encodeEncryptedContent=function(a){throw Error("encodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");};
+WireFormat.prototype.decodeEncryptedContent=function(a,b,c){throw Error("decodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");};WireFormat.setDefaultWireFormat=function(a){WireFormat.defaultWireFormat=a};WireFormat.getDefaultWireFormat=function(){return WireFormat.defaultWireFormat};
+var TlvWireFormat=require("./tlv-wire-format.js").TlvWireFormat,DataUtils=require("./data-utils.js").DataUtils,Tlv=require("./tlv/tlv.js").Tlv,TlvStructureDecoder=require("./tlv/tlv-structure-decoder.js").TlvStructureDecoder,DecodingException=require("./decoding-exception.js").DecodingException,NdnCommon=require("../util/ndn-common.js").NdnCommon,LOG=require("../log.js").Log.LOG,ElementReader=function(a){this.elementListener_=a;this.dataParts_=[];this.tlvStructureDecoder_=new TlvStructureDecoder};
+exports.ElementReader=ElementReader;
+ElementReader.prototype.onReceivedData=function(a){for(;;){var b,c;try{if(0===this.dataParts_.length&&0>=a.length)break;this.tlvStructureDecoder_.seek(0);b=this.tlvStructureDecoder_.findElementEnd(a);c=this.tlvStructureDecoder_.getOffset()}catch(d){throw this.dataParts_=[],this.tlvStructureDecoder_=new TlvStructureDecoder,d;}if(b){var e;0===this.dataParts_.length?e=a.slice(0,c):(this.dataParts_.push(a.slice(0,c)),e=DataUtils.concatArrays(this.dataParts_),this.dataParts_=[]);a=a.slice(c,a.length);
+this.tlvStructureDecoder_=new TlvStructureDecoder;this.elementListener_.onReceivedElement(e);if(0==a.length)break}else{b=a.length;for(c=0;c<this.dataParts_.length;++c)b+=this.dataParts_[c].length;if(b>NdnCommon.MAX_NDN_PACKET_SIZE)throw this.dataParts_=[],this.tlvStructureDecoder_=new TlvStructureDecoder,new DecodingException(Error("The incoming packet exceeds the maximum limit Face.getMaxNdnPacketSize()"));this.dataParts_.push(new Buffer(a));3<LOG&&console.log("Incomplete packet received. Length "+
+a.length+". Wait for more input.");break}}};function DerDecodingException(a){if(a)return a.__proto__=DerDecodingException.prototype,a}DerDecodingException.prototype=Error();DerDecodingException.prototype.name="DerDecodingException";exports.DerDecodingException=DerDecodingException;function DerEncodingException(a){if(a)return a.__proto__=DerEncodingException.prototype,a}DerEncodingException.prototype=Error();DerEncodingException.prototype.name="DerEncodingException";exports.DerEncodingException=DerEncodingException;
+var DerNodeType=function(){};exports.DerNodeType=DerNodeType;DerNodeType.Eoc=0;DerNodeType.Boolean=1;DerNodeType.Integer=2;DerNodeType.BitString=3;DerNodeType.OctetString=4;DerNodeType.Null=5;DerNodeType.ObjectIdentifier=6;DerNodeType.ObjectDescriptor=7;DerNodeType.External=40;DerNodeType.Real=9;DerNodeType.Enumerated=10;DerNodeType.EmbeddedPdv=43;DerNodeType.Utf8String=12;DerNodeType.RelativeOid=13;DerNodeType.Sequence=48;DerNodeType.Set=49;DerNodeType.NumericString=18;
+DerNodeType.PrintableString=19;DerNodeType.T61String=20;DerNodeType.VideoTexString=21;DerNodeType.Ia5String=22;DerNodeType.UtcTime=23;DerNodeType.GeneralizedTime=24;DerNodeType.GraphicString=25;DerNodeType.VisibleString=26;DerNodeType.GeneralString=27;DerNodeType.UniversalString=28;DerNodeType.CharacterString=29;DerNodeType.BmpString=30;
+var DynamicBuffer=require("../../util/dynamic-buffer.js").DynamicBuffer,Blob=require("../../util/blob.js").Blob,DerDecodingException=require("./der-decoding-exception.js").DerDecodingException,DerEncodingException=require("./der-encoding-exception.js").DerEncodingException,DerNodeType=require("./der-node-type.js").DerNodeType,DerNode=function(a){this.nodeType_=a;this.parent_=null;this.header_=new Buffer(0);this.payload_=new DynamicBuffer(0);this.payloadPosition_=0};exports.DerNode=DerNode;
+DerNode.prototype.getSize=function(){return this.header_.length+this.payloadPosition_};
+DerNode.prototype.encodeHeader=function(a){var b=new DynamicBuffer(10),c=0;b.array[c++]=this.nodeType_;if(0>a)throw Error("encodeHeader: DER object has negative length");if(127>=a)b.array[c++]=a&255;else{var d=new DynamicBuffer(10),e=a;for(a=0;0!=e;)++a,d.ensureLengthFromBack(a),d.array[d.array.length-a]=e&255,e>>=8;e=a+1;d.ensureLengthFromBack(e);d.array[d.array.length-e]=(128|a)&255;b.copy(d.slice(d.array.length-e),c);c+=e}this.header_=b.slice(0,c)};
+DerNode.prototype.decodeHeader=function(a,b){var c=b,d=a[c]&255,c=c+1;this.nodeType_=d;var e=a[c]&255,c=c+1,f=new DynamicBuffer(10),g=0;f.array[g++]=d;d=f.array[g++]=e;if(0!=(e&128))for(e&=127,d=0;0<e;){var h=a[c],c=c+1;f.ensureLength(g+1);f.array[g++]=h;d=256*d+(h&255);e-=1}this.header_=f.slice(0,g);return d};DerNode.prototype.encode=function(){var a=new Buffer(this.getSize());this.header_.copy(a);this.payload_.slice(0,this.payloadPosition_).copy(a,this.header_.length);return new Blob(a,!1)};
+DerNode.prototype.decode=function(a,b){var c=b,d=this.decodeHeader(a,c),e=this.header_.length;0<d&&(c+=e,this.payloadAppend(a.slice(c,c+d)))};DerNode.prototype.payloadAppend=function(a){this.payloadPosition_=this.payload_.copy(a,this.payloadPosition_)};
+DerNode.parse=function(a,b){void 0==b&&(b=0);var c=a[b]&255;if(c===DerNodeType.Boolean)c=new DerNode.DerBoolean;else if(c===DerNodeType.Integer)c=new DerNode.DerInteger;else if(c===DerNodeType.BitString)c=new DerNode.DerBitString;else if(c===DerNodeType.OctetString)c=new DerNode.DerOctetString;else if(c===DerNodeType.Null)c=new DerNode.DerNull;else if(c===DerNodeType.ObjectIdentifier)c=new DerNode.DerOid;else if(c===DerNodeType.Sequence)c=new DerNode.DerSequence;else if(c===DerNodeType.PrintableString)c=
+new DerNode.DerPrintableString;else if(c===DerNodeType.GeneralizedTime)c=new DerNode.DerGeneralizedTime;else throw new DerDecodingException(Error("Unimplemented DER type "+c));c.decode(a,b);return c};DerNode.prototype.toVal=function(){return this.encode()};DerNode.prototype.getPayload=function(){return new Blob(this.payload_.slice(0,this.payloadPosition_),!0)};DerNode.prototype.getChildren=function(){throw new DerDecodingException(Error("getChildren: This DerNode is not DerSequence"));};
+DerNode.getSequence=function(a,b){if(0>b||b>=a.length)throw new DerDecodingException(Error("getSequence: Child index is out of bounds"));if(!(a[b]instanceof DerNode.DerSequence))throw new DerDecodingException(Error("getSequence: Child DerNode is not a DerSequence"));return a[b]};DerNode.DerStructure=function(a){DerNode.call(this,a);this.childChanged_=!1;this.nodeList_=[];this.size_=0};DerNode.DerStructure.prototype=new DerNode;DerNode.DerStructure.prototype.name="DerStructure";
+DerNode.DerStructure.prototype.getSize=function(){this.childChanged_&&(this.updateSize(),this.childChanged_=!1);this.encodeHeader(this.size_);return this.size_+this.header_.length};DerNode.DerStructure.prototype.getChildren=function(){return this.nodeList_};DerNode.DerStructure.prototype.updateSize=function(){for(var a=0,b=0;b<this.nodeList_.length;++b)a+=this.nodeList_[b].getSize();this.size_=a;this.childChanged_=!1};
+DerNode.DerStructure.prototype.addChild=function(a,b){a.parent_=this;this.nodeList_.push(a);b&&null!=this.parent_&&this.parent_.setChildChanged();this.childChanged_=!0};DerNode.DerStructure.prototype.setChildChanged=function(){null!=this.parent_&&this.parent_.setChildChanged();this.childChanged_=!0};
+DerNode.DerStructure.prototype.encode=function(){var a=new DynamicBuffer(10),b=0;this.updateSize();this.encodeHeader(this.size_);for(var b=a.copy(this.header_,b),c=0;c<this.nodeList_.length;++c)var d=this.nodeList_[c].encode(),b=a.copy(d.buf(),b);return new Blob(a.slice(0,b),!1)};DerNode.DerStructure.prototype.decode=function(a,b){var c=b;this.size_=this.decodeHeader(a,c);for(var c=c+this.header_.length,d=0;d<this.size_;){var e=DerNode.parse(a,c),f=e.getSize(),c=c+f,d=d+f;this.addChild(e,!1)}};
+DerNode.DerByteString=function(a,b){DerNode.call(this,b);null!=a&&(this.payloadAppend(a),this.encodeHeader(a.length))};DerNode.DerByteString.prototype=new DerNode;DerNode.DerByteString.prototype.name="DerByteString";DerNode.DerByteString.prototype.toVal=function(){return this.getPayload()};DerNode.DerBoolean=function(a){DerNode.call(this,DerNodeType.Boolean);void 0!=a&&(a=a?255:0,this.payload_.ensureLength(this.payloadPosition_+1),this.payload_.array[this.payloadPosition_++]=a,this.encodeHeader(1))};
+DerNode.DerBoolean.prototype=new DerNode;DerNode.DerBoolean.prototype.name="DerBoolean";DerNode.DerBoolean.prototype.toVal=function(){return 0!=this.payload_.array[0]};
+DerNode.DerInteger=function(a){DerNode.call(this,DerNodeType.Integer);if(void 0!=a){if(Buffer.isBuffer(a)){if(0<a.length&&128<=a[0])throw new DerEncodingException(Error("DerInteger: Negative integers are not currently supported"));0==a.length?this.payloadAppend(new Buffer([0])):this.payloadAppend(a)}else{a=Math.round(a);if(0>a)throw new DerEncodingException(Error("DerInteger: Negative integers are not currently supported"));for(var b=new DynamicBuffer(10),c=0;!(++c,b.ensureLengthFromBack(c),b.array[b.array.length-
+c]=a&255,a>>=8,0>=a););128<=b.array[b.array.length-c]&&(++c,b.ensureLengthFromBack(c),b.array[b.array.length-c]=0);this.payloadAppend(b.slice(b.array.length-c))}this.encodeHeader(this.payloadPosition_)}};DerNode.DerInteger.prototype=new DerNode;DerNode.DerInteger.prototype.name="DerInteger";
+DerNode.DerInteger.prototype.toVal=function(){if(0<this.payloadPosition_&&128<=this.payload_.array[0])throw new DerDecodingException(Error("DerInteger: Negative integers are not currently supported"));for(var a=0,b=0;b<this.payloadPosition_;++b)a<<=8,a+=this.payload_.array[b];return a};DerNode.DerBitString=function(a,b){DerNode.call(this,DerNodeType.BitString);void 0!=a&&(this.payload_.ensureLength(this.payloadPosition_+1),this.payload_.array[this.payloadPosition_++]=b&255,this.payloadAppend(a),this.encodeHeader(this.payloadPosition_))};
+DerNode.DerBitString.prototype=new DerNode;DerNode.DerBitString.prototype.name="DerBitString";DerNode.DerOctetString=function(a){DerNode.DerByteString.call(this,a,DerNodeType.OctetString)};DerNode.DerOctetString.prototype=new DerNode.DerByteString;DerNode.DerOctetString.prototype.name="DerOctetString";DerNode.DerNull=function(){DerNode.call(this,DerNodeType.Null);this.encodeHeader(0)};DerNode.DerNull.prototype=new DerNode;DerNode.DerNull.prototype.name="DerNull";
+DerNode.DerOid=function(a){DerNode.call(this,DerNodeType.ObjectIdentifier);if(void 0!=a)if("string"===typeof a){a=a.split(".");for(var b=[],c=0;c<a.length;++c)b.push(parseInt(a[c]));this.prepareEncoding(b)}else this.prepareEncoding(a.getIntegerList())};DerNode.DerOid.prototype=new DerNode;DerNode.DerOid.prototype.name="DerOid";
+DerNode.DerOid.prototype.prepareEncoding=function(a){var b;if(0==a.length)throw new DerEncodingException(Error("No integer in OID"));if(0<=a[0]&&2>=a[0])b=40*a[0];else throw new DerEncodingException(Error("First integer in OID is out of range"));if(2<=a.length)if(0<=a[1]&&39>=a[1])b+=a[1];else throw new DerEncodingException(Error("Second integer in OID is out of range"));var c=new DynamicBuffer(10),d=0,d=c.copy(DerNode.DerOid.encode128(b),d);if(2<a.length)for(b=2;b<a.length;++b)d=c.copy(DerNode.DerOid.encode128(a[b]),
+d);this.encodeHeader(d);this.payloadAppend(c.slice(0,d))};DerNode.DerOid.encode128=function(a){var b=new DynamicBuffer(10),c=0;if(128>a)++c,b.array[b.array.length-c]=a&127;else for(++c,b.array[b.array.length-c]=a&127,a>>=7;0!=a;)++c,b.ensureLengthFromBack(c),b.array[b.array.length-c]=a&127|128,a>>=7;return b.slice(b.array.length-c)};
+DerNode.DerOid.prototype.decode128=function(a,b){for(var c=0,d=a;0!=(this.payload_.array[a]&128);)c=128*c+(this.payload_.array[a]&255)-128,a+=1;c=128*c+(this.payload_.array[a]&255);b[0]=a-d+1;return c};DerNode.DerOid.prototype.toVal=function(){for(var a=0,b=[];a<this.payloadPosition_;){var c=[0],d=this.decode128(a,c),a=a+c[0];b.push(d)}a=b[0];a=Math.floor(a/40)+"."+a%40;for(c=1;c<b.length;++c)a+="."+b[c];return a};DerNode.DerSequence=function(){DerNode.DerStructure.call(this,DerNodeType.Sequence)};
+DerNode.DerSequence.prototype=new DerNode.DerStructure;DerNode.DerSequence.prototype.name="DerSequence";DerNode.DerPrintableString=function(a){DerNode.DerByteString.call(this,a,DerNodeType.PrintableString)};DerNode.DerPrintableString.prototype=new DerNode.DerByteString;DerNode.DerPrintableString.prototype.name="DerPrintableString";
+DerNode.DerGeneralizedTime=function(a){DerNode.call(this,DerNodeType.GeneralizedTime);void 0!=a&&(a=DerNode.DerGeneralizedTime.toDerTimeString(a),this.payloadAppend((new Blob(a)).buf()),this.encodeHeader(this.payloadPosition_))};DerNode.DerGeneralizedTime.prototype=new DerNode;DerNode.DerGeneralizedTime.prototype.name="DerGeneralizedTime";
+DerNode.DerGeneralizedTime.toDerTimeString=function(a){a=new Date(Math.round(a));return a.getUTCFullYear()+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCMonth()+1)+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCDate())+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCHours())+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCMinutes())+DerNode.DerGeneralizedTime.to2DigitString(a.getUTCSeconds())+"Z"};
+DerNode.DerGeneralizedTime.to2DigitString=function(a){a=a.toString();return 1===a.length?"0"+a:a};DerNode.DerGeneralizedTime.prototype.toVal=function(){var a=this.payload_.slice(0,this.payloadPosition_).toString();return Date.UTC(parseInt(a.substr(0,4)),parseInt(a.substr(4,2)-1),parseInt(a.substr(6,2)),parseInt(a.substr(8,2)),parseInt(a.substr(10,2)),parseInt(a.substr(12,2)))};var fs=require("fs"),BoostInfoTree=function(a,b){this.subtrees=[];this.value=a;this.parent=b;this.lastChild=null};
+BoostInfoTree.prototype.addSubtree=function(a,b){var c=this.find(a);null!==c?c.push(b):this.subtrees.push({key:a,value:[b]});b.parent=this;this.lastChild=b};BoostInfoTree.prototype.createSubtree=function(a,b){var c=new BoostInfoTree(b,this);this.addSubtree(a,c);return c};
+BoostInfoTree.prototype.get=function(a){a=a.replace(/^\/+/,"");if(0===a.length)return[this];var b=a.split("/");a=this.find(b[0]);if(null===a)return[];if(1==b.length)return a.slice(0);for(var b=b.slice(1).join("/"),c=[],d=0;d<a.length;++d)var e=a[d].get(b),c=c.concat(e);return c};BoostInfoTree.prototype.getFirstValue=function(a){a=this.get(a);return 1<=a.length?a[0].value:null};BoostInfoTree.prototype.getValue=function(){return this.value};BoostInfoTree.prototype.getParent=function(){return this.parent};
+BoostInfoTree.prototype.getLastChild=function(){return this.lastChild};
+BoostInfoTree.prototype.prettyPrint=function(a){a=a||1;var b=Array(a+1).join(" "),c="";null!=this.parent&&(this.value&&0<this.value.length&&(c+='"'+this.value+'"'),c+="\n");if(0<this.subtrees.length){this.parent&&(c+=b+"{\n");for(var d=Array(a+2+1).join(" "),e=0;e<this.subtrees.length;++e)for(var f=0;f<this.subtrees[e].value.length;++f)c+=d+this.subtrees[e].key+" "+this.subtrees[e].value[f].prettyPrint(a+2);this.parent&&(c+=b+"}\n")}return c};BoostInfoTree.prototype.toString=function(){return this.prettyPrint()};
+BoostInfoTree.prototype.find=function(a){for(var b=0;b<this.subtrees.length;++b)if(this.subtrees[b].key==a)return this.subtrees[b].value;return null};var BoostInfoParser=function(){this.root=new BoostInfoTree};exports.BoostInfoParser=BoostInfoParser;exports.BoostInfoTree=BoostInfoTree;BoostInfoParser.prototype.read=function(a,b){var c;"string"==typeof b?c=a:(b=a,c=fs.readFileSync(a).toString());var d=this.root,e=this;c.split(/\r?\n/).forEach(function(a){d=e.parseLine(a.trim(),d)})};
+BoostInfoParser.prototype.write=function(a){fs.writeFileSync(a,""+this.root)};BoostInfoParser.prototype.getRoot=function(){return this.root};
+BoostInfoParser.shlex_split=function(a){var b=[];if(""==a)return b;for(var c=0;;){for(;0<=" \t\n\r".indexOf(a[c]);)if(c+=1,c>=a.length)return b;for(var d=c,e=!1,f="";;){if("\\"==a[d]){if(f+=a.substring(c,d),d=c=d+1,d>=a.length)break}else if(e)'"'==a[d]&&(f+=a.substring(c,d),c=d+1,e=!1);else if('"'==a[d])f+=a.substring(c,d),c=d+1,e=!0;else if(0<=" \t\n\r".indexOf(a[d]))break;d+=1;if(d>=a.length)break}f+=a.substring(c,d);b.push(f);if(d>=a.length)return b;c=d}};
+BoostInfoParser.prototype.parseLine=function(a,b){var c=a.indexOf(";");0<=c&&(a=a.substring(0,c).trim());if(0==a.length)return b;for(var c=BoostInfoParser.shlex_split(a),d=!1,e=!1,f=0;f<c.length;++f)d=d||"{"==c[f],e=e||"}"==c[f];if(!d&&!e){var d=c[0],g;1<c.length&&(g=c[1]);b.createSubtree(d,g);return b}c=a.indexOf("{");if(0<c)return g=a.substring(0,c),c=a.substring(c),g=this.parseLine(g,b),this.parseLine(c,g);if("{"==a[0])return b=b.getLastChild();if("}"==a[0])return b=b.getParent();throw runtime_error("BoostInfoParser: input line is malformed");
+};
+var Name=require("../name.js").Name,InterestFilter=require("../interest-filter.js").InterestFilter,ForwardingFlags=require("../forwarding-flags.js").ForwardingFlags,WireFormat=require("../encoding/wire-format.js").WireFormat,LOG=require("../log.js").Log.LOG,MemoryContentCache=function(a,b){b=b||1E3;this.face=a;this.cleanupIntervalMilliseconds=b;this.nextCleanupTime=(new Date).getTime()+b;this.onDataNotFoundForPrefix={};this.interestFilterIdList=[];this.registeredPrefixIdList=[];this.noStaleTimeCache=[];
+this.staleTimeCache=[];this.emptyComponent=new Name.Component;this.pendingInterestTable=[];var c=this;this.storePendingInterestCallback=function(a,b,f,g,h){c.storePendingInterest(b,f)}};exports.MemoryContentCache=MemoryContentCache;
+MemoryContentCache.prototype.registerPrefix=function(a,b,c,d,e,f){var g=c,h=d,k=e;c="object"===typeof g&&1===g.length&&"function"===typeof g[0]?g[0]:null;d="function"===typeof g?g:"function"===typeof h?h:null;e=g instanceof ForwardingFlags?g:h instanceof ForwardingFlags?h:k instanceof ForwardingFlags?k:new ForwardingFlags;f=g instanceof WireFormat?g:h instanceof WireFormat?h:k instanceof WireFormat?k:f instanceof WireFormat?f:WireFormat.getDefaultWireFormat();d&&(this.onDataNotFoundForPrefix[a.toUri()]=
+d);a=this.face.registerPrefix(a,this.onInterest.bind(this),b,c,e,f);this.registeredPrefixIdList.push(a)};MemoryContentCache.prototype.setInterestFilter=function(a,b){if(b){var c;c="object"===typeof a&&a instanceof InterestFilter?a.getPrefix():a;this.onDataNotFoundForPrefix[c.toUri()]=b}c=this.face.setInterestFilter(a,this.onInterest.bind(this));this.interestFilterIdList.push(c)};
+MemoryContentCache.prototype.unregisterAll=function(){for(var a=0;a<this.interestFilterIdList.length;++a)this.face.unsetInterestFilter(this.interestFilterIdList[a]);this.interestFilterIdList=[];for(a=0;a<this.registeredPrefixIdList.length;++a)this.face.removeRegisteredPrefix(this.registeredPrefixIdList[a]);this.registeredPrefixIdList=[];this.onDataNotFoundForPrefix={}};
+MemoryContentCache.prototype.add=function(a){this.doCleanup();if(null!=a.getMetaInfo().getFreshnessPeriod()&&0<=a.getMetaInfo().getFreshnessPeriod()){for(var b=new MemoryContentCache.StaleTimeContent(a),c=this.staleTimeCache.length-1;0<=c&&!(this.staleTimeCache[c].staleTimeMilliseconds<=b.staleTimeMilliseconds);)--c;this.staleTimeCache.splice(c+1,0,b)}else this.noStaleTimeCache.push(new MemoryContentCache.Content(a));b=(new Date).getTime();for(c=this.pendingInterestTable.length-1;0<=c;--c)if(this.pendingInterestTable[c].isTimedOut(b))this.pendingInterestTable.splice(c,
+1);else if(this.pendingInterestTable[c].getInterest().matchesName(a.getName())){try{this.pendingInterestTable[c].getFace().send(a.wireEncode().buf())}catch(d){0<LOG&&console.log(""+d);break}this.pendingInterestTable.splice(c,1)}};MemoryContentCache.prototype.storePendingInterest=function(a,b){this.pendingInterestTable.push(new MemoryContentCache.PendingInterest(a,b))};MemoryContentCache.prototype.getStorePendingInterest=function(){return this.storePendingInterestCallback};
+MemoryContentCache.prototype.onInterest=function(a,b,c,d,e){this.doCleanup();for(var f=0,g=null,h=this.staleTimeCache.length+this.noStaleTimeCache.length,k=0;k<h;++k){var l;l=k<this.staleTimeCache.length?this.staleTimeCache[k]:this.noStaleTimeCache[k-this.staleTimeCache.length];if(b.matchesName(l.getName())){if(0>b.getChildSelector()){c.send(l.getDataEncoding());return}var m;m=l.getName().size()>b.getName().size()?l.getName().get(b.getName().size()):this.emptyComponent;var q=!1;null===g?q=!0:0==b.getChildSelector()?
+0>m.compare(f)&&(q=!0):0<m.compare(f)&&(q=!0);q&&(f=m,g=l.getDataEncoding())}}null!==g?c.send(g):(f=this.onDataNotFoundForPrefix[a.toUri()])&&f(a,b,c,d,e)};MemoryContentCache.prototype.doCleanup=function(){var a=(new Date).getTime();if(a>=this.nextCleanupTime){for(;0<this.staleTimeCache.length&&this.staleTimeCache[0].isStale(a);)this.staleTimeCache.shift();this.nextCleanupTime=a+this.cleanupIntervalMilliseconds}};
+MemoryContentCache.Content=function(a){a&&(this.name=new Name(a.getName()),this.dataEncoding=a.wireEncode().buf())};MemoryContentCache.Content.prototype.getName=function(){return this.name};MemoryContentCache.Content.prototype.getDataEncoding=function(){return this.dataEncoding};MemoryContentCache.StaleTimeContent=function(a){MemoryContentCache.Content.call(this,a);this.staleTimeMilliseconds=(new Date).getTime()+a.getMetaInfo().getFreshnessPeriod()};MemoryContentCache.StaleTimeContent.prototype=new MemoryContentCache.Content;
+MemoryContentCache.StaleTimeContent.prototype.name="StaleTimeContent";MemoryContentCache.StaleTimeContent.prototype.isStale=function(a){return this.staleTimeMilliseconds<=a};MemoryContentCache.PendingInterest=function(a,b){this.interest=a;this.face=b;0<=this.interest.getInterestLifetimeMilliseconds()?this.timeoutMilliseconds=(new Date).getTime()+this.interest.getInterestLifetimeMilliseconds():this.timeoutMilliseconds=-1};MemoryContentCache.PendingInterest.prototype.getInterest=function(){return this.interest};
+MemoryContentCache.PendingInterest.prototype.getFace=function(){return this.face};MemoryContentCache.PendingInterest.prototype.isTimedOut=function(a){return 0<=this.timeoutTimeMilliseconds&&a>=this.timeoutTimeMilliseconds};var Name=require("../name.js").Name,NdnRegexMatcher=function(){};exports.NdnRegexMatcher=NdnRegexMatcher;NdnRegexMatcher.match=function(a,b){var c=b.toUri();a=NdnRegexMatcher.sanitizeSets(a);a=a.replace(/<>/g,"(?:<.+?>)");a=a.replace(/>/g,"");a=a.replace(/<(?!!)/g,"/");return c.match(new RegExp(a))};
+NdnRegexMatcher.sanitizeSets=function(a){for(var b=a,c=/\[(\^?)(.*?)\]/g,d;null!==(d=c.exec(a));){var e=c.lastIndex-1-d[2].length,f=e+d[2].length;0!==e-f&&(d=d[2].replace(/></g,">|<"),b=b.substr(0,e)+d+b.substr(f))}0<=b.indexOf("[^")?(b=b.replace(/\[\^/g,"(?:(?!"),b=b.replace(/\]/g,")(?:/.*)*)")):(b=b.replace(/\[/g,"("),b=b.replace(/\]/g,")"));return b};
+var Interest=require("../interest.js").Interest,Blob=require("./blob.js").Blob,KeyChain=require("../security/key-chain.js").KeyChain,NdnCommon=require("./ndn-common.js").NdnCommon,SegmentFetcher=function(a,b,c,d,e){this.face=a;this.validatorKeyChain=b;this.verifySegment=c;this.onComplete=d;this.onError=e;this.contentParts=[]};exports.SegmentFetcher=SegmentFetcher;SegmentFetcher.ErrorCode={INTEREST_TIMEOUT:1,DATA_HAS_NO_SEGMENT:2,SEGMENT_VERIFICATION_FAILED:3};SegmentFetcher.DontVerifySegment=function(a){return!0};
+SegmentFetcher.fetch=function(a,b,c,d,e){null==c||c instanceof KeyChain?(new SegmentFetcher(a,c,SegmentFetcher.DontVerifySegment,d,e)).fetchFirstSegment(b):(new SegmentFetcher(a,null,c,d,e)).fetchFirstSegment(b)};SegmentFetcher.prototype.fetchFirstSegment=function(a){a=new Interest(a);a.setChildSelector(1);a.setMustBeFresh(!0);var b=this;this.face.expressInterest(a,function(a,d){b.onData(a,d)},function(a){b.onTimeout(a)})};
+SegmentFetcher.prototype.fetchNextSegment=function(a,b,c){a=new Interest(a);a.setChildSelector(0);a.setMustBeFresh(!1);a.setName(b.getPrefix(-1).appendSegment(c));var d=this;this.face.expressInterest(a,function(a,b){d.onData(a,b)},function(a){d.onTimeout(a)})};
+SegmentFetcher.prototype.onData=function(a,b){if(null!=this.validatorKeyChain)try{var c=this;this.validatorKeyChain.verifyData(b,function(b){c.onVerified(b,a)},this.onValidationFailed.bind(this))}catch(d){console.log("Error in KeyChain.verifyData: "+d)}else if(this.verifySegment(b))this.onVerified(b,a);else try{this.onError(SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,"Segment verification failed")}catch(e){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(e))}};
+SegmentFetcher.prototype.onVerified=function(a,b){if(SegmentFetcher.endsWithSegmentNumber(a.getName())){var c=0;try{c=a.getName().get(-1).toSegment()}catch(d){try{this.onError(SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,"Error decoding the name segment number "+a.getName().get(-1).toEscapedString()+": "+d)}catch(e){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(e))}return}var f=this.contentParts.length;if(c!=f)this.fetchNextSegment(b,a.getName(),f);else{this.contentParts.push(a.getContent().buf());
+if(0<a.getMetaInfo().getFinalBlockId().getValue().size()){var g=0;try{g=a.getMetaInfo().getFinalBlockId().toSegment()}catch(h){try{this.onError(SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,"Error decoding the FinalBlockId segment number "+a.getMetaInfo().getFinalBlockId().toEscapedString()+": "+h)}catch(k){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(k))}return}if(c==g){c=Buffer.concat(this.contentParts);try{this.onComplete(new Blob(c,!1))}catch(l){console.log("Error in onComplete: "+
+NdnCommon.getErrorWithStackTrace(l))}return}}this.fetchNextSegment(b,a.getName(),f+1)}}else try{this.onError(SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,"Got an unexpected packet without a segment number: "+a.getName().toUri())}catch(m){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(m))}};
+SegmentFetcher.prototype.onValidationFailed=function(a,b){try{this.onError(SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,"Segment verification failed for "+a.getName().toUri()+" . Reason: "+b)}catch(c){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(c))}};SegmentFetcher.prototype.onTimeout=function(a){try{this.onError(SegmentFetcher.ErrorCode.INTEREST_TIMEOUT,"Time out for interest "+a.getName().toUri())}catch(b){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(b))}};
+SegmentFetcher.endsWithSegmentNumber=function(a){return 1<=a.size()&&a.get(-1).isSegment()};var Transport=function(){};exports.Transport=Transport;Transport.ConnectionInfo=function(){};Transport.prototype.isLocal=function(a,b,c){c("Transport.isLocal is not implemented")};
+var MicroForwarderTransport=function(){Transport.call(this);this.onReceivedObject=this.connectionInfo=this.elementReader=null;var a=this;window.addEventListener("message",function(b){if(b.source==window&&b.data.type&&"FromMicroForwarderStub"==b.data.type)if(b=b.data.object,b.type&&"Buffer"==b.type){if(null!=a.elementReader)a.elementReader.onReceivedData(new Buffer(b.data))}else if(a.onReceivedObject)a.onReceivedObject(b)},!1)};MicroForwarderTransport.prototype=new Transport;
+MicroForwarderTransport.prototype.name="MicroForwarderTransport";MicroForwarderTransport.ConnectionInfo=function(){Transport.ConnectionInfo.call(this)};MicroForwarderTransport.ConnectionInfo.prototype=new Transport.ConnectionInfo;MicroForwarderTransport.ConnectionInfo.prototype.name="MicroForwarderTransport.ConnectionInfo";MicroForwarderTransport.ConnectionInfo.prototype.equals=function(a){return null==a?!1:!0};MicroForwarderTransport.ConnectionInfo.prototype.toString=function(){return"{}"};
+MicroForwarderTransport.prototype.setOnReceivedObject=function(a){this.onReceivedObject=a};MicroForwarderTransport.prototype.isLocal=function(a,b,c){b(!0)};MicroForwarderTransport.prototype.connect=function(a,b,c,d){this.elementReader=new ElementReader(b);this.connectionInfo=a;c()};MicroForwarderTransport.prototype.sendObject=function(a){window.postMessage({type:"FromMicroForwarderTransport",object:a},"*")};
+MicroForwarderTransport.prototype.send=function(a){null==this.connectionInfo?console.log("MicroForwarderTransport connection is not established."):this.sendObject(a.toJSON())};var RuntimePortTransport=function(a){Transport.call(this);this.connectionInfo=this.elementReader=null;this.onReceivedObject=a;this.port=null};RuntimePortTransport.prototype=new Transport;RuntimePortTransport.prototype.name="RuntimePortTransport";
+RuntimePortTransport.ConnectionInfo=function(a){Transport.ConnectionInfo.call(this);this.port=a};RuntimePortTransport.ConnectionInfo.prototype=new Transport.ConnectionInfo;RuntimePortTransport.ConnectionInfo.prototype.name="RuntimePortTransport.ConnectionInfo";RuntimePortTransport.ConnectionInfo.prototype.equals=function(a){return null==a||void 0==a.port?!1:this.port==a.port};RuntimePortTransport.ConnectionInfo.prototype.toString=function(){return"{}"};
+RuntimePortTransport.prototype.setOnReceivedObject=function(a){this.onReceivedObject=a};RuntimePortTransport.prototype.isLocal=function(a,b,c){b(!0)};
+RuntimePortTransport.prototype.connect=function(a,b,c,d){this.elementReader=new ElementReader(b);this.connectionInfo=a;this.port=this.connectionInfo.port;var e=this;this.port.onMessage.addListener(function(a){if("Buffer"==a.type)e.elementReader.onReceivedData(Buffer.isBuffer(a.data)?a.data:new Buffer(a.data));else if(null!=e.onReceivedObject)e.onReceivedObject(a)});this.port.onDisconnect.addListener(function(){e.port=null;null!=d&&d()});c()};
+RuntimePortTransport.prototype.sendObject=function(a){null==this.port?console.log("RuntimePortTransport connection is not established."):this.port.postMessage(a)};RuntimePortTransport.prototype.send=function(a){this.sendObject(a.toJSON())};
+var ElementReader=require("../encoding/element-reader.js").ElementReader,LOG=require("../log.js").Log.LOG,Transport=require("./transport.js").Transport,Face,WebSocketTransport=function WebSocketTransport(){Transport.call(this);if(!WebSocket)throw Error("WebSocket support is not available on this platform.");this.elementReader=this.connectionInfo=this.ws=null;this.defaultGetConnectionInfo=Face.makeShuffledHostGetConnectionInfo("A.ws.ndn.ucla.edu B.ws.ndn.ucla.edu C.ws.ndn.ucla.edu D.ws.ndn.ucla.edu E.ws.ndn.ucla.edu F.ws.ndn.ucla.edu G.ws.ndn.ucla.edu H.ws.ndn.ucla.edu I.ws.ndn.ucla.edu J.ws.ndn.ucla.edu K.ws.ndn.ucla.edu L.ws.ndn.ucla.edu M.ws.ndn.ucla.edu N.ws.ndn.ucla.edu".split(" "),
+9696,function(b,c){return new WebSocketTransport.ConnectionInfo(b,c)})};WebSocketTransport.prototype=new Transport;WebSocketTransport.prototype.name="WebSocketTransport";WebSocketTransport.importFace=function(a){Face=a};exports.WebSocketTransport=WebSocketTransport;WebSocketTransport.ConnectionInfo=function(a,b){Transport.ConnectionInfo.call(this);this.host=a;this.port=void 0!==b?b:9696};WebSocketTransport.ConnectionInfo.prototype=new Transport.ConnectionInfo;
+WebSocketTransport.ConnectionInfo.prototype.name="WebSocketTransport.ConnectionInfo";WebSocketTransport.ConnectionInfo.prototype.equals=function(a){return null==a||void 0==a.host||void 0==a.port?!1:this.host==a.host&&this.port==a.port};WebSocketTransport.ConnectionInfo.prototype.toString=function(){return this.hostIsUri()?"{ uri: "+this.host+" }":"{ host: "+this.host+", port: "+this.port+" }"};
+WebSocketTransport.ConnectionInfo.prototype.hostIsUri=function(){return"ws:"==this.host.substr(0,3)||"wss:"==this.host.substr(0,4)};WebSocketTransport.prototype.isLocal=function(a,b,c){b(!1)};
+WebSocketTransport.prototype.connect=function(a,b,c,d){this.close();var e=a.hostIsUri()?a.host:"ws://"+a.host+":"+a.port;this.ws=new WebSocket(e);0<LOG&&console.log("ws connection created.");this.connectionInfo=a;this.ws.binaryType="arraybuffer";this.elementReader=new ElementReader(b);var f=this;this.ws.onmessage=function(a){a=a.data;if(null==a||void 0==a||""==a)console.log("INVALID ANSWER");else if(a instanceof ArrayBuffer){a=new Buffer(new Uint8Array(a));3<LOG&&console.log("BINARY RESPONSE IS "+
+a.toString("hex"));try{f.elementReader.onReceivedData(a)}catch(b){console.log("NDN.ws.onmessage exception: "+b)}}};this.ws.onopen=function(a){3<LOG&&console.log(a);3<LOG&&console.log("ws.onopen: WebSocket connection opened.");3<LOG&&console.log("ws.onopen: ReadyState: "+this.readyState);c()};this.ws.onerror=function(a){console.log("ws.onerror: ReadyState: "+this.readyState);console.log(a);console.log("ws.onerror: WebSocket error: "+a.data)};this.ws.onclose=function(a){console.log("ws.onclose: WebSocket connection closed.");
+f.ws=null;null!=d&&d()}};WebSocketTransport.prototype.connectByFace=function(a,b){this.connect(a.connectionInfo,a,b,function(){a.closeByTransport()})};WebSocketTransport.prototype.send=function(a){if(null!=this.ws){var b=new Uint8Array(a.length);b.set(a);this.ws.send(b.buffer);3<LOG&&console.log("ws.send() returned.")}else console.log("WebSocket connection is not established.")};WebSocketTransport.prototype.close=function(){null!=this.ws&&delete this.ws};exports.TcpTransport=require("./transport/web-socket-transport").WebSocketTransport;
+Blob=require("./util/blob.js").Blob;DataUtils=require("./encoding/data-utils.js").DataUtils;LOG=require("./log.js").Log.LOG;DecodingException=require("./encoding/decoding-exception.js").DecodingException;
+Name=function Name(b){if("string"==typeof b)3<LOG&&console.log("Content Name String "+b),this.components=Name.createNameArray(b);else if("object"===typeof b)if(this.components=[],b instanceof Name)this.append(b);else for(var c=0;c<b.length;++c)this.append(b[c]);else null==b?this.components=[]:1<LOG&&console.log("NO CONTENT NAME GIVEN");this.changeCount=0};exports.Name=Name;
+Name.Component=function(a){"object"===typeof a&&a instanceof Name.Component?(this.value_=a.value_,this.type_=a.type_):(this.value_=a?"object"===typeof a&&"undefined"!==typeof ArrayBuffer&&a instanceof ArrayBuffer?new Blob(new Buffer(new Uint8Array(a)),!1):"object"===typeof a&&a instanceof Blob?a:new Blob(a):new Blob([]),this.type_=Name.Component.ComponentType.GENERIC)};Name.Component.ComponentType={IMPLICIT_SHA256_DIGEST:1,GENERIC:8};Name.Component.prototype.getValue=function(){return this.value_};
+Name.Component.prototype.getValueAsBuffer=function(){return this.value_.buf()};Object.defineProperty(Name.Component.prototype,"value",{get:function(){return this.getValueAsBuffer()}});Name.Component.prototype.toEscapedString=function(){return this.type_===Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST?"sha256digest="+this.value_.toHex():Name.toEscapedString(this.value_.buf())};Name.Component.prototype.isSegment=function(){return 1<=this.value_.size()&&0==this.value_.buf()[0]&&this.isGeneric()};
+Name.Component.prototype.isSegmentOffset=function(){return 1<=this.value_.size()&&251==this.value_.buf()[0]&&this.isGeneric()};Name.Component.prototype.isVersion=function(){return 1<=this.value_.size()&&253==this.value_.buf()[0]&&this.isGeneric()};Name.Component.prototype.isTimestamp=function(){return 1<=this.value_.size()&&252==this.value_.buf()[0]&&this.isGeneric()};Name.Component.prototype.isSequenceNumber=function(){return 1<=this.value_.size()&&254==this.value_.buf()[0]&&this.isGeneric()};
+Name.Component.prototype.isGeneric=function(){return this.type_===Name.Component.ComponentType.GENERIC};Name.Component.prototype.isImplicitSha256Digest=function(){return this.type_===Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST};Name.Component.prototype.toNumber=function(){return DataUtils.bigEndianToUnsignedInt(this.value_.buf())};
+Name.Component.prototype.toNumberWithMarker=function(a){if(0==this.value_.size()||this.value_.buf()[0]!=a)throw Error("Name component does not begin with the expected marker");return DataUtils.bigEndianToUnsignedInt(this.value_.buf().slice(1))};Name.Component.prototype.toSegment=function(){return this.toNumberWithMarker(0)};Name.Component.prototype.toSegmentOffset=function(){return this.toNumberWithMarker(251)};Name.Component.prototype.toVersion=function(){return this.toNumberWithMarker(253)};
+Name.Component.prototype.toTimestamp=function(){return this.toNumberWithMarker(252)};Name.Component.prototype.toSequenceNumber=function(){return this.toNumberWithMarker(254)};Name.Component.fromNumber=function(a){var b=new TlvEncoder(8);b.writeNonNegativeInteger(a);return new Name.Component(new Blob(b.getOutput(),!1))};
+Name.Component.fromNumberWithMarker=function(a,b){var c=new TlvEncoder(9);c.writeNonNegativeInteger(a);c.writeNonNegativeInteger(b);return new Name.Component(new Blob(c.getOutput(),!1))};Name.Component.fromSegment=function(a){return Name.Component.fromNumberWithMarker(a,0)};Name.Component.fromSegmentOffset=function(a){return Name.Component.fromNumberWithMarker(a,251)};Name.Component.fromVersion=function(a){return Name.Component.fromNumberWithMarker(a,253)};
+Name.Component.fromTimestamp=function(a){return Name.Component.fromNumberWithMarker(a,252)};Name.Component.fromSequenceNumber=function(a){return Name.Component.fromNumberWithMarker(a,254)};
+Name.Component.fromImplicitSha256Digest=function(a){digestBlob="object"===typeof a&&a instanceof Blob?a:new Blob(a,!0);if(32!==digestBlob.size())throw new DecodingException("Name.Component.fromImplicitSha256Digest: The digest length must be 32 bytes");a=new Name.Component(digestBlob);a.type_=Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST;return a};
+Name.Component.prototype.getSuccessor=function(){for(var a=new Buffer(this.value_.size()+1),b=!0,c=this.value_.size()-1;0<=c;--c)b?(a[c]=this.value_.buf()[c]+1&255,b=0===a[c]):a[c]=this.value_.buf()[c];b?a[a.length-1]=0:a=a.slice(0,this.value_.size());return new Name.Component(new Blob(a,!1))};Name.Component.prototype.equals=function(a){return"object"===typeof a&&a instanceof Name.Component&&this.value_.equals(a.value_)&&this.type_===a.type_};
+Name.Component.prototype.compare=function(a){return this.type_<a.type_?-1:this.type_>a.type_?1:Name.Component.compareBuffers(this.value_.buf(),a.value_.buf())};Name.Component.compareBuffers=function(a,b){if(a.length<b.length)return-1;if(a.length>b.length)return 1;for(var c=0;c<a.length;++c){if(a[c]<b[c])return-1;if(a[c]>b[c])return 1}return 0};Name.prototype.getName=function(){return this.toUri()};
+Name.createNameArray=function(a){a=a.trim();if(0>=a.length)return[];var b=a.indexOf(":");if(0<=b){var c=a.indexOf("/");if(0>c||b<c)a=a.substr(b+1,a.length-b-1).trim()}if("/"==a[0])if(2<=a.length&&"/"==a[1]){b=a.indexOf("/",2);if(0>b)return[];a=a.substr(b+1,a.length-b-1).trim()}else a=a.substr(1,a.length-1).trim();a=a.split("/");for(b=0;b<a.length;++b)"sha256digest="==a[b].substr(0,13)?(c=a[b].substr(13).trim(),c=Name.Component.fromImplicitSha256Digest(new Blob(new Buffer(c,"hex")),!1)):c=new Name.Component(Name.fromEscapedString(a[b])),
+c.getValue().isNull()?(a.splice(b,1),--b):a[b]=c;return a};Name.prototype.set=function(a){this.components=Name.createNameArray(a);++this.changeCount};
+Name.prototype.append=function(a){if("object"==typeof a&&a instanceof Name){a=a==this?this.components.slice(0,this.components.length):a.components;for(var b=0;b<a.length;++b)this.components.push(new Name.Component(a[b]))}else"object"===typeof a&&a instanceof Name.Component?this.components.push(a):this.components.push(new Name.Component(a));++this.changeCount;return this};Name.prototype.add=function(a){return this.append(a)};Name.prototype.clear=function(){this.components=[];++this.changeCount};
+Name.prototype.toUri=function(a){if(0==this.size())return a?"ndn:/":"/";a=a?"ndn:":"";for(var b=0;b<this.size();++b)a+="/"+this.components[b].toEscapedString();return a};Name.prototype.to_uri=function(){return this.toUri()};Name.prototype.toString=function(){return this.toUri()};Name.prototype.appendSegment=function(a){return this.append(Name.Component.fromSegment(a))};Name.prototype.appendSegmentOffset=function(a){return this.append(Name.Component.fromSegmentOffset(a))};
+Name.prototype.appendVersion=function(a){return this.append(Name.Component.fromVersion(a))};Name.prototype.appendTimestamp=function(a){return this.append(Name.Component.fromTimestamp(a))};Name.prototype.appendSequenceNumber=function(a){return this.append(Name.Component.fromSequenceNumber(a))};Name.prototype.appendImplicitSha256Digest=function(a){return this.append(Name.Component.fromImplicitSha256Digest(a))};Name.prototype.addSegment=function(a){return this.appendSegment(a)};
+Name.prototype.getSubName=function(a,b){0>a&&(a=this.components.length- -a);void 0==b&&(b=this.components.length-a);for(var c=new Name,d=a+b,e=a;e<d&&e<this.components.length;++e)c.components.push(this.components[e]);return c};Name.prototype.getPrefix=function(a){return 0>a?this.getSubName(0,this.components.length+a):this.getSubName(0,a)};Name.prototype.cut=function(a){return new Name(this.components.slice(0,this.components.length-a))};Name.prototype.size=function(){return this.components.length};
+Name.prototype.get=function(a){if(0<=a){if(a>=this.components.length)throw Error("Name.get: Index is out of bounds");return this.components[a]}if(a<-this.components.length)throw Error("Name.get: Index is out of bounds");return this.components[this.components.length- -a]};Name.prototype.getComponentCount=function(){return this.components.length};Name.prototype.getComponent=function(a){return new Buffer(this.components[a].getValue().buf())};
+Name.prototype.indexOfFileName=function(){for(var a=this.size()-1;0<=a;--a){var b=this.components[a].getValue().buf();if(!(0>=b.length||0==b[0]||192==b[0]||193==b[0]||245<=b[0]&&255>=b[0]))return a}return-1};Name.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeName(this)};Name.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeName(this,a.buf(),!1):b.decodeName(this,a,!0)};
+Name.prototype.compare=function(a,b,c,d,e){a instanceof Name&&(c=a,a=0,b=this.size());void 0==d&&(d=0);void 0==e&&(e=c.size());0>a&&(a=this.size()- -a);0>d&&(d=c.size()- -d);b=Math.min(b,this.size()-a);e=Math.min(e,c.size()-d);for(var f=Math.min(b,e),g=0;g<f;++g){var h=this.components[a+g].compare(c.components[d+g]);if(0!=h)return h}return b<e?-1:b>e?1:0};
+Name.prototype.equals=function(a){if(this.components.length!=a.components.length)return!1;for(var b=this.components.length-1;0<=b;--b)if(!this.components[b].equals(a.components[b]))return!1;return!0};Name.prototype.equalsName=function(a){return this.equals(a)};Name.prototype.getContentDigestValue=function(){for(var a=this.size()-1;0<=a;--a){var b=Name.getComponentContentDigestValue(this.components[a]);if(null!=b)return b}return null};
+Name.getComponentContentDigestValue=function(a){"object"==typeof a&&a instanceof Name.Component&&(a=a.getValue().buf());return a.length==Name.ContentDigestPrefix.length+32+Name.ContentDigestSuffix.length&&DataUtils.arraysEqual(a.slice(0,Name.ContentDigestPrefix.length),Name.ContentDigestPrefix)&&DataUtils.arraysEqual(a.slice(a.length-Name.ContentDigestSuffix.length,a.length),Name.ContentDigestSuffix)?a.slice(Name.ContentDigestPrefix.length,Name.ContentDigestPrefix.length+32):null};
+Name.ContentDigestPrefix=new Buffer([193,46,77,46,71,193,1,170,2,133]);Name.ContentDigestSuffix=new Buffer([0]);
+Name.toEscapedString=function(a){"object"==typeof a&&a instanceof Name.Component?a=a.getValue().buf():"object"===typeof a&&a instanceof Blob&&(a=a.buf());for(var b="",c=!1,d=0;d<a.length;++d)if(46!=a[d]){c=!0;break}if(c)for(d=0;d<a.length;++d)c=a[d],b=48<=c&&57>=c||65<=c&&90>=c||97<=c&&122>=c||43==c||45==c||46==c||95==c?b+String.fromCharCode(c):b+("%"+(16>c?"0":"")+c.toString(16).toUpperCase());else for(b="...",d=0;d<a.length;++d)b+=".";return b};
+Name.fromEscapedString=function(a){a=unescape(a.trim());return null==a.match(/[^.]/)?2>=a.length?new Blob:new Blob(DataUtils.toNumbersFromString(a.substr(3,a.length-3)),!1):new Blob(DataUtils.toNumbersFromString(a),!1)};Name.fromEscapedStringAsBuffer=function(a){return Name.fromEscapedString(a).buf()};Name.prototype.getSuccessor=function(){if(0==this.size()){var a=new Name;a.append(new Blob(new Buffer([0]),!1));return a}return this.getPrefix(-1).append(this.get(-1).getSuccessor())};
+Name.prototype.match=function(a){var b=this.components;a=a.components;if(b.length>a.length)return!1;for(var c=b.length-1;0<=c;--c)if(!b[c].equals(a[c]))return!1;return!0};Name.prototype.isPrefixOf=function(a){return this.match(a)};Name.prototype.getChangeCount=function(){return this.changeCount};
+var TlvEncoder=require("./encoding/tlv/tlv-encoder.js").TlvEncoder,WireFormat=require("./encoding/wire-format.js").WireFormat,Blob=require("./util/blob.js").Blob,ChangeCounter=require("./util/change-counter.js").ChangeCounter,Name=require("./name.js").Name,KeyLocatorType={KEYNAME:1,KEY_LOCATOR_DIGEST:2};exports.KeyLocatorType=KeyLocatorType;
+var KeyLocator=function KeyLocator(b,c){"object"===typeof b&&b instanceof KeyLocator?(this.type_=b.type_,this.keyName_=new ChangeCounter(new Name(b.getKeyName())),this.keyData_=b.keyData_):(this.type_=c,this.keyName_=new ChangeCounter(new Name),this.keyData_=new Blob,c==KeyLocatorType.KEYNAME?this.keyName_.set("object"===typeof b&&b instanceof Name?new Name(b):new Name):c==KeyLocatorType.KEY_LOCATOR_DIGEST&&(this.keyData_=new Blob(b)));this.changeCount_=0};exports.KeyLocator=KeyLocator;
+KeyLocator.prototype.getType=function(){return this.type_};KeyLocator.prototype.getKeyName=function(){return this.keyName_.get()};KeyLocator.prototype.getKeyData=function(){return this.keyData_};KeyLocator.prototype.getKeyDataAsBuffer=function(){return this.getKeyData().buf()};KeyLocator.prototype.setType=function(a){this.type_=a;++this.changeCount_};KeyLocator.prototype.setKeyName=function(a){this.keyName_.set("object"===typeof a&&a instanceof Name?new Name(a):new Name);++this.changeCount_};
+KeyLocator.prototype.setKeyData=function(a){this.keyData_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};KeyLocator.prototype.clear=function(){this.type_=null;this.keyName_.set(new Name);this.keyData_=new Blob;++this.changeCount_};
+KeyLocator.prototype.equals=function(a){if(this.type_!=a.type_)return!1;if(this.type_==KeyLocatorType.KEYNAME){if(!this.getKeyName().equals(a.getKeyName()))return!1}else if(this.type_==KeyLocatorType.KEY_LOCATOR_DIGEST&&!this.getKeyData().equals(a.getKeyData()))return!1;return!0};KeyLocator.canGetFromSignature=function(a){return a instanceof Sha256WithRsaSignature||a instanceof Sha256WithEcdsaSignature||a instanceof HmacWithSha256Signature};
+KeyLocator.getFromSignature=function(a){if(a instanceof Sha256WithRsaSignature||a instanceof Sha256WithEcdsaSignature||a instanceof HmacWithSha256Signature)return a.getKeyLocator();throw Error("KeyLocator.getFromSignature: Signature type does not have a KeyLocator");};KeyLocator.prototype.getChangeCount=function(){this.keyName_.checkChanged()&&++this.changeCount_;return this.changeCount_};Object.defineProperty(KeyLocator.prototype,"type",{get:function(){return this.getType()},set:function(a){this.setType(a)}});
+Object.defineProperty(KeyLocator.prototype,"keyData",{get:function(){return this.getKeyDataAsBuffer()},set:function(a){this.setKeyData(a)}});var Sha256WithRsaSignature=require("./sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("./sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,HmacWithSha256Signature=require("./hmac-with-sha256-signature.js").HmacWithSha256Signature,Name=require("./name.js").Name,ContentType={BLOB:0,LINK:1,KEY:2,NACK:3,OTHER_CODE:32767};
+exports.ContentType=ContentType;
+var MetaInfo=function MetaInfo(b,c,d,e,f,g){if(c)throw Error("MetaInfo constructor: timestamp support has been removed.");if(e)throw Error("MetaInfo constructor: locator support has been removed.");if("object"===typeof b&&b instanceof MetaInfo)this.publisher_=b.publisher_,this.type_=b.type_,this.otherTypeCode_=b.otherTypeCode_,this.freshnessPeriod_=b.freshnessPeriod_,this.finalBlockId_=b.finalBlockId_;else{if(b)throw Error("MetaInfo constructor: publisher support has been removed.");this.type=null==
+d||0>d?ContentType.BLOB:d;this.otherTypeCode_=-1;this.freshnessSeconds=f;this.finalBlockID=g}this.changeCount_=0};exports.MetaInfo=MetaInfo;MetaInfo.prototype.getType=function(){return this.type_};MetaInfo.prototype.getOtherTypeCode=function(){return this.otherTypeCode_};MetaInfo.prototype.getFreshnessPeriod=function(){return this.freshnessPeriod_};MetaInfo.prototype.getFinalBlockId=function(){return this.finalBlockId_};MetaInfo.prototype.getFinalBlockID=function(){return this.getFinalBlockId()};
+MetaInfo.prototype.getFinalBlockIDAsBuffer=function(){return this.finalBlockId_.getValue().buf()};MetaInfo.prototype.setType=function(a){this.type_=null==a||0>a?ContentType.BLOB:a;++this.changeCount_};MetaInfo.prototype.setOtherTypeCode=function(a){if(0>a)throw Error("MetaInfo other type code must be non-negative");this.otherTypeCode_=a;++this.changeCount_};MetaInfo.prototype.setFreshnessPeriod=function(a){this.freshnessPeriod_=null==a||0>a?null:a;++this.changeCount_};
+MetaInfo.prototype.setFinalBlockId=function(a){this.finalBlockId_="object"===typeof a&&a instanceof Name.Component?a:new Name.Component(a);++this.changeCount_};MetaInfo.prototype.setFinalBlockID=function(a){this.setFinalBlockId(a)};MetaInfo.prototype.getChangeCount=function(){return this.changeCount_};Object.defineProperty(MetaInfo.prototype,"type",{get:function(){return this.getType()},set:function(a){this.setType(a)}});
+Object.defineProperty(MetaInfo.prototype,"freshnessSeconds",{get:function(){return null==this.freshnessPeriod_||0>this.freshnessPeriod_?null:this.freshnessPeriod_/1E3},set:function(a){this.freshnessPeriod_=null==a||0>a?null:1E3*a;++this.changeCount_}});Object.defineProperty(MetaInfo.prototype,"finalBlockID",{get:function(){return this.getFinalBlockIDAsBuffer()},set:function(a){this.setFinalBlockId(a)}});Blob=require("./util/blob.js").Blob;ChangeCounter=require("./util/change-counter.js").ChangeCounter;
+KeyLocator=require("./key-locator.js").KeyLocator;Sha256WithEcdsaSignature=function Sha256WithEcdsaSignature(b){"object"===typeof b&&b instanceof Sha256WithEcdsaSignature?(this.keyLocator_=new ChangeCounter(new KeyLocator(b.getKeyLocator())),this.signature_=b.signature_):(this.keyLocator_=new ChangeCounter(new KeyLocator),this.signature_=new Blob);this.changeCount_=0};exports.Sha256WithEcdsaSignature=Sha256WithEcdsaSignature;Sha256WithEcdsaSignature.prototype.clone=function(){return new Sha256WithEcdsaSignature(this)};
+Sha256WithEcdsaSignature.prototype.getKeyLocator=function(){return this.keyLocator_.get()};Sha256WithEcdsaSignature.prototype.getSignature=function(){return this.signature_};Sha256WithEcdsaSignature.prototype.setKeyLocator=function(a){this.keyLocator_.set("object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator);++this.changeCount_};Sha256WithEcdsaSignature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};
+Sha256WithEcdsaSignature.prototype.getChangeCount=function(){this.keyLocator_.checkChanged()&&++this.changeCount_;return this.changeCount_};Blob=require("./util/blob.js").Blob;ChangeCounter=require("./util/change-counter.js").ChangeCounter;KeyLocator=require("./key-locator.js").KeyLocator;
+Sha256WithRsaSignature=function Sha256WithRsaSignature(b){"object"===typeof b&&b instanceof Sha256WithRsaSignature?(this.keyLocator_=new ChangeCounter(new KeyLocator(b.getKeyLocator())),this.signature_=b.signature_):(this.keyLocator_=new ChangeCounter(new KeyLocator),this.signature_=new Blob);this.changeCount_=0};exports.Sha256WithRsaSignature=Sha256WithRsaSignature;Sha256WithRsaSignature.prototype.clone=function(){return new Sha256WithRsaSignature(this)};
+Sha256WithRsaSignature.prototype.getKeyLocator=function(){return this.keyLocator_.get()};Sha256WithRsaSignature.prototype.getSignature=function(){return this.signature_};Sha256WithRsaSignature.prototype.getSignatureAsBuffer=function(){return this.signature_.buf()};Sha256WithRsaSignature.prototype.setKeyLocator=function(a){this.keyLocator_.set("object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator);++this.changeCount_};
+Sha256WithRsaSignature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};Sha256WithRsaSignature.prototype.getChangeCount=function(){this.keyLocator_.checkChanged()&&++this.changeCount_;return this.changeCount_};Object.defineProperty(Sha256WithRsaSignature.prototype,"keyLocator",{get:function(){return this.getKeyLocator()},set:function(a){this.setKeyLocator(a)}});
+Object.defineProperty(Sha256WithRsaSignature.prototype,"signature",{get:function(){return this.getSignatureAsBuffer()},set:function(a){this.setSignature(a)}});
+var Blob=require("./util/blob.js").Blob,GenericSignature=function GenericSignature(b){"object"===typeof b&&b instanceof GenericSignature?(this.signature_=b.signature_,this.signatureInfoEncoding_=b.signatureInfoEncoding_,this.typeCode_=b.typeCode_):(this.signature_=new Blob,this.signatureInfoEncoding_=new Blob,this.typeCode_=null);this.changeCount_=0};exports.GenericSignature=GenericSignature;GenericSignature.prototype.clone=function(){return new GenericSignature(this)};
+GenericSignature.prototype.getSignature=function(){return this.signature_};GenericSignature.prototype.getSignatureAsBuffer=function(){return this.signature_.buf()};GenericSignature.prototype.getSignatureInfoEncoding=function(){return this.signatureInfoEncoding_};GenericSignature.prototype.getTypeCode=function(){return this.typeCode_};GenericSignature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};
+GenericSignature.prototype.setSignatureInfoEncoding=function(a,b){this.signatureInfoEncoding_="object"===typeof a&&a instanceof Blob?a:new Blob(a);this.typeCode_=b;++this.changeCount_};GenericSignature.prototype.getChangeCount=function(){return this.changeCount_};Object.defineProperty(GenericSignature.prototype,"signature",{get:function(){return this.getSignatureAsBuffer()},set:function(a){this.setSignature(a)}});Blob=require("./util/blob.js").Blob;ChangeCounter=require("./util/change-counter.js").ChangeCounter;
+KeyLocator=require("./key-locator.js").KeyLocator;HmacWithSha256Signature=function HmacWithSha256Signature(b){"object"===typeof b&&b instanceof HmacWithSha256Signature?(this.keyLocator_=new ChangeCounter(new KeyLocator(b.getKeyLocator())),this.signature_=b.signature_):(this.keyLocator_=new ChangeCounter(new KeyLocator),this.signature_=new Blob);this.changeCount_=0};exports.HmacWithSha256Signature=HmacWithSha256Signature;HmacWithSha256Signature.prototype.clone=function(){return new HmacWithSha256Signature(this)};
+HmacWithSha256Signature.prototype.getKeyLocator=function(){return this.keyLocator_.get()};HmacWithSha256Signature.prototype.getSignature=function(){return this.signature_};HmacWithSha256Signature.prototype.getSignatureAsBuffer=function(){return this.signature_.buf()};HmacWithSha256Signature.prototype.setKeyLocator=function(a){this.keyLocator_.set("object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator);++this.changeCount_};
+HmacWithSha256Signature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};HmacWithSha256Signature.prototype.getChangeCount=function(){this.keyLocator_.checkChanged()&&++this.changeCount_;return this.changeCount_};Object.defineProperty(HmacWithSha256Signature.prototype,"keyLocator",{get:function(){return this.getKeyLocator()},set:function(a){this.setKeyLocator(a)}});
+Object.defineProperty(HmacWithSha256Signature.prototype,"signature",{get:function(){return this.getSignatureAsBuffer()},set:function(a){this.setSignature(a)}});var Blob=require("./util/blob.js").Blob,DigestSha256Signature=function DigestSha256Signature(b){this.signature_="object"===typeof b&&b instanceof DigestSha256Signature?b.signature_:new Blob;this.changeCount_=0};exports.DigestSha256Signature=DigestSha256Signature;DigestSha256Signature.prototype.clone=function(){return new DigestSha256Signature(this)};
+DigestSha256Signature.prototype.getSignature=function(){return this.signature_};DigestSha256Signature.prototype.setSignature=function(a){this.signature_="object"===typeof a&&a instanceof Blob?a:new Blob(a);++this.changeCount_};DigestSha256Signature.prototype.getChangeCount=function(){return this.changeCount_};Object.defineProperty(DigestSha256Signature.prototype,"signature",{get:function(){return this.getSignature()},set:function(a){this.setSignature(a)}});
+var Blob=require("./util/blob.js").Blob,SignedBlob=require("./util/signed-blob.js").SignedBlob,ChangeCounter=require("./util/change-counter.js").ChangeCounter,Name=require("./name.js").Name,Sha256WithRsaSignature=require("./sha256-with-rsa-signature.js").Sha256WithRsaSignature,MetaInfo=require("./meta-info.js").MetaInfo,IncomingFaceId=require("./lp/incoming-face-id.js").IncomingFaceId,WireFormat=require("./encoding/wire-format.js").WireFormat,Crypto=require("./crypto.js"),Data=function Data(b,c,d){b instanceof
+Data?(this.name_=new ChangeCounter(new Name(b.getName())),this.metaInfo_=new ChangeCounter(new MetaInfo(b.getMetaInfo())),this.signature_=new ChangeCounter(b.getSignature().clone()),this.content_=b.content_,this.defaultWireEncoding_=b.getDefaultWireEncoding(),this.defaultFullName_=b.defaultFullName_,this.defaultWireEncodingFormat_=b.defaultWireEncodingFormat_):(this.name_="string"===typeof b?new ChangeCounter(new Name(b)):new ChangeCounter("object"===typeof b&&b instanceof Name?new Name(b):new Name),
+"object"===typeof c&&c instanceof MetaInfo?(b=c,c=d):b=null,this.metaInfo_=new ChangeCounter("object"===typeof b&&b instanceof MetaInfo?new MetaInfo(b):new MetaInfo),this.content_="object"===typeof c&&c instanceof Blob?c:new Blob(c,!0),this.signature_=new ChangeCounter(new Sha256WithRsaSignature),this.defaultWireEncoding_=new SignedBlob,this.defaultFullName_=new Name,this.defaultWireEncodingFormat_=null);this.changeCount_=this.getDefaultWireEncodingChangeCount_=0;this.lpPacket_=null};
+exports.Data=Data;Data.prototype.getName=function(){return this.name_.get()};Data.prototype.getMetaInfo=function(){return this.metaInfo_.get()};Data.prototype.getSignature=function(){return this.signature_.get()};Data.prototype.getContent=function(){return this.content_};Data.prototype.getContentAsBuffer=function(){return this.content_.buf()};
+Data.prototype.getDefaultWireEncoding=function(){this.getDefaultWireEncodingChangeCount_!=this.getChangeCount()&&(this.defaultWireEncoding_=new SignedBlob,this.defaultWireEncodingFormat_=null,this.getDefaultWireEncodingChangeCount_=this.getChangeCount());return this.defaultWireEncoding_};Data.prototype.getDefaultWireEncodingFormat=function(){return this.defaultWireEncodingFormat_};
+Data.prototype.getIncomingFaceId=function(){var a=null===this.lpPacket_?null:IncomingFaceId.getFirstHeader(this.lpPacket_);return null===a?null:a.getFaceId()};
+Data.prototype.getFullName=function(a){a=a||WireFormat.getDefaultWireFormat();if(!this.getDefaultWireEncoding().isNull()&&0<this.defaultFullName_.size()&&this.getDefaultWireEncodingFormat()==a)return this.defaultFullName_;var b=new Name(this.getName()),c=Crypto.createHash("sha256");c.update(this.wireEncode(a).buf());b.appendImplicitSha256Digest(new Blob(c.digest(),!1));a==WireFormat.getDefaultWireFormat()&&(this.defaultFullName_=b);return b};
+Data.prototype.setName=function(a){this.name_.set("object"===typeof a&&a instanceof Name?new Name(a):new Name);++this.changeCount_;return this};Data.prototype.setMetaInfo=function(a){this.metaInfo_.set("object"===typeof a&&a instanceof MetaInfo?new MetaInfo(a):new MetaInfo);++this.changeCount_;return this};Data.prototype.setSignature=function(a){this.signature_.set(null==a?new Sha256WithRsaSignature:a.clone());++this.changeCount_;return this};
+Data.prototype.setContent=function(a){this.content_="object"===typeof a&&a instanceof Blob?a:new Blob(a,!0);++this.changeCount_;return this};
+Data.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();if(!this.getDefaultWireEncoding().isNull()&&this.getDefaultWireEncodingFormat()==a)return this.getDefaultWireEncoding();var b=a.encodeData(this),b=new SignedBlob(b.encoding,b.signedPortionBeginOffset,b.signedPortionEndOffset);a==WireFormat.getDefaultWireFormat()&&this.setDefaultWireEncoding(b,WireFormat.getDefaultWireFormat());return b};
+Data.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c;c="object"===typeof a&&a instanceof Blob?b.decodeData(this,a.buf(),!1):b.decodeData(this,a,!0);b==WireFormat.getDefaultWireFormat()?this.setDefaultWireEncoding(new SignedBlob(new Blob(a,!0),c.signedPortionBeginOffset,c.signedPortionEndOffset),WireFormat.getDefaultWireFormat()):this.setDefaultWireEncoding(new SignedBlob,null)};Data.prototype.setLpPacket=function(a){this.lpPacket_=a;return this};
+Data.prototype.getChangeCount=function(){var a=this.name_.checkChanged(),a=this.metaInfo_.checkChanged()||a;(a=this.signature_.checkChanged()||a)&&++this.changeCount_;return this.changeCount_};Data.prototype.setDefaultWireEncoding=function(a,b){this.defaultWireEncoding_=a;this.defaultWireEncodingFormat_=b;this.getDefaultWireEncodingChangeCount_=this.getChangeCount()};Object.defineProperty(Data.prototype,"name",{get:function(){return this.getName()},set:function(a){this.setName(a)}});
+Object.defineProperty(Data.prototype,"metaInfo",{get:function(){return this.getMetaInfo()},set:function(a){this.setMetaInfo(a)}});Object.defineProperty(Data.prototype,"signature",{get:function(){return this.getSignature()},set:function(a){this.setSignature(a)}});Object.defineProperty(Data.prototype,"content",{get:function(){return this.getContentAsBuffer()},set:function(a){this.setContent(a)}});function SecurityException(a){if(a)return a.__proto__=SecurityException.prototype,a}
+SecurityException.prototype=Error();SecurityException.prototype.name="SecurityException";exports.SecurityException=SecurityException;function UnrecognizedKeyFormatException(a){SecurityException.call(this,a)}UnrecognizedKeyFormatException.prototype=new SecurityException;UnrecognizedKeyFormatException.prototype.name="UnrecognizedKeyFormatException";exports.UnrecognizedKeyFormatException=UnrecognizedKeyFormatException;function UnrecognizedDigestAlgorithmException(a){SecurityException.call(this,a)}
+UnrecognizedDigestAlgorithmException.prototype=new SecurityException;UnrecognizedDigestAlgorithmException.prototype.name="UnrecognizedDigestAlgorithmException";exports.UnrecognizedDigestAlgorithmException=UnrecognizedDigestAlgorithmException;var KeyType=function(){};exports.KeyType=KeyType;KeyType.RSA=0;KeyType.ECDSA=1;KeyType.AES=128;var KeyClass=function(){};exports.KeyClass=KeyClass;KeyClass.PUBLIC=1;KeyClass.PRIVATE=2;KeyClass.SYMMETRIC=3;var DigestAlgorithm=function(){};
+exports.DigestAlgorithm=DigestAlgorithm;DigestAlgorithm.SHA256=1;var KeyType=require("./security-types.js").KeyType,KeyParams=function(a){this.keyType=a};exports.KeyParams=KeyParams;KeyParams.prototype.getKeyType=function(){return this.keyType};var RsaKeyParams=function RsaKeyParams(b){KeyParams.call(this,RsaKeyParams.getType());null==b&&(b=RsaKeyParams.getDefaultSize());this.size=b};RsaKeyParams.prototype=new KeyParams;RsaKeyParams.prototype.name="RsaKeyParams";exports.RsaKeyParams=RsaKeyParams;
+RsaKeyParams.prototype.getKeySize=function(){return this.size};RsaKeyParams.getDefaultSize=function(){return 2048};RsaKeyParams.getType=function(){return KeyType.RSA};var EcdsaKeyParams=function EcdsaKeyParams(b){KeyParams.call(this,EcdsaKeyParams.getType());null==b&&(b=EcdsaKeyParams.getDefaultSize());this.size=b};EcdsaKeyParams.prototype=new KeyParams;EcdsaKeyParams.prototype.name="EcdsaKeyParams";exports.EcdsaKeyParams=EcdsaKeyParams;EcdsaKeyParams.prototype.getKeySize=function(){return this.size};
+EcdsaKeyParams.getDefaultSize=function(){return 256};EcdsaKeyParams.getType=function(){return KeyType.ECDSA};var AesKeyParams=function AesKeyParams(b){KeyParams.call(this,AesKeyParams.getType());null==b&&(b=AesKeyParams.getDefaultSize());this.size=b};AesKeyParams.prototype=new KeyParams;AesKeyParams.prototype.name="AesKeyParams";exports.AesKeyParams=AesKeyParams;AesKeyParams.prototype.getKeySize=function(){return this.size};AesKeyParams.getDefaultSize=function(){return 64};AesKeyParams.getType=function(){return KeyType.AES};
+var Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,DerDecodingException=require("../../encoding/der/der-decoding-exception.js").DerDecodingException,DerNode=require("../../encoding/der/der-node.js").DerNode,SecurityException=require("../security-exception.js").SecurityException,UnrecognizedKeyFormatException=require("../security-exception.js").UnrecognizedKeyFormatException,KeyType=require("../security-types.js").KeyType,DigestAlgorithm=require("../security-types.js").DigestAlgorithm,
+PublicKey=function PublicKey(b){if(b){this.keyDer=b;var c=null;try{var d=DerNode.parse(b.buf(),0).getChildren(),c=DerNode.getSequence(d,0).getChildren()[0].toVal()}catch(e){throw new UnrecognizedKeyFormatException(Error("PublicKey.decodeKeyType: Error decoding the public key: "+e.message));}c==PublicKey.RSA_ENCRYPTION_OID?this.keyType=KeyType.RSA:c==PublicKey.EC_ENCRYPTION_OID&&(this.keyType=KeyType.ECDSA)}else this.keyDer=new Blob,this.keyType=null};exports.PublicKey=PublicKey;
+PublicKey.prototype.toDer=function(){return DerNode.parse(this.keyDer.buf())};PublicKey.prototype.getKeyType=function(){return this.keyType};PublicKey.prototype.getDigest=function(a){void 0==a&&(a=DigestAlgorithm.SHA256);if(a==DigestAlgorithm.SHA256)return a=Crypto.createHash("sha256"),a.update(this.keyDer.buf()),new Blob(a.digest(),!1);throw new SecurityException(Error("Wrong format!"));};PublicKey.prototype.getKeyDer=function(){return this.keyDer};PublicKey.RSA_ENCRYPTION_OID="1.2.840.113549.1.1.1";
+PublicKey.EC_ENCRYPTION_OID="1.2.840.10045.2.1";var DerNode=require("../../encoding/der/der-node.js").DerNode,OID=require("../../encoding/oid.js").OID,CertificateExtension=function(a,b,c){this.extensionId="string"===typeof a?new OID(a):a;this.isCritical=b;this.extensionValue=c};exports.CertificateExtension=CertificateExtension;
+CertificateExtension.prototype.toDer=function(){var a=new DerNode.DerSequence,b=new DerNode.DerOid(this.extensionId),c=new DerNode.DerBoolean(this.isCritical),d=new DerNode.DerOctetString(this.extensionValue.buf());a.addChild(b);a.addChild(c);a.addChild(d);a.getSize();return a};CertificateExtension.prototype.toDerBlob=function(){return this.toDer().encode()};CertificateExtension.prototype.getOid=function(){return this.extensionId};CertificateExtension.prototype.getIsCritical=function(){return this.isCritical};
+CertificateExtension.prototype.getValue=function(){return this.extensionValue};var Blob=require("../../util/blob.js").Blob,OID=require("../../encoding/oid.js").OID,DerNode=require("../../encoding/der/der-node.js").DerNode,CertificateSubjectDescription=function(a,b){this.oid="string"===typeof a?new OID(a):a;this.value=b};exports.CertificateSubjectDescription=CertificateSubjectDescription;
+CertificateSubjectDescription.prototype.toDer=function(){var a=new DerNode.DerSequence,b=new DerNode.DerOid(this.oid),c=new DerNode.DerPrintableString((new Blob(this.value)).buf());a.addChild(b);a.addChild(c);return a};CertificateSubjectDescription.prototype.getOidString=function(){return this.oid.toString()};CertificateSubjectDescription.prototype.getValue=function(){return this.value};
+var Data=require("../../data.js").Data,ContentType=require("../../meta-info.js").ContentType,WireFormat=require("../../encoding/wire-format.js").WireFormat,DerNode=require("../../encoding/der/der-node.js").DerNode,KeyType=require("../../security/security-types.js").KeyType,PublicKey=require("./public-key.js").PublicKey,CertificateSubjectDescription=require("./certificate-subject-description.js").CertificateSubjectDescription,CertificateExtension=require("./certificate-extension.js").CertificateExtension,
+Certificate=function(a){void 0!=a?Data.call(this,a):Data.call(this);this.subjectDescriptionList=[];this.extensionList=[];this.notBefore=Number.MAX_VALUE;this.notAfter=-Number.MAX_VALUE;this.key=new PublicKey;void 0!=a&&this.decode()};Certificate.prototype=new Data;Certificate.prototype.name="Certificate";exports.Certificate=Certificate;Certificate.prototype.encode=function(){var a=this.toDer();this.setContent(a.encode());this.getMetaInfo().setType(ContentType.KEY)};
+Certificate.prototype.addSubjectDescription=function(a){this.subjectDescriptionList.push(a)};Certificate.prototype.getSubjectDescriptionList=function(){return this.subjectDescriptionList};Certificate.prototype.addExtension=function(a){this.extensionList.push(a)};Certificate.prototype.getExtensionList=function(){return this.extensionList};Certificate.prototype.setNotBefore=function(a){this.notBefore=a};Certificate.prototype.getNotBefore=function(){return this.notBefore};
+Certificate.prototype.setNotAfter=function(a){this.notAfter=a};Certificate.prototype.getNotAfter=function(){return this.notAfter};Certificate.prototype.setPublicKeyInfo=function(a){this.key=a};Certificate.prototype.getPublicKeyInfo=function(){return this.key};Certificate.prototype.isTooEarly=function(){return(new Date).getTime()<this.notBefore};Certificate.prototype.isTooLate=function(){return(new Date).getTime()>this.notAfter};
+Certificate.prototype.toDer=function(){var a=new DerNode.DerSequence,b=new DerNode.DerSequence,c=new DerNode.DerGeneralizedTime(this.notBefore),d=new DerNode.DerGeneralizedTime(this.notAfter);b.addChild(c);b.addChild(d);a.addChild(b);c=new DerNode.DerSequence;for(b=0;b<this.subjectDescriptionList.length;++b)c.addChild(this.subjectDescriptionList[b].toDer());a.addChild(c);a.addChild(this.key.toDer());if(0<this.extensionList.length){c=new DerNode.DerSequence;for(b=0;b<this.extensionList.length;++b)c.addChild(this.extensionList[b].toDer());
+a.addChild(c)}return a};
+Certificate.prototype.decode=function(){var a=DerNode.parse(this.getContent().buf()).getChildren(),b=DerNode.getSequence(a,0).getChildren();this.notBefore=b[0].toVal();this.notAfter=b[1].toVal();for(var c=DerNode.getSequence(a,1).getChildren(),b=0;b<c.length;++b){var d=DerNode.getSequence(c,b).getChildren(),e=d[0].toVal(),d=d[1].toVal().buf().toString("binary");this.addSubjectDescription(new CertificateSubjectDescription(e,d))}b=a[2].encode();this.key=new PublicKey(b);if(3<a.length)for(a=DerNode.getSequence(a,
+3).getChildren(),b=0;b<a.length;++b)d=DerNode.getSequence(a,b).getChildren(),e=d[0].toVal(),c=d[1].toVal(),d=d[2].toVal(),this.addExtension(new CertificateExtension(e,c,d))};Certificate.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();Data.prototype.wireDecode.call(this,a,b);this.decode()};
+Certificate.prototype.toString=function(){var a;a="Certificate name:\n"+("  "+this.getName().toUri()+"\n");a+="Validity:\n";var b=Certificate.toIsoString(Math.round(this.notBefore)),c=Certificate.toIsoString(Math.round(this.notAfter));a=a+("  NotBefore: "+b+"\n")+("  NotAfter: "+c+"\n");for(b=0;b<this.subjectDescriptionList.length;++b)c=this.subjectDescriptionList[b],a+="Subject Description:\n",a+="  "+c.getOidString()+": "+c.getValue()+"\n";a+="Public key bits:\n";c=this.key.getKeyDer().buf().toString("base64");
+for(b=0;b<c.length;b+=64)a+=c.substring(b,Math.min(b+64,c.length))+"\n";if(0<this.extensionList.length)for(a+="Extensions:\n",b=0;b<this.extensionList.length;++b)c=this.extensionList[b],a+="  OID: "+c.getOid()+"\n",a+="  Is critical: "+(c.getIsCritical()?"Y":"N")+"\n",a+="  Value: "+c.getValue().toHex()+"\n";return a};
+Certificate.toIsoString=function(a){a=new Date(Math.round(a));return a.getUTCFullYear()+Certificate.to2DigitString(a.getUTCMonth()+1)+Certificate.to2DigitString(a.getUTCDate())+"T"+Certificate.to2DigitString(a.getUTCHours())+Certificate.to2DigitString(a.getUTCMinutes())+Certificate.to2DigitString(a.getUTCSeconds())};Certificate.to2DigitString=function(a){a=a.toString();return 1===a.length?"0"+a:a};
+var Data=require("../../data.js").Data,Name=require("../../name.js").Name,SecurityException=require("../../security//security-exception.js").SecurityException,Certificate=require("./certificate.js").Certificate,WireFormat=require("../../encoding/wire-format.js").WireFormat,IdentityCertificate=function IdentityCertificate(b){void 0!=b?Certificate.call(this,b):Certificate.call(this);this.publicKeyName=new Name;if(b instanceof IdentityCertificate)this.publicKeyName=new Name(b.publicKeyName);else if(b instanceof
+Data){if(!IdentityCertificate.isCorrectName(b.getName()))throw new SecurityException(Error("Wrong Identity Certificate Name!"));this.setPublicKeyName()}};IdentityCertificate.prototype=new Certificate;IdentityCertificate.prototype.name="IdentityCertificate";exports.IdentityCertificate=IdentityCertificate;
+IdentityCertificate.prototype.setName=function(a){if(!IdentityCertificate.isCorrectName(a))throw new SecurityException(Error("Wrong Identity Certificate Name!"));Certificate.prototype.setName.call(this,a);this.setPublicKeyName();return this};IdentityCertificate.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();Certificate.prototype.wireDecode.call(this,a,b);this.setPublicKeyName()};IdentityCertificate.prototype.getPublicKeyName=function(){return this.publicKeyName};
+IdentityCertificate.isIdentityCertificate=function(a){return IdentityCertificate.isCorrectName(a.getName())};
+IdentityCertificate.certificateNameToPublicKeyName=function(a){for(var b=!1,c=a.size()-1;0<c+1;--c)if("ID-CERT"==a.get(c).toEscapedString()){b=!0;break}if(!b)throw Error("Incorrect identity certificate name "+a.toUri());for(var b=a.getSubName(0,c),c=!1,d=0;d<b.size();d++)if("KEY"==b.get(d).toEscapedString()){c=!0;break}if(!c)throw Error("Incorrect identity certificate name "+a.toUri());return b.getSubName(0,d).append(b.getSubName(d+1,b.size()-d-1))};
+IdentityCertificate.isCorrectName=function(a){for(var b=a.size()-1;0<=b&&"ID-CERT"!=a.get(b).toEscapedString();b--);if(0>b)return!1;for(b=0;b<a.size()&&"KEY"!=a.get(b).toEscapedString();b++);return b>=a.size()?!1:!0};IdentityCertificate.prototype.setPublicKeyName=function(){this.publicKeyName=IdentityCertificate.certificateNameToPublicKeyName(this.getName())};
+var Name=require("../../name.js").Name,SecurityException=require("../security-exception.js").SecurityException,SyncPromise=require("../../util/sync-promise.js").SyncPromise,IdentityStorage=function(){};exports.IdentityStorage=IdentityStorage;IdentityStorage.prototype.doesIdentityExistPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.doesIdentityExistPromise is not implemented"))};
+IdentityStorage.prototype.doesIdentityExist=function(a){return SyncPromise.getValue(this.doesIdentityExistPromise(a,!0))};IdentityStorage.prototype.addIdentityPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.addIdentityPromise is not implemented"))};IdentityStorage.prototype.addIdentity=function(a){return SyncPromise.getValue(this.addIdentityPromise(a,!0))};IdentityStorage.prototype.revokeIdentity=function(){return SyncPromise.reject(Error("IdentityStorage.revokeIdentity is not implemented"))};
+IdentityStorage.prototype.getNewKeyNamePromise=function(a,b,c){for(var d=Math.floor((new Date).getTime()/1E3);d<=IdentityStorage.lastTimestamp;)d+=1;IdentityStorage.lastTimestamp=d;d=""+d;b=b?"ksk-"+d:"dsk-"+d;var e=(new Name(a)).append(b);return this.doesKeyExistPromise(e,c).then(function(a){if(a)throw new SecurityException(Error("Key name already exists"));return SyncPromise.resolve(e)})};
+IdentityStorage.prototype.getNewKeyName=function(a,b){return SyncPromise.getValue(this.getNewKeyNamePromise(a,b,!0))};IdentityStorage.prototype.doesKeyExistPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.doesKeyExistPromise is not implemented"))};IdentityStorage.prototype.doesKeyExist=function(a){return SyncPromise.getValue(this.doesKeyExistPromise(a,!0))};IdentityStorage.prototype.addKeyPromise=function(a,b,c,d){return SyncPromise.reject(Error("IdentityStorage.addKeyPromise is not implemented"))};
+IdentityStorage.prototype.addKey=function(a,b,c){return SyncPromise.getValue(this.addKeyPromise(a,b,c,!0))};IdentityStorage.prototype.getKeyPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.getKeyPromise is not implemented"))};IdentityStorage.prototype.getKey=function(a){return SyncPromise.getValue(this.getKeyPromise(a,!0))};IdentityStorage.prototype.activateKey=function(a){throw Error("IdentityStorage.activateKey is not implemented");};
+IdentityStorage.prototype.deactivateKey=function(a){throw Error("IdentityStorage.deactivateKey is not implemented");};IdentityStorage.prototype.doesCertificateExistPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.doesCertificateExistPromise is not implemented"))};IdentityStorage.prototype.doesCertificateExist=function(a){return SyncPromise.getValue(this.doesCertificateExistPromise(a,!0))};IdentityStorage.prototype.addCertificatePromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.addCertificatePromise is not implemented"))};
+IdentityStorage.prototype.addCertificate=function(a){return SyncPromise.getValue(this.addCertificatePromise(a,!0))};IdentityStorage.prototype.getCertificatePromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.getCertificatePromise is not implemented"))};IdentityStorage.prototype.getCertificate=function(a){return SyncPromise.getValue(this.getValuePromise(a,!0))};IdentityStorage.prototype.getTpmLocatorPromise=function(a){return SyncPromise.reject(Error("IdentityStorage.getTpmLocatorPromise is not implemented"))};
+IdentityStorage.prototype.getTpmLocator=function(){return SyncPromise.getValue(this.getTpmLocatorPromise(!0))};IdentityStorage.prototype.getDefaultIdentityPromise=function(a){return SyncPromise.reject(Error("IdentityStorage.getDefaultIdentityPromise is not implemented"))};IdentityStorage.prototype.getDefaultIdentity=function(){return SyncPromise.getValue(this.getDefaultIdentityPromise(!0))};IdentityStorage.prototype.getDefaultKeyNameForIdentityPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.getDefaultKeyNameForIdentityPromise is not implemented"))};
+IdentityStorage.prototype.getDefaultKeyNameForIdentity=function(a){return SyncPromise.getValue(this.getDefaultKeyNameForIdentityPromise(a,!0))};IdentityStorage.prototype.getDefaultCertificateNameForIdentityPromise=function(a,b){var c=this;return this.getDefaultKeyNameForIdentityPromise(a).then(function(a){return c.getDefaultCertificateNameForKeyPromise(a)})};
+IdentityStorage.prototype.getDefaultCertificateNameForIdentity=function(a){return SyncPromise.getValue(this.getDefaultCertificateNameForIdentityPromise(a,!0))};IdentityStorage.prototype.getDefaultCertificateNameForKeyPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.getDefaultCertificateNameForKeyPromise is not implemented"))};IdentityStorage.prototype.getDefaultCertificateNameForKey=function(a){return SyncPromise.getValue(this.getDefaultCertificateNameForKeyPromise(a,!0))};
+IdentityStorage.prototype.getAllIdentitiesPromise=function(a,b,c){return SyncPromise.reject(Error("IdentityStorage.getAllIdentitiesPromise is not implemented"))};IdentityStorage.prototype.getAllKeyNamesOfIdentityPromise=function(a,b,c,d){return SyncPromise.reject(Error("IdentityStorage.getAllKeyNamesOfIdentityPromise is not implemented"))};IdentityStorage.prototype.getAllCertificateNamesOfKeyPromise=function(a,b,c,d){return SyncPromise.reject(Error("IdentityStorage.getAllCertificateNamesOfKeyPromise is not implemented"))};
+IdentityStorage.prototype.getAllKeyNamesOfIdentity=function(a,b,c){return SyncPromise.getValue(this.getAllKeyNamesOfIdentityPromise(a,b,c,!0))};IdentityStorage.prototype.setDefaultIdentityPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.setDefaultIdentityPromise is not implemented"))};IdentityStorage.prototype.setDefaultIdentity=function(a){return SyncPromise.getValue(this.setDefaultIdentityPromise(a,!0))};
+IdentityStorage.prototype.setDefaultKeyNameForIdentityPromise=function(a,b,c){return SyncPromise.reject(Error("IdentityStorage.setDefaultKeyNameForIdentityPromise is not implemented"))};IdentityStorage.prototype.setDefaultKeyNameForIdentity=function(a,b){return SyncPromise.getValue(this.setDefaultKeyNameForIdentityPromise(a,b,!0))};IdentityStorage.prototype.setDefaultCertificateNameForKeyPromise=function(a,b,c){return SyncPromise.reject(Error("IdentityStorage.setDefaultCertificateNameForKeyPromise is not implemented"))};
+IdentityStorage.prototype.setDefaultCertificateNameForKey=function(a,b){return SyncPromise.getValue(this.setDefaultCertificateNameForKeyPromise(a,b,!0))};IdentityStorage.prototype.getDefaultCertificatePromise=function(a){var b=this;return this.getDefaultIdentityPromise(a).then(function(c){return b.getDefaultCertificateNameForIdentityPromise(c,a)},function(a){return SyncPromise.resolve(null)}).then(function(c){return null==c?SyncPromise.resolve(null):b.getCertificatePromise(c,a)})};
+IdentityStorage.prototype.getDefaultCertificate=function(){return SyncPromise.getValue(this.getDefaultCertificatePromise(!0))};IdentityStorage.prototype.deleteCertificateInfoPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.deleteCertificateInfoPromise is not implemented"))};IdentityStorage.prototype.deleteCertificateInfo=function(a){return SyncPromise.getValue(this.deleteCertificateInfoPromise(a,!0))};IdentityStorage.prototype.deletePublicKeyInfoPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.deletePublicKeyInfoPromise is not implemented"))};
+IdentityStorage.prototype.deletePublicKeyInfo=function(a){return SyncPromise.getValue(this.deletePublicKeyInfoPromise(a,!0))};IdentityStorage.prototype.deleteIdentityInfoPromise=function(a,b){return SyncPromise.reject(Error("IdentityStorage.deleteIdentityInfoPromise is not implemented"))};IdentityStorage.prototype.deleteIdentityInfo=function(a){return SyncPromise.getValue(this.deleteIdentityInfoPromise(a,!0))};IdentityStorage.lastTimestamp=Math.floor((new Date).getTime()/1E3);
+var IndexedDbIdentityStorage=function(){IdentityStorage.call(this);this.database=new Dexie("ndnsec-public-info");this.database.version(1).stores({globals:"key",identity:"identityNameUri",publicKey:"keyNameUri",certificate:"certificateNameUri"});this.database.open()};IndexedDbIdentityStorage.prototype=new IdentityStorage;IndexedDbIdentityStorage.prototype.name="IndexedDbIdentityStorage";
+IndexedDbIdentityStorage.prototype.doesIdentityExistPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.doesIdentityExistPromise is only supported for async"))):this.database.identity.where("identityNameUri").equals(a.toUri()).count().then(function(a){return Promise.resolve(0<a)})};
+IndexedDbIdentityStorage.prototype.addIdentityPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.addIdentityPromise is only supported for async")));var c=this;return this.doesIdentityExistPromise(a).then(function(b){return b?Promise.resolve():c.database.identity.put({identityNameUri:a.toUri(),defaultKeyUri:null})})};
+IndexedDbIdentityStorage.prototype.doesKeyExistPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.doesKeyExistPromise is only supported for async"))):this.database.publicKey.where("keyNameUri").equals(a.toUri()).count().then(function(a){return Promise.resolve(0<a)})};
+IndexedDbIdentityStorage.prototype.addKeyPromise=function(a,b,c,d){if(d)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.addKeyPromise is only supported for async")));if(0===a.size())return Promise.resolve();var e=this;return this.doesKeyExistPromise(a).then(function(d){if(d)return Promise.resolve();d=a.getPrefix(-1);return e.addIdentityPromise(d).then(function(){return e.database.publicKey.put({keyNameUri:a.toUri(),keyType:b,keyDer:(new Blob(c,!0)).buf(),defaultCertificate:null})})})};
+IndexedDbIdentityStorage.prototype.getKeyPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getKeyPromise is only supported for async"))):0===a.size()?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage::getKeyPromise: Empty keyName"))):this.database.publicKey.get(a.toUri()).then(function(a){return a?Promise.resolve(new Blob(a.keyDer)):Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage::getKeyPromise: The key does not exist")))})};
+IndexedDbIdentityStorage.prototype.doesCertificateExistPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.doesCertificateExistPromise is only supported for async"))):this.database.certificate.where("certificateNameUri").equals(a.toUri()).count().then(function(a){return Promise.resolve(0<a)})};
+IndexedDbIdentityStorage.prototype.addCertificatePromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.addCertificatePromise is only supported for async")));var c=a.getName(),d=a.getPublicKeyName(),e=this;return this.addKeyPromise(d,a.getPublicKeyInfo().getKeyType(),a.getPublicKeyInfo().getKeyDer(),b).then(function(){return e.doesCertificateExistPromise(c)}).then(function(b){return b?Promise.resolve():e.database.certificate.put({certificateNameUri:c.toUri(),
+encoding:a.wireEncode().buf()})})};IndexedDbIdentityStorage.prototype.getCertificatePromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getCertificatePromise is only supported for async"))):this.database.certificate.get(a.toUri()).then(function(a){if(a){var b=new IdentityCertificate;try{b.wireDecode(a.encoding)}catch(e){return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage::getCertificatePromise: The certificate cannot be decoded")))}return Promise.resolve(b)}return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage::getCertificatePromise: The certificate does not exist")))})};
+IndexedDbIdentityStorage.prototype.getDefaultIdentityPromise=function(a){return this.database.globals.get("defaultIdentityUri").then(function(a){if(a)return Promise.resolve(new Name(a.value));throw new SecurityException(Error("IndexedDbIdentityStorage.getDefaultIdentity: The default identity is not defined"));})};
+IndexedDbIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getDefaultKeyNameForIdentityPromise is only supported for async"))):this.database.identity.get(a.toUri()).then(function(a){if(a){if(null!=a.defaultKeyUri)return Promise.resolve(new Name(a.defaultKeyUri));throw new SecurityException(Error("No default key set."));}throw new SecurityException(Error("Identity not found."));})};
+IndexedDbIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getDefaultCertificateNameForKeyPromise is only supported for async"))):this.database.publicKey.get(a.toUri()).then(function(a){if(a){if(null!=a.defaultCertificateUri)return Promise.resolve(new Name(a.defaultCertificateUri));throw new SecurityException(Error("No default certificate set."));}throw new SecurityException(Error("Key not found."));
+})};
+IndexedDbIdentityStorage.prototype.getAllIdentitiesPromise=function(a,b,c){if(c)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getAllIdentitiesPromise is only supported for async")));var d=null,e=this;return this.getDefaultIdentityPromise().then(function(a){d=a;return SyncPromise.resolve()},function(a){return SyncPromise.resolve()}).then(function(){return e.database.identity.each(function(c){c=new Name(c.identityNameUri);var e=null!==d&&c.equals(d);b&&e?a.push(c):b||e||
+a.push(c)})})};
+IndexedDbIdentityStorage.prototype.getAllKeyNamesOfIdentityPromise=function(a,b,c,d){if(d)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getAllKeyNamesOfIdentityPromise is only supported for async")));var e=null,f=this;return this.getDefaultKeyNameForIdentityPromise(a).then(function(a){e=a;return SyncPromise.resolve()},function(a){return SyncPromise.resolve()}).then(function(){return f.database.publicKey.each(function(d){d=new Name(d.keyNameUri);if(d.getPrefix(-1).equals(a)){var f=null!==
+e&&d.equals(e);c&&f?b.push(d):c||f||b.push(d)}})})};
+IndexedDbIdentityStorage.prototype.getAllCertificateNamesOfKeyPromise=function(a,b,c,d){if(d)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.getAllCertificateNamesOfKeyPromise is only supported for async")));var e=null,f=this;return this.getDefaultCertificateNameForKeyPromise(a).then(function(a){e=a;return SyncPromise.resolve()},function(a){return SyncPromise.resolve()}).then(function(){return f.database.certificate.each(function(d){d=new Name(d.certificateNameUri);if(IdentityCertificate.certificateNameToPublicKeyName(d).equals(a)){var f=
+null!==e&&d.equals(e);c&&f?b.push(d):c||f||b.push(d)}})})};IndexedDbIdentityStorage.prototype.setDefaultIdentityPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.setDefaultIdentityPromise is only supported for async")));var c=this;return this.doesIdentityExistPromise(a).then(function(b){return b?c.database.globals.put({key:"defaultIdentityUri",value:a.toUri()}):c.database.globals["delete"]("defaultIdentityUri")})};
+IndexedDbIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise=function(a,b,c){c="boolean"===typeof b?b:c;b=b instanceof Name?b:null;if(c)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.setDefaultKeyNameForIdentityPromise is only supported for async")));c=a.getPrefix(-1);return null!=b&&0<b.size()&&!b.equals(c)?Promise.reject(new SecurityException(Error("The specified identity name does not match the key name"))):this.database.identity.update(c.toUri(),{defaultKeyUri:a.toUri()})};
+IndexedDbIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise=function(a,b,c){return c?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.setDefaultCertificateNameForKeyPromise is only supported for async"))):this.database.publicKey.update(a.toUri(),{defaultCertificateUri:b.toUri()})};
+IndexedDbIdentityStorage.prototype.deleteCertificateInfoPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.deleteCertificateInfoPromise is only supported for async"))):0===a.size()?Promise.resolve():this.database.certificate["delete"](a.toUri())};
+IndexedDbIdentityStorage.prototype.deletePublicKeyInfoPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.deletePublicKeyInfoPromise is only supported for async")));if(0===a.size())return Promise.resolve();var c=this;return this.database.publicKey["delete"](a.toUri()).then(function(){return c.database.certificate.each(function(b){IdentityCertificate.certificateNameToPublicKeyName(new Name(b.certificateNameUri)).equals(a)&&c.database.certificate["delete"](b.certificateNameUri)})})};
+IndexedDbIdentityStorage.prototype.deleteIdentityInfoPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbIdentityStorage.deleteIdentityInfoPromise is only supported for async")));var c=this;return this.database.identity["delete"](a.toUri()).then(function(){return c.database.publicKey.each(function(b){(new Name(b.keyNameUri)).getPrefix(-1).equals(a)&&c.database.publicKey["delete"](b.keyNameUri)})}).then(function(){return c.database.certificate.each(function(b){IdentityCertificate.certificateNameToPublicKeyName(new Name(b.certificateNameUri)).getPrefix(-1).equals(a)&&
+c.database.certificate["delete"](b.certificateNameUri)})})};
+var Name=require("../../name.js").Name,Blob=require("../../util/blob.js").Blob,SecurityException=require("../security-exception.js").SecurityException,IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,SyncPromise=require("../../util/sync-promise.js").SyncPromise,IdentityStorage=require("./identity-storage.js").IdentityStorage,MemoryIdentityStorage=function(){IdentityStorage.call(this);this.identityStore={};this.defaultIdentity="";this.keyStore={};this.certificateStore=
+{}};MemoryIdentityStorage.prototype=new IdentityStorage;MemoryIdentityStorage.prototype.name="MemoryIdentityStorage";exports.MemoryIdentityStorage=MemoryIdentityStorage;MemoryIdentityStorage.prototype.doesIdentityExistPromise=function(a){return SyncPromise.resolve(void 0!==this.identityStore[a.toUri()])};MemoryIdentityStorage.prototype.addIdentityPromise=function(a){a=a.toUri();void 0===this.identityStore[a]&&(this.identityStore[a]={defaultKey:null});return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.doesKeyExistPromise=function(a){return SyncPromise.resolve(void 0!==this.keyStore[a.toUri()])};MemoryIdentityStorage.prototype.addKeyPromise=function(a,b,c){if(0===a.size()||this.doesKeyExist(a))return SyncPromise.resolve();var d=a.getSubName(0,a.size()-1);this.addIdentity(d);this.keyStore[a.toUri()]={keyType:b,keyDer:new Blob(c),defaultCertificate:null};return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.getKeyPromise=function(a){if(0===a.size())return SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage::getKeyPromise: Empty keyName")));a=a.toUri();a=this.keyStore[a];return void 0===a?SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage::getKeyPromise: The key does not exist"))):SyncPromise.resolve(a.keyDer)};MemoryIdentityStorage.prototype.doesCertificateExistPromise=function(a){return SyncPromise.resolve(void 0!==this.certificateStore[a.toUri()])};
+MemoryIdentityStorage.prototype.addCertificatePromise=function(a){var b=a.getName(),c=a.getPublicKeyName();this.addKey(c,a.getPublicKeyInfo().getKeyType(),a.getPublicKeyInfo().getKeyDer());if(this.doesCertificateExist(b))return SyncPromise.resolve();this.certificateStore[b.toUri()]=a.wireEncode();return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.getCertificatePromise=function(a){a=a.toUri();if(void 0===this.certificateStore[a])return SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage::getCertificatePromise: The certificate does not exist")));var b=new IdentityCertificate;try{b.wireDecode(this.certificateStore[a])}catch(c){return SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage::getCertificatePromise: The certificate cannot be decoded")))}return SyncPromise.resolve(b)};
+IdentityStorage.prototype.getTpmLocatorPromise=function(a){return SyncPromise.resolve("tpm-memory:")};MemoryIdentityStorage.prototype.getDefaultIdentityPromise=function(){return 0===this.defaultIdentity.length?SyncPromise.reject(new SecurityException(Error("MemoryIdentityStorage.getDefaultIdentity: The default identity is not defined"))):SyncPromise.resolve(new Name(this.defaultIdentity))};
+MemoryIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise=function(a){a=a.toUri();return void 0!==this.identityStore[a]?null!=this.identityStore[a].defaultKey?SyncPromise.resolve(this.identityStore[a].defaultKey):SyncPromise.reject(new SecurityException(Error("No default key set."))):SyncPromise.reject(new SecurityException(Error("Identity not found.")))};
+MemoryIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise=function(a){a=a.toUri();return void 0!==this.keyStore[a]?null!=this.keyStore[a].defaultCertificate?SyncPromise.resolve(this.keyStore[a].defaultCertificate):SyncPromise.reject(new SecurityException(Error("No default certificate set."))):SyncPromise.reject(new SecurityException(Error("Key not found.")))};
+MemoryIdentityStorage.prototype.setDefaultIdentityPromise=function(a){a=a.toUri();this.defaultIdentity=void 0!==this.identityStore[a]?a:"";return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise=function(a,b){b=b instanceof Name?b:null;var c=a.getPrefix(-1);if(null!=b&&0<b.size()&&!b.equals(c))return SyncPromise.reject(new SecurityException(Error("The specified identity name does not match the key name")));c=c.toUri();void 0!==this.identityStore[c]&&(this.identityStore[c].defaultKey=new Name(a));return SyncPromise.resolve()};
+MemoryIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise=function(a,b){var c=a.toUri();void 0!==this.keyStore[c]&&(this.keyStore[c].defaultCertificate=new Name(b));return SyncPromise.resolve()};MemoryIdentityStorage.prototype.deleteCertificateInfoPromise=function(a){return SyncPromise.reject(Error("MemoryIdentityStorage.deleteCertificateInfoPromise is not implemented"))};MemoryIdentityStorage.prototype.deletePublicKeyInfoPromise=function(a){return SyncPromise.reject(Error("MemoryIdentityStorage.deletePublicKeyInfoPromise is not implemented"))};
+MemoryIdentityStorage.prototype.deleteIdentityInfoPromise=function(a){return SyncPromise.reject(Error("MemoryIdentityStorage.deleteIdentityInfoPromise is not implemented"))};var SyncPromise=require("../../util/sync-promise.js").SyncPromise,DerNode=require("../../encoding/der/der-node.js").DerNode,PrivateKeyStorage=function(){};exports.PrivateKeyStorage=PrivateKeyStorage;PrivateKeyStorage.prototype.generateKeyPairPromise=function(a,b,c){return SyncPromise.reject(Error("PrivateKeyStorage.generateKeyPairPromise is not implemented"))};
+PrivateKeyStorage.prototype.generateKeyPair=function(a,b){SyncPromise.getValue(this.generateKeyPairPromise(a,b,!0))};PrivateKeyStorage.prototype.deleteKeyPairPromise=function(a,b){return SyncPromise.reject(Error("PrivateKeyStorage.deleteKeyPairPromise is not implemented"))};PrivateKeyStorage.prototype.deleteKeyPair=function(a){SyncPromise.getValue(this.deleteKeyPairPromise(a,!0))};PrivateKeyStorage.prototype.getPublicKeyPromise=function(a,b){return SyncPromise.reject(Error("PrivateKeyStorage.getPublicKeyPromise is not implemented"))};
+PrivateKeyStorage.prototype.getPublicKey=function(a){return SyncPromise.getValue(this.getPublicKeyPromise(a,!0))};PrivateKeyStorage.prototype.signPromise=function(a,b,c,d){return SyncPromise.reject(Error("PrivateKeyStorage.sign is not implemented"))};PrivateKeyStorage.prototype.sign=function(a,b,c){return SyncPromise.getValue(this.signPromise(a,b,c,!0))};PrivateKeyStorage.prototype.decrypt=function(a,b,c){throw Error("PrivateKeyStorage.decrypt is not implemented");};
+PrivateKeyStorage.prototype.encrypt=function(a,b,c){throw Error("PrivateKeyStorage.encrypt is not implemented");};PrivateKeyStorage.prototype.generateKey=function(a,b){throw Error("PrivateKeyStorage.generateKey is not implemented");};PrivateKeyStorage.prototype.doesKeyExistPromise=function(a,b,c){return SyncPromise.reject(Error("PrivateKeyStorage.doesKeyExist is not implemented"))};PrivateKeyStorage.prototype.doesKeyExist=function(a,b){return SyncPromise.getValue(this.doesKeyExistPromise(a,b,!0))};
+PrivateKeyStorage.encodePkcs8PrivateKey=function(a,b,c){var d=new DerNode.DerSequence;d.addChild(new DerNode.DerOid(b));d.addChild(c);b=new DerNode.DerSequence;b.addChild(new DerNode.DerInteger(0));b.addChild(d);b.addChild(new DerNode.DerOctetString(a));return b.encode()};
+PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey=function(a){var b=new DerNode.DerSequence;b.addChild(new DerNode.DerInteger(0));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.n)));b.addChild(new DerNode.DerInteger(a.e));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.d)));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.p)));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.q)));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.dmp1)));
+b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.dmq1)));b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.coeff)));return b.encode()};
+PrivateKeyStorage.encodePublicKeyFromRSAKey=function(a){var b=new DerNode.DerSequence;b.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(a.n)));b.addChild(new DerNode.DerInteger(a.e));a=new DerNode.DerSequence;a.addChild(new DerNode.DerOid(new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID)));a.addChild(new DerNode.DerNull);var c=new DerNode.DerSequence;c.addChild(a);c.addChild(new DerNode.DerBitString(b.encode().buf(),0));return c.encode()};
+PrivateKeyStorage.bigIntegerToBuffer=function(a){a=a.toString(16);if("-"==a.substr(0,1))throw Error("PrivateKeyStorage.bigIntegerToBuffer: Negative integers are not currently supported");1==a.length%2?a="0"+a:a.match(/^[0-7]/)||(a="00"+a);return new Buffer(a,"hex")};PrivateKeyStorage.RSA_ENCRYPTION_OID="1.2.840.113549.1.1.1";PrivateKeyStorage.EC_ENCRYPTION_OID="1.2.840.10045.2.1";
+var Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,SecurityException=require("../security-exception.js").SecurityException,PublicKey=require("../certificate/public-key.js").PublicKey,KeyClass=require("../security-types.js").KeyClass,KeyType=require("../security-types").KeyType,DigestAlgorithm=require("../security-types.js").DigestAlgorithm,DataUtils=require("../../encoding/data-utils.js").DataUtils,PrivateKeyStorage=require("./private-key-storage.js").PrivateKeyStorage,
+DerNode=require("../../encoding/der/der-node.js").DerNode,OID=require("../../encoding/oid.js").OID,SyncPromise=require("../../util/sync-promise.js").SyncPromise,UseSubtleCrypto=require("../../use-subtle-crypto-node.js").UseSubtleCrypto,rsaKeygen=null;try{rsaKeygen=require("rsa-keygen")}catch(e$$44){}var MemoryPrivateKeyStorage=function(){PrivateKeyStorage.call(this);this.publicKeyStore={};this.privateKeyStore={}};MemoryPrivateKeyStorage.prototype=new PrivateKeyStorage;
+MemoryPrivateKeyStorage.prototype.name="MemoryPrivateKeyStorage";exports.MemoryPrivateKeyStorage=MemoryPrivateKeyStorage;MemoryPrivateKeyStorage.prototype.setPublicKeyForKeyName=function(a,b,c){this.publicKeyStore[a.toUri()]=new PublicKey(new Blob(c,!0))};
+MemoryPrivateKeyStorage.prototype.setPrivateKeyForKeyName=function(a,b,c){c=c.toString("base64");var d;if(b===KeyType.RSA){d="-----BEGIN RSA PRIVATE KEY-----\n";for(var e=0;e<c.length;e+=64)d+=c.substr(e,64)+"\n";d+="-----END RSA PRIVATE KEY-----"}else if(b===KeyType.ECDSA){d="-----BEGIN EC PRIVATE KEY-----\n";for(e=0;e<c.length;e+=64)d+=c.substr(e,64)+"\n";d+="-----END EC PRIVATE KEY-----"}else throw new SecurityException(Error("MemoryPrivateKeyStorage: KeyType is not supported"));this.privateKeyStore[a.toUri()]=
+{keyType:b,privateKey:d}};MemoryPrivateKeyStorage.prototype.setKeyPairForKeyName=function(a,b,c,d){this.setPublicKeyForKeyName(a,b,c);this.setPrivateKeyForKeyName(a,b,d)};
+MemoryPrivateKeyStorage.prototype.generateKeyPairPromise=function(a,b,c){if(this.doesKeyExist(a,KeyClass.PUBLIC))return SyncPromise.reject(new SecurityException(Error("Public key already exists")));if(this.doesKeyExist(a,KeyClass.PRIVATE))return SyncPromise.reject(new SecurityException(Error("Private key already exists")));var d=this;if(UseSubtleCrypto()&&!c){if(b.getKeyType()===KeyType.RSA){var e=null,f=null;return crypto.subtle.generateKey({name:"RSASSA-PKCS1-v1_5",modulusLength:b.getKeySize(),
+publicExponent:new Uint8Array([1,0,1]),hash:{name:"SHA-256"}},!0,["sign","verify"]).then(function(a){e=a.privateKey;return crypto.subtle.exportKey("spki",a.publicKey)}).then(function(a){f=(new Blob(new Uint8Array(a),!1)).buf();return crypto.subtle.exportKey("pkcs8",e)}).then(function(c){c=DerNode.parse((new Blob(new Uint8Array(c),!1)).buf()).getChildren()[2].toVal();d.setKeyPairForKeyName(a,b.getKeyType(),f,c.buf());d.privateKeyStore[a.toUri()].subtleKey=e;return Promise.resolve()})}return SyncPromise.reject(new SecurityException(Error("Only RSA key generation currently supported")))}return SyncPromise.resolve().then(function(){if("undefined"!==
+typeof RSAKey)if(b.getKeyType()===KeyType.RSA){var c=new RSAKey;c.generate(b.getKeySize(),"010001");d.setKeyPairForKeyName(a,b.getKeyType(),PrivateKeyStorage.encodePublicKeyFromRSAKey(c).buf(),PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey(c).buf())}else return SyncPromise.reject(new SecurityException(Error("Only RSA key generation currently supported")));else{var e;if(b.getKeyType()===KeyType.RSA){if(!rsaKeygen)return SyncPromise.reject(new SecurityException(Error("Need to install rsa-keygen: sudo npm install rsa-keygen")));
+e=rsaKeygen.generate(b.getKeySize());c=e.public_key.toString().replace("-----BEGIN PUBLIC KEY-----","").replace("-----END PUBLIC KEY-----","");c=new Buffer(c,"base64");e=e.private_key.toString()}else return SyncPromise.reject(new SecurityException(Error("Only RSA key generation currently supported")));d.setPublicKeyForKeyName(a,b.getKeyType(),c);d.privateKeyStore[a.toUri()]={keyType:b.getKeyType(),privateKey:e}}return SyncPromise.resolve()})};
+MemoryPrivateKeyStorage.prototype.deleteKeyPairPromise=function(a){a=a.toUri();delete this.publicKeyStore[a];delete this.privateKeyStore[a];return SyncPromise.resolve()};MemoryPrivateKeyStorage.prototype.getPublicKeyPromise=function(a){var b=a.toUri(),b=this.publicKeyStore[b];return void 0===b?SyncPromise.reject(new SecurityException(Error("MemoryPrivateKeyStorage: Cannot find public key "+a.toUri()))):SyncPromise.resolve(b)};
+MemoryPrivateKeyStorage.prototype.signPromise=function(a,b,c,d){d="boolean"===typeof c?c:d;c="boolean"!==typeof c&&c?c:DigestAlgorithm.SHA256;if(c!=DigestAlgorithm.SHA256)return SyncPromise.reject(new SecurityException(Error("MemoryPrivateKeyStorage.sign: Unsupported digest algorithm")));b=b.toUri();var e=this.privateKeyStore[b];if(void 0===e)return SyncPromise.reject(new SecurityException(Error("MemoryPrivateKeyStorage: Cannot find private key "+b)));if(UseSubtleCrypto()&&!d){var f={name:"RSASSA-PKCS1-v1_5",
+hash:{name:"SHA-256"}};e.subtleKey?d=crypto.subtle.sign(f,e.subtleKey,a):(d=DataUtils.privateKeyPemToDer(e.privateKey),d=PrivateKeyStorage.encodePkcs8PrivateKey(d,new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),new DerNode.DerNull).buf(),d=crypto.subtle.importKey("pkcs8",d.buffer,f,!0,["sign"]).then(function(b){e.subtleKey=b;return crypto.subtle.sign(f,b,a)}));return d.then(function(a){a=new Blob(new Uint8Array(a),!0);return Promise.resolve(a)})}if(e.keyType===KeyType.RSA)d=Crypto.createSign("RSA-SHA256");
+else if(e.keyType===KeyType.ECDSA)d=Crypto.createSign("sha256");else return SyncPromise.reject(new SecurityException(Error("MemoryPrivateKeyStorage.sign: Unrecognized private key type")));d.update(a);d=new Buffer(DataUtils.toNumbersIfString(d.sign(e.privateKey)));d=new Blob(d,!1);return SyncPromise.resolve(d)};
+MemoryPrivateKeyStorage.prototype.doesKeyExistPromise=function(a,b){var c=a.toUri(),d=!1;b==KeyClass.PUBLIC?d=void 0!==this.publicKeyStore[c]:b==KeyClass.PRIVATE&&(d=void 0!==this.privateKeyStore[c]);return SyncPromise.resolve(d)};var Crypto=require("../../crypto.js"),IndexedDbPrivateKeyStorage=function(){PrivateKeyStorage.call(this);this.database=new Dexie("ndnsec-tpm");this.database.version(1).stores({publicKey:"nameHash",privateKey:"nameHash"});this.database.open()};
+IndexedDbPrivateKeyStorage.prototype=new PrivateKeyStorage;IndexedDbPrivateKeyStorage.prototype.name="IndexedDbPrivateKeyStorage";
+IndexedDbPrivateKeyStorage.prototype.generateKeyPairPromise=function(a,b,c){if(c)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.generateKeyPairPromise is only supported for async")));var d=this;return d.doesKeyExistPromise(a,KeyClass.PUBLIC).then(function(b){if(b)throw Error("Public key already exists");return d.doesKeyExistPromise(a,KeyClass.PRIVATE)}).then(function(c){if(c)throw Error("Private key already exists");if(b.getKeyType()===KeyType.RSA){var f=null,g=null;
+return crypto.subtle.generateKey({name:"RSASSA-PKCS1-v1_5",modulusLength:b.getKeySize(),publicExponent:new Uint8Array([1,0,1]),hash:{name:"SHA-256"}},!0,["sign","verify"]).then(function(a){f=a.privateKey;return crypto.subtle.exportKey("spki",a.publicKey)}).then(function(a){g=new Uint8Array(a);return crypto.subtle.exportKey("pkcs8",f)}).then(function(b){return d.database.transaction("rw",d.database.privateKey,d.database.publicKey,function(){d.database.publicKey.put({nameHash:IndexedDbPrivateKeyStorage.transformName(a),
+encoding:g});d.database.privateKey.put({nameHash:IndexedDbPrivateKeyStorage.transformName(a),encoding:new Uint8Array(b)})})})}throw Error("Only RSA key generation currently supported");})};IndexedDbPrivateKeyStorage.prototype.deleteKeyPairPromise=function(a,b){if(b)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.deleteKeyPairPromise is only supported for async")));var c=this;return this.database.publicKey["delete"](IndexedDbPrivateKeyStorage.transformName(a)).then(function(){return c.database.privateKey["delete"](IndexedDbPrivateKeyStorage.transformName(a))})};
+IndexedDbPrivateKeyStorage.prototype.getPublicKeyPromise=function(a,b){return b?Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.getPublicKeyPromise is only supported for async"))):this.database.publicKey.get(IndexedDbPrivateKeyStorage.transformName(a)).then(function(a){return Promise.resolve(new PublicKey(new Blob(a.encoding)))})};
+IndexedDbPrivateKeyStorage.prototype.signPromise=function(a,b,c,d){d="boolean"===typeof c?c:d;c="boolean"!==typeof c&&c?c:DigestAlgorithm.SHA256;if(d)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.signPromise is only supported for async")));if(c!=DigestAlgorithm.SHA256)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.sign: Unsupported digest algorithm")));var e={name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};return this.database.privateKey.get(IndexedDbPrivateKeyStorage.transformName(b)).then(function(a){return crypto.subtle.importKey("pkcs8",
+(new Blob(a.encoding)).buf(),e,!0,["sign"])}).then(function(b){return crypto.subtle.sign(e,b,a)}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!0))})};
+IndexedDbPrivateKeyStorage.prototype.doesKeyExistPromise=function(a,b,c){if(c)return Promise.reject(new SecurityException(Error("IndexedDbPrivateKeyStorage.doesKeyExistPromise is only supported for async")));c=null;if(b==KeyClass.PUBLIC)c=this.database.publicKey;else if(b==KeyClass.PRIVATE)c=this.database.privateKey;else return Promise.resolve(!1);return c.where("nameHash").equals(IndexedDbPrivateKeyStorage.transformName(a)).count().then(function(a){return Promise.resolve(0<a)})};
+IndexedDbPrivateKeyStorage.transformName=function(a){var b=Crypto.createHash("sha256");b.update(new Buffer(a.toUri()));return b.digest("base64").replace(/\//g,"%")};
+var Crypto=require("../../crypto.js"),Name=require("../../name.js").Name,Data=require("../../data.js").Data,Blob=require("../../util/blob.js").Blob,ConfigFile=require("../../util/config-file.js").ConfigFile,DigestSha256Signature=require("../../digest-sha256-signature.js").DigestSha256Signature,Sha256WithRsaSignature=require("../../sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("../../sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,KeyLocatorType=require("../../key-locator.js").KeyLocatorType,
+WireFormat=require("../../encoding/wire-format.js").WireFormat,SecurityException=require("../security-exception.js").SecurityException,DigestAlgorithm=require("../security-types.js").DigestAlgorithm,KeyType=require("../security-types.js").KeyType,RsaKeyParams=require("../key-params.js").RsaKeyParams,IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,PublicKey=require("../certificate/public-key.js").PublicKey,CertificateSubjectDescription=require("../certificate/certificate-subject-description.js").CertificateSubjectDescription,
+SyncPromise=require("../../util/sync-promise.js").SyncPromise,BasicIdentityStorage=require("./basic-identity-storage.js").BasicIdentityStorage,FilePrivateKeyStorage=require("./file-private-key-storage.js").FilePrivateKeyStorage,IdentityManager=function IdentityManager(b,c){if(c){if(!b)throw Error("IdentityManager: A custom privateKeyStorage is supplied with a null identityStorage");this.identityStorage=b;this.privateKeyStorage=c}else{if(!ConfigFile)throw new SecurityException(Error("IdentityManager: If not in Node.js then you must supply identityStorage and privateKeyStorage."));
+var d=new ConfigFile,e=[null],f=this;this.identityStorage=b?b:IdentityManager.getDefaultIdentityStorage_(d,function(){return f.checkTpmPromise_(e[0])});this.privateKeyStorage=IdentityManager.getDefaultPrivateKeyStorage_(d,e)}};exports.IdentityManager=IdentityManager;
+IdentityManager.prototype.createIdentityAndCertificatePromise=function(a,b,c){var d=this,e=!0,f=null;return this.identityStorage.addIdentityPromise(a,c).then(function(){return d.identityStorage.getDefaultKeyNameForIdentityPromise(a,c).then(function(a){f=a;return d.identityStorage.getKeyPromise(f,c).then(function(a){(new PublicKey(a)).getKeyType()==b.getKeyType()&&(e=!1);return SyncPromise.resolve()})},function(a){if(!(a instanceof SecurityException))throw a;return SyncPromise.resolve()})}).then(function(){return e?
+d.generateKeyPairPromise(a,!0,b,c).then(function(a){f=a;return d.identityStorage.setDefaultKeyNameForIdentityPromise(f,c)}):SyncPromise.resolve()}).then(function(){return d.identityStorage.getDefaultCertificateNameForKeyPromise(f,c).then(function(a){return SyncPromise.resolve(a)},function(a){if(!(a instanceof SecurityException))throw a;var b;return d.selfSignPromise(f,c).then(function(a){b=a.getName();return d.addCertificateAsIdentityDefaultPromise(a,c)}).then(function(){return SyncPromise.resolve(b)})})})};
+IdentityManager.prototype.createIdentityAndCertificate=function(a,b,c,d){return SyncPromise.complete(c,d,this.createIdentityAndCertificatePromise(a,b,!c))};IdentityManager.prototype.createIdentity=function(a,b){return IdentityCertificate.certificateNameToPublicKeyName(this.createIdentityAndCertificate(a,b))};
+IdentityManager.prototype.deleteIdentity=function(a,b,c){var d=this,e=!0,f=this.identityStorage.getDefaultIdentityPromise(!b).then(function(b){b.equals(a)&&(e=!1);return SyncPromise.resolve()},function(a){return SyncPromise.resolve()}).then(function(){if(!e)return SyncPromise.resolve();var b=[];return d.identityStorage.getAllKeyNamesOfIdentityPromise(a,b,!0).then(function(){return d.identityStorage.getAllKeyNamesOfIdentityPromise(a,b,!1)}).then(function(){return d.identityStorage.deleteIdentityInfoPromise(a)}).then(function(){function a(c){return c>=
+b.length?SyncPromise.resolve():d.privateKeyStorage.deleteKeyPairPromise(b[c]).then(function(){return a(c+1)})}return a(0)})});return SyncPromise.complete(b,c,f)};IdentityManager.prototype.setDefaultIdentityPromise=function(a,b){return this.identityStorage.setDefaultIdentityPromise(a,b)};IdentityManager.prototype.setDefaultIdentity=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.setDefaultIdentityPromise(a,!b))};IdentityManager.prototype.getDefaultIdentityPromise=function(a){return this.identityStorage.getDefaultIdentityPromise(a)};
+IdentityManager.prototype.getDefaultIdentity=function(a,b){return SyncPromise.complete(a,b,this.identityStorage.getDefaultIdentityPromise(!a))};IdentityManager.prototype.getDefaultCertificatePromise=function(a){return this.identityStorage.getDefaultCertificatePromise(a)};IdentityManager.prototype.generateRSAKeyPair=function(a,b,c){return SyncPromise.getValue(this.generateKeyPairPromise(a,b,new RsaKeyParams(c),!0))};
+IdentityManager.prototype.setDefaultKeyForIdentity=function(a,b,c,d){d="function"===typeof b?c:d;c="function"===typeof b?b:c;b="function"!==typeof b&&b?b:new Name;return SyncPromise.complete(c,d,this.identityStorage.setDefaultKeyNameForIdentityPromise(a,b,!c))};IdentityManager.prototype.getDefaultKeyNameForIdentity=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.getDefaultKeyNameForIdentityPromise(a,!b))};
+IdentityManager.prototype.generateRSAKeyPairAsDefaultPromise=function(a,b,c,d){var e,f=this;return this.generateKeyPairPromise(a,b,new RsaKeyParams(c)).then(function(a){e=a;return f.identityStorage.setDefaultKeyNameForIdentityPromise(e)}).then(function(){return SyncPromise.resolve(e)})};IdentityManager.prototype.generateRSAKeyPairAsDefault=function(a,b,c){return SyncPromise.getValue(this.generateRSAKeyPairAsDefaultPromise(a,b,c,!0))};
+IdentityManager.prototype.getPublicKey=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.getKeyPromise(a,!b).then(function(a){return SyncPromise.resolve(new PublicKey(a))}))};
+IdentityManager.prototype.prepareUnsignedIdentityCertificate=function(a,b,c,d,e,f,g,h,k){b instanceof PublicKey||(k=h,h=g,g=f,f=e,e=d,d=c,c=b,b=null);var l=g,m=h;g=l instanceof Name?l:null;"function"===typeof l?(h=l,k=m):"function"===typeof m?h=m:k=h=null;a=null==b?this.prepareUnsignedIdentityCertificatePromise(a,c,d,e,f,g,!h):this.prepareUnsignedIdentityCertificatePromise(a,b,c,d,e,f,g,!h);return SyncPromise.complete(h,k,a)};
+IdentityManager.prototype.prepareUnsignedIdentityCertificatePromise=function(a,b,c,d,e,f,g,h){b instanceof PublicKey||(h=g,g=f,f=e,e=d,d=c,c=b,b=null);var k=g;g=k instanceof Name?k:null;return(null==b?this.identityStorage.getKeyPromise(a,"boolean"===typeof k?k:"boolean"===typeof h?h:!1).then(function(a){b=new PublicKey(a);return SyncPromise.resolve()}):SyncPromise.resolve()).then(function(){return SyncPromise.resolve(IdentityManager.prepareUnsignedIdentityCertificateHelper_(a,b,c,d,e,f,g))})};
+IdentityManager.prepareUnsignedIdentityCertificateHelper_=function(a,b,c,d,e,f,g){if(1>a.size())return null;var h=a.get(-1).toEscapedString();if(4>h.length)return null;keyIdPrefix=h.substr(0,4);if("ksk-"!=keyIdPrefix&&"dsk-"!=keyIdPrefix)return null;var h=new IdentityCertificate,k=new Name;if(null==g)c.match(a)?k.append(c).append("KEY").append(a.getSubName(c.size())).append("ID-CERT").appendVersion((new Date).getTime()):k.append(a.getPrefix(-1)).append("KEY").append(a.get(-1)).append("ID-CERT").appendVersion((new Date).getTime());
+else if(g.match(a)&&!g.equals(a))k.append(g).append("KEY").append(a.getSubName(g.size())).append("ID-CERT").appendVersion((new Date).getTime());else return null;h.setName(k);h.setNotBefore(d);h.setNotAfter(e);h.setPublicKeyInfo(b);if(null==f||0===f.length)h.addSubjectDescription(new CertificateSubjectDescription("2.5.4.41",a.getPrefix(-1).toUri()));else for(a=0;a<f.length;++a)h.addSubjectDescription(f[a]);try{h.encode()}catch(l){throw SecurityException(Error("DerEncodingException: "+l));}return h};
+IdentityManager.prototype.addCertificate=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.addCertificatePromise(a,!b))};IdentityManager.prototype.setDefaultCertificateForKeyPromise=function(a,b){var c=this,d=a.getPublicKeyName();return this.identityStorage.doesKeyExistPromise(d,b).then(function(e){if(!e)throw new SecurityException(Error("No corresponding Key record for certificate!"));return c.identityStorage.setDefaultCertificateNameForKeyPromise(d,a.getName(),b)})};
+IdentityManager.prototype.setDefaultCertificateForKey=function(a,b,c){return SyncPromise.complete(b,c,this.setDefaultCertificateForKeyPromise(a,!b))};IdentityManager.prototype.addCertificateAsIdentityDefaultPromise=function(a,b){var c=this;return this.identityStorage.addCertificatePromise(a,b).then(function(){var d=a.getPublicKeyName();return c.identityStorage.setDefaultKeyNameForIdentityPromise(d,b)}).then(function(){return c.setDefaultCertificateForKeyPromise(a,b)})};
+IdentityManager.prototype.addCertificateAsDefault=function(a,b,c){var d=!b,e=this;return SyncPromise.complete(b,c,this.identityStorage.addCertificatePromise(a,d).then(function(){return e.setDefaultCertificateForKeyPromise(a,d)}))};IdentityManager.prototype.getCertificate=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.getCertificatePromise(a,!1,!b))};
+IdentityManager.prototype.getDefaultCertificateNameForIdentityPromise=function(a,b){return this.identityStorage.getDefaultCertificateNameForIdentityPromise(a,b)};IdentityManager.prototype.getDefaultCertificateNameForIdentity=function(a,b,c){return SyncPromise.complete(b,c,this.identityStorage.getDefaultCertificateNameForIdentityPromise(a,!b))};
+IdentityManager.prototype.getDefaultCertificateName=function(a,b){var c=!a,d=this;return SyncPromise.complete(a,b,this.identityStorage.getDefaultIdentityPromise(c).then(function(a){return d.identityStorage.getDefaultCertificateNameForIdentityPromise(a,c)}))};IdentityManager.prototype.getAllIdentities=function(a,b,c,d){return SyncPromise.complete(c,d,this.identityStorage.getAllIdentitiesPromise(a,b,!c))};
+IdentityManager.prototype.getAllKeyNamesOfIdentity=function(a,b,c,d,e){return SyncPromise.complete(d,e,this.identityStorage.getAllKeyNamesOfIdentityPromise(a,b,c,!d))};IdentityManager.prototype.getAllCertificateNamesOfKey=function(a,b,c,d,e){return SyncPromise.complete(d,e,this.identityStorage.getAllCertificateNamesOfKeyPromise(a,b,c,!d))};
+IdentityManager.prototype.signByCertificatePromise=function(a,b,c,d){d="boolean"===typeof c?c:d;c="boolean"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();var e=IdentityManager.certificateNameToPublicKeyName(b),f=this;if(a instanceof Data){var g=[0];return this.makeSignatureByCertificatePromise(b,g,d).then(function(b){a.setSignature(b);b=a.wireEncode(c);return f.privateKeyStorage.signPromise(b.signedBuf(),e,g[0],d)}).then(function(b){a.getSignature().setSignature(b);a.wireEncode(c);return SyncPromise.resolve(a)})}g=
+[0];return this.makeSignatureByCertificatePromise(b,g,d).then(function(b){return f.privateKeyStorage.signPromise(a,e,g[0],d)}).then(function(a){signature.setSignature(a);return SyncPromise.resolve(signature)})};IdentityManager.prototype.signByCertificate=function(a,b,c,d,e){e="function"===typeof c?d:e;d="function"===typeof c?c:d;c="function"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();return SyncPromise.complete(d,e,this.signByCertificatePromise(a,b,c,!d))};
+IdentityManager.prototype.signInterestByCertificatePromise=function(a,b,c,d){d="boolean"===typeof c?c:d;c="boolean"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();var e=this,f,g=[0];return this.makeSignatureByCertificatePromise(b,g,d).then(function(h){f=h;a.getName().append(c.encodeSignatureInfo(f));a.getName().append(new Name.Component);h=a.wireEncode(c);var k=IdentityManager.certificateNameToPublicKeyName(b);return e.privateKeyStorage.signPromise(h.signedBuf(),k,g[0],d)}).then(function(b){f.setSignature(b);
+a.setName(a.getName().getPrefix(-1).append(c.encodeSignatureValue(f)));return SyncPromise.resolve(a)})};IdentityManager.prototype.signInterestByCertificate=function(a,b,c,d,e){e="function"===typeof c?d:e;d="function"===typeof c?c:d;c="function"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();return SyncPromise.complete(d,e,this.signInterestByCertificatePromise(a,b,c,!d))};
+IdentityManager.prototype.signWithSha256=function(a,b){b=b||WireFormat.getDefaultWireFormat();a.setSignature(new DigestSha256Signature);var c=a.wireEncode(b),d=Crypto.createHash("sha256");d.update(c.signedBuf());a.getSignature().setSignature(new Blob(d.digest(),!1));a.wireEncode(b)};
+IdentityManager.prototype.signInterestWithSha256=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=new DigestSha256Signature;a.getName().append(b.encodeSignatureInfo(c));a.getName().append(new Name.Component);var d=a.wireEncode(b),e=Crypto.createHash("sha256");e.update(d.signedBuf());c.setSignature(new Blob(e.digest(),!1));a.setName(a.getName().getPrefix(-1).append(b.encodeSignatureValue(c)))};
+IdentityManager.prototype.selfSignPromise=function(a,b){var c=new IdentityCertificate,d=this;return this.identityStorage.getKeyPromise(a,b).then(function(e){e=new PublicKey(e);var f=(new Date).getTime(),g=f+63072E6;c.setNotBefore(f);c.setNotAfter(g);f=a.getPrefix(-1).append("KEY").append(a.get(-1)).append("ID-CERT").appendVersion(c.getNotBefore());c.setName(f);c.setPublicKeyInfo(e);c.addSubjectDescription(new CertificateSubjectDescription("2.5.4.41",a.toUri()));c.encode();return d.signByCertificatePromise(c,
+c.getName(),b)})};IdentityManager.prototype.selfSign=function(a,b,c){return SyncPromise.complete(b,c,this.selfSignPromise(a,!b))};IdentityManager.certificateNameToPublicKeyName=function(a){for(var b=a.size()-1;0<=b&&"ID-CERT"!=a.get(b).toEscapedString();)--b;a=a.getSubName(0,b);for(b=0;b<a.size()&&"KEY"!=a.get(b).toEscapedString();)++b;return a.getSubName(0,b).append(a.getSubName(b+1,a.size()-b-1))};
+IdentityManager.prototype.makeSignatureByCertificatePromise=function(a,b,c){var d=IdentityManager.certificateNameToPublicKeyName(a);return this.privateKeyStorage.getPublicKeyPromise(d,c).then(function(c){c=c.getKeyType();var d=null;if(c==KeyType.RSA)d=new Sha256WithRsaSignature,b[0]=DigestAlgorithm.SHA256,d.getKeyLocator().setType(KeyLocatorType.KEYNAME),d.getKeyLocator().setKeyName(a.getPrefix(-1));else if(c==KeyType.ECDSA)d=new Sha256WithEcdsaSignature,b[0]=DigestAlgorithm.SHA256,d.getKeyLocator().setType(KeyLocatorType.KEYNAME),
+d.getKeyLocator().setKeyName(a.getPrefix(-1));else throw new SecurityException(Error("Key type is not recognized"));return SyncPromise.resolve(d)})};
+IdentityManager.prototype.generateKeyPairPromise=function(a,b,c,d){var e,f=this;return this.identityStorage.getNewKeyNamePromise(a,b,d).then(function(a){e=a;return f.privateKeyStorage.generateKeyPairPromise(e,c,d)}).then(function(){return f.privateKeyStorage.getPublicKeyPromise(e,d)}).then(function(a){return f.identityStorage.addKeyPromise(e,c.getKeyType(),a.getKeyDer())}).then(function(){return SyncPromise.resolve(e)})};
+IdentityManager.getDefaultIdentityStorage_=function(a,b){var c=a.get("pib","");if(""!==c&&"pib-sqlite3"!==c)throw new SecurityException(Error("Invalid config file pib value: "+c));return new BasicIdentityStorage(b)};
+IdentityManager.getDefaultPrivateKeyStorage_=function(a,b){var c=a.get("tpm","");if(""===c){if("darwin"===process.platform)throw b[0]="tpm-osxkeychain:",new SecurityException(Error("IdentityManager: OS X key chain storage is not yet implemented. You must supply a privateKeyStorage."));b[0]="tpm-file:";return new FilePrivateKeyStorage}if("tpm-osxkeychain"===c)throw b[0]="tpm-osxkeychain:",new SecurityException(Error("IdentityManager: tpm-osxkeychain is not yet implemented."));if("tpm-file"===c)return b[0]=
+"tpm-file:",new FilePrivateKeyStorage;throw new SecurityException(Error("Invalid config file tpm value: "+c));};IdentityManager.prototype.checkTpmPromise_=function(a){return this.identityStorage.getTpmLocatorPromise().then(function(b){return""!==b&&b!==a?Promise.reject(new SecurityException(Error("The TPM locator supplied does not match the TPM locator in the PIB: "+b+" != "+a))):Promise.resolve()},function(a){return Promise.resolve()})};
+var ValidationRequest=function(a,b,c,d,e){this.interest=a;this.onVerified=b;this.onValidationFailed=c;this.retry=d;this.stepCount=e};exports.ValidationRequest=ValidationRequest;
+var Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,DataUtils=require("../../encoding/data-utils.js").DataUtils,SecurityException=require("../security-exception.js").SecurityException,DigestSha256Signature=require("../../digest-sha256-signature.js").DigestSha256Signature,Sha256WithRsaSignature=require("../../sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("../../sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,UseSubtleCrypto=
+require("../../use-subtle-crypto-node.js").UseSubtleCrypto,PolicyManager=function(){};exports.PolicyManager=PolicyManager;PolicyManager.prototype.skipVerifyAndTrust=function(a){throw Error("PolicyManager.skipVerifyAndTrust is not implemented");};PolicyManager.prototype.requireVerify=function(a){throw Error("PolicyManager.requireVerify is not implemented");};PolicyManager.prototype.checkVerificationPolicy=function(a,b,c,d,e){throw Error("PolicyManager.checkVerificationPolicy is not implemented");};
+PolicyManager.prototype.checkSigningPolicy=function(a,b){throw Error("PolicyManager.checkSigningPolicy is not implemented");};PolicyManager.prototype.inferSigningIdentity=function(a){throw Error("PolicyManager.inferSigningIdentity is not implemented");};PolicyManager.verifyUsesString_=null;PolicyManager.setVerifyUsesString_=function(){var a=Crypto.createHash("sha256").digest();PolicyManager.verifyUsesString_="string"===typeof a};
+PolicyManager.verifySignature=function(a,b,c,d){if(a instanceof Sha256WithRsaSignature)c.isNull()?d(!1):PolicyManager.verifySha256WithRsaSignature(a.getSignature(),b,c,d);else if(a instanceof Sha256WithEcdsaSignature)c.isNull()?d(!1):PolicyManager.verifySha256WithEcdsaSignature(a.getSignature(),b,c,d);else if(a instanceof DigestSha256Signature)PolicyManager.verifyDigestSha256Signature(a.getSignature(),b,d);else throw new SecurityException(Error("PolicyManager.verify: Signature type is unknown"));
+};
+PolicyManager.verifySha256WithRsaSignature=function(a,b,c,d){if(UseSubtleCrypto()){var e={name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};crypto.subtle.importKey("spki",c.buf().buffer,e,!0,["verify"]).then(function(c){return crypto.subtle.verify(e,c,a.buf(),b.signedBuf())}).then(function(a){d(a)})}else{null===PolicyManager.verifyUsesString_&&PolicyManager.setVerifyUsesString_();var f=c.buf().toString("base64");c="-----BEGIN PUBLIC KEY-----\n";for(var g=0;g<f.length;g+=64)c+=f.substr(g,64)+"\n";c+=
+"-----END PUBLIC KEY-----";f=Crypto.createVerify("RSA-SHA256");f.update(b.signedBuf());g=PolicyManager.verifyUsesString_?DataUtils.toString(a.buf()):a.buf();d(f.verify(c,g))}};
+PolicyManager.verifySha256WithEcdsaSignature=function(a,b,c,d){if(UseSubtleCrypto())d(!1);else{null===PolicyManager.verifyUsesString_&&PolicyManager.setVerifyUsesString_();var e=c.buf().toString("base64");c="-----BEGIN PUBLIC KEY-----\n";for(var f=0;f<e.length;f+=64)c+=e.substr(f,64)+"\n";c+="-----END PUBLIC KEY-----";e=Crypto.createVerify("sha256");e.update(b.signedBuf());a=PolicyManager.verifyUsesString_?DataUtils.toString(a.buf()):a.buf();d(e.verify(c,a))}};
+PolicyManager.verifyDigestSha256Signature=function(a,b,c){var d=Crypto.createHash("sha256");d.update(b.signedBuf());b=new Blob(d.digest(),!1);c(b.equals(a))};var IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,CertificateCache=function(){this.cache={}};exports.CertificateCache=CertificateCache;CertificateCache.prototype.insertCertificate=function(a){var b=a.getName().getPrefix(-1);this.cache[b.toUri()]=a.wireEncode()};
+CertificateCache.prototype.deleteCertificate=function(a){delete this.cache[a.toUri()]};CertificateCache.prototype.getCertificate=function(a){a=this.cache[a.toUri()];if(void 0===a)return null;var b=new IdentityCertificate;b.wireDecode(a);return b};CertificateCache.prototype.reset=function(){this.cache={}};
+var fs=require("fs"),path=require("path"),Name=require("../../name.js").Name,Data=require("../../data.js").Data,Interest=require("../../interest.js").Interest,KeyLocator=require("../../key-locator.js").KeyLocator,KeyLocatorType=require("../../key-locator.js").KeyLocatorType,Blob=require("../../util/blob.js").Blob,IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,BoostInfoParser=require("../../util/boost-info-parser.js").BoostInfoParser,NdnRegexMatcher=require("../../util/ndn-regex-matcher.js").NdnRegexMatcher,
+CertificateCache=require("./certificate-cache.js").CertificateCache,ValidationRequest=require("./validation-request.js").ValidationRequest,SecurityException=require("../security-exception.js").SecurityException,WireFormat=require("../../encoding/wire-format.js").WireFormat,PolicyManager=require("./policy-manager.js").PolicyManager,NdnCommon=require("../../util/ndn-common.js").NdnCommon,ConfigPolicyManager=function(a,b,c,d,e,f){PolicyManager.call(this);void 0==b&&(b=null);void 0==c&&(c=5);void 0==
+d&&(d=3E3);void 0==e&&(e=36E5);void 0==f&&(f=1E3);this.certificateCache=null==b?new CertificateCache:b;this.maxDepth=c;this.keyGraceInterval=d;this.keyTimestampTtl=e;this.maxTrackedKeys=f;this.reset();null!=a&&""!=a&&this.load(a)};ConfigPolicyManager.prototype=new PolicyManager;ConfigPolicyManager.prototype.name="ConfigPolicyManager";exports.ConfigPolicyManager=ConfigPolicyManager;
+ConfigPolicyManager.prototype.reset=function(){this.certificateCache.reset();this.fixedCertificateCache={};this.keyTimestamps={};this.requiresVerification=!0;this.config=new BoostInfoParser;this.refreshManager=new ConfigPolicyManager.TrustAnchorRefreshManager};ConfigPolicyManager.prototype.load=function(a,b){this.reset();this.config.read(a,b);this.loadTrustAnchorCertificates()};ConfigPolicyManager.prototype.requireVerify=function(a){return this.requiresVerification};
+ConfigPolicyManager.prototype.checkSigningPolicy=function(a,b){return!0};ConfigPolicyManager.prototype.skipVerifyAndTrust=function(a){return!this.requiresVerification};
+ConfigPolicyManager.prototype.checkVerificationPolicy=function(a,b,c,d,e){if(b>this.maxDepth){try{d(a,"The verification stepCount "+b+" exceeded the maxDepth "+this.maxDepth)}catch(f){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(f))}return null}e=ConfigPolicyManager.extractSignature(a,e);if(null==e){try{d(a,"Cannot extract the signature from "+a.getName().toUri())}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}return null}if(!KeyLocator.canGetFromSignature(e)){try{d(a,
+"The signature type does not support a KeyLocator")}catch(h){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(h))}return null}var k=null;try{k=KeyLocator.getFromSignature(e)}catch(l){try{d(a,"Error in KeyLocator.getFromSignature: "+l)}catch(m){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(m))}return null}k=k.getKeyName();if(0==k.size()){try{d(a,"The signature KeyLocator doesn't have a key name")}catch(q){console.log("Error in onValidationFailed: "+
+NdnCommon.getErrorWithStackTrace(q))}return null}var p=a.getName(),s="data";a instanceof Interest&&(p=p.getPrefix(-4),s="interest");var w=this.findMatchingRule(p,s);if(null==w){try{d(a,"No matching rule found for "+p.toUri())}catch(M){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(M))}return null}s=["unknown"];if(!this.checkSignatureMatch(k,p,w,s)){try{d(a,s[0])}catch(O){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(O))}return null}this.refreshManager.refreshAnchors();
+p=this.refreshManager.getCertificate(k);null==p&&(p=this.certificateCache.getCertificate(k));var K=this;if(null==p)return e=new Interest(k),new ValidationRequest(e,function(e){var f;try{f=new IdentityCertificate(e)}catch(g){try{d(a,"Cannot decode certificate "+e.getName().toUri())}catch(h){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(h))}return null}K.certificateCache.insertCertificate(f);K.checkVerificationPolicy(a,b+1,c,d)},d,2,b+1);if(a instanceof Interest){var x=
+p.getPublicKeyName(),A=a.getName().get(-4).toNumber();if(!this.interestTimestampIsFresh(x,A,s)){try{d(a,s[0])}catch(I){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(I))}return null}}this.verify(e,a.wireEncode(),function(b,e){if(b){try{c(a)}catch(f){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(f))}a instanceof Interest&&K.updateTimestampForKey(x,A)}else try{d(a,e)}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}})};
+ConfigPolicyManager.prototype.loadTrustAnchorCertificates=function(){for(var a=this.config.getRoot().get("validator/trust-anchor"),b=0;b<a.length;++b){var c=a[b],d=c.get("type")[0].getValue(),e=!1,f;if("file"==d)f=c.get("file-name")[0].getValue(),e=!0;else if("base64"==d)f=c.get("base64-string")[0].getValue(),e=!1;else if("dir"==d){d=c.get("dir")[0].getValue();e=0;c=c.get("refresh");1<=c.length&&(c=c[0].getValue().match(/(\d+)([hms])/),null==c?e=0:(e=parseInt(c[1]),"s"!=c[2]&&(e*=60,"m"!=c[2]&&(e*=
+60))));this.refreshManager.addDirectory(d,1E3*e);continue}else if("any"==d){this.requiresVerification=!1;break}this.lookupCertificate(f,e)}};
+ConfigPolicyManager.prototype.checkSignatureMatch=function(a,b,c,d){c=c.get("checker")[0];var e=c.get("type")[0].getValue();if("fixed-signer"==e){b=c.get("signer")[0];c=b.get("type")[0].getValue();if("file"==c){if(c=this.lookupCertificate(b.get("file-name")[0].getValue(),!0),null==c)return d[0]="Can't find fixed-signer certificate file: "+b.get("file-name")[0].getValue(),!1}else if("base64"==c){if(c=this.lookupCertificate(b.get("base64-string")[0].getValue(),!1),null==c)return d[0]="Can't find fixed-signer certificate base64: "+
+b.get("base64-string")[0].getValue(),!1}else return d[0]="Unrecognized fixed-signer signerType: "+c,!1;if(c.getName().equals(a))return!0;d[0]='fixed-signer cert name "'+c.getName().toUri()+'" does not equal signatureName "'+a.toUri()+'"';return!1}if("hierarchical"==e){c=NdnRegexMatcher.match("^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>",a);if(null!=c){a=(new Name(c[1])).append(new Name(c[2]));if(ConfigPolicyManager.matchesRelation(b,a,"is-prefix-of"))return!0;d[0]='The hierarchical objectName "'+b.toUri()+
+'" is not a prefix of "'+a.toUri()+'"';return!1}d[0]='The hierarchical identityRegex "^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>" does not match signatureName "'+a.toUri()+'"';return!1}if("customized"==e){var f=c.get("key-locator")[0];c=f.getFirstValue("relation");if(null!=c){b=new Name(f.get("name")[0].getValue());if(ConfigPolicyManager.matchesRelation(a,b,c))return!0;d[0]='The custom signatureName "'+a.toUri()+'" does not match matchName "'+b.toUri()+'" using relation '+c;return!1}var g=f.getFirstValue("regex");
+if(null!=g){if(null!=NdnRegexMatcher.match(g,a))return!0;d[0]='The custom signatureName "'+a.toUri()+'" does not regex match simpleKeyRegex "'+g+'"';return!1}c=f.get("hyper-relation");if(1<=c.length){c=c[0];var g=c.getFirstValue("k-regex"),h=c.getFirstValue("k-expand"),f=c.getFirstValue("p-regex"),k=c.getFirstValue("p-expand");c=c.getFirstValue("h-relation");if(null!=g&&null!=h&&null!=f&&null!=k&&null!=c){e=NdnRegexMatcher.match(g,a);if(null==e||void 0===e[1])return d[0]='The custom hyper-relation signatureName "'+
+a.toUri()+'" does not match the keyRegex "'+g+'"',!1;a=ConfigPolicyManager.expand(e,h);e=NdnRegexMatcher.match(f,b);if(null==e||void 0===e[1])return d[0]='The custom hyper-relation objectName "'+b.toUri()+'" does not match the nameRegex "'+f+'"',!1;b=ConfigPolicyManager.expand(e,k);if(ConfigPolicyManager.matchesRelation(new Name(b),new Name(a),c))return!0;d[0]='The custom hyper-relation nameMatch "'+b+'" does not match the keyMatchPrefix "'+a+'" using relation '+c;return!1}}}d[0]="Unrecognized checkerType: "+
+e;return!1};ConfigPolicyManager.expand=function(a,b){return b.replace(/\\(\d)/g,function(b,d){return a[parseInt(d)]})};
+ConfigPolicyManager.prototype.lookupCertificate=function(a,b){var c;c=this.fixedCertificateCache[a];if(void 0===c){if(b)c=ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile(a);else{var d=new Buffer(a,"base64");c=new IdentityCertificate;c.wireDecode(d)}d=c.getName().getPrefix(-1).toUri();this.fixedCertificateCache[a]=d;this.certificateCache.insertCertificate(c)}else c=this.certificateCache.getCertificate(new Name(c));return c};
+ConfigPolicyManager.prototype.findMatchingRule=function(a,b){for(var c=this.config.getRoot().get("validator/rule"),d=0;d<c.length;++d){var e=c[d];if(e.get("for")[0].getValue()==b){var f=!0,g=e.get("filter");if(0==g.length)return e;for(var h=0;h<g.length;++h){var k=g[h],f=k.getFirstValue("regex");null===f?(f=k.get("relation")[0].getValue(),k=k.get("name")[0].getValue(),k=new Name(k),f=ConfigPolicyManager.matchesRelation(a,k,f)):f=null!==NdnRegexMatcher.match(f,a);if(!f)break}if(f)return e}}return null};
+ConfigPolicyManager.matchesRelation=function(a,b,c){var d=!1;"is-strict-prefix-of"==c?b.size()==a.size()?d=!1:b.match(a)&&(d=!0):"is-prefix-of"==c?b.match(a)&&(d=!0):"equal"==c&&b.equals(a)&&(d=!0);return d};ConfigPolicyManager.extractSignature=function(a,b){if(a instanceof Data)return a.getSignature();if(a instanceof Interest){b=b||WireFormat.getDefaultWireFormat();try{var c=b.decodeSignatureInfoAndValue(a.getName().get(-2).getValue().buf(),a.getName().get(-1).getValue().buf(),!1)}catch(d){return null}return c}return null};
+ConfigPolicyManager.prototype.interestTimestampIsFresh=function(a,b,c){a=this.keyTimestamps[a.toUri()];if(void 0==a){a=(new Date).getTime();var d=a+this.keyGraceInterval;if(b>a-this.keyGraceInterval&&b<d)return!0;c[0]="The command interest timestamp is not within the first use grace period of "+this.keyGraceInterval+" milliseconds.";return!1}return b<=a?(c[0]="The command interest timestamp is not newer than the previous timestamp",!1):!0};
+ConfigPolicyManager.prototype.updateTimestampForKey=function(a,b){this.keyTimestamps[a.toUri()]=b;var c=0,d=[],e=(new Date).getTime(),f=e,g=null,h;for(h in this.keyTimestamps){++c;var k=this.keyTimestamps[h];e-k>this.keyTimestampTtl?d.push(h):k<f&&(f=k,g=h)}if(c>=this.maxTrackedKeys){for(e=0;e<d.length;++e)delete this.keyTimestamps[d[e]],--c;c>this.maxTrackedKeys&&delete this.keyTimestamps[g]}};
+ConfigPolicyManager.prototype.verify=function(a,b,c){var d=KeyLocator.getFromSignature(a);if(d.getType()==KeyLocatorType.KEYNAME){var e=d.getKeyName(),d=this.refreshManager.getCertificate(e);null==d&&(d=this.certificateCache.getCertificate(e));null==d?c(!1,"Cannot find a certificate with name "+e.toUri()):(e=d.getPublicKeyInfo().getKeyDer(),e.isNull()?c(!1,"There is no public key in the certificate with name "+d.getName().toUri()):PolicyManager.verifySignature(a,b,e,function(a){a?c(!0):c(!1,"The signature did not verify with the given public key")}))}else c(!1,
+"The KeyLocator does not have a key name")};ConfigPolicyManager.TrustAnchorRefreshManager=function(){this.certificateCache=new CertificateCache;this.refreshDirectories={}};ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile=function(a){a=fs.readFileSync(a).toString();a=new Buffer(a,"base64");var b=new IdentityCertificate;b.wireDecode(new Blob(a,!1));return b};ConfigPolicyManager.TrustAnchorRefreshManager.prototype.getCertificate=function(a){return this.certificateCache.getCertificate(a)};
+ConfigPolicyManager.TrustAnchorRefreshManager.prototype.addDirectory=function(a,b){var c;try{c=fs.readdirSync(a)}catch(d){throw new SecurityException(Error("Cannot list files in directory "+a));}for(var e=[],f=0;f<c.length;++f){var g;try{var h=path.join(a,c[f]);g=ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile(h)}catch(k){continue}var l=g.getName().getPrefix(-1).toUri();this.certificateCache.insertCertificate(g);e.push(l)}this.refreshDirectories[a]={certificates:e,nextRefresh:(new Date).getTime()+
+b,refreshPeriod:b}};ConfigPolicyManager.TrustAnchorRefreshManager.prototype.refreshAnchors=function(){var a=(new Date).getTime(),b;for(b in this.refreshDirectories){var c=this.refreshDirectories[b];if(c.nextRefresh<=a){var d=c.certificates.slice(0),e;for(e in d)this.certificateCache.deleteCertificate(new Name(e));this.addDirectory(b,c.refreshPeriod)}}};
+var Name=require("../../name.js").Name,PolicyManager=require("./policy-manager.js").PolicyManager,NdnCommon=require("../../util/ndn-common.js").NdnCommon,NoVerifyPolicyManager=function(){PolicyManager.call(this)};NoVerifyPolicyManager.prototype=new PolicyManager;NoVerifyPolicyManager.prototype.name="NoVerifyPolicyManager";exports.NoVerifyPolicyManager=NoVerifyPolicyManager;NoVerifyPolicyManager.prototype.skipVerifyAndTrust=function(a){return!0};NoVerifyPolicyManager.prototype.requireVerify=function(a){return!1};
+NoVerifyPolicyManager.prototype.checkVerificationPolicy=function(a,b,c,d,e){try{c(a)}catch(f){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(f))}return null};NoVerifyPolicyManager.prototype.checkSigningPolicy=function(a,b){return!0};NoVerifyPolicyManager.prototype.inferSigningIdentity=function(a){return new Name};
+var Name=require("../../name.js").Name,Interest=require("../../interest.js").Interest,Data=require("../../data.js").Data,Blob=require("../../util/blob.js").Blob,IdentityCertificate=require("../certificate/identity-certificate.js").IdentityCertificate,KeyLocator=require("../../key-locator.js").KeyLocator,KeyLocatorType=require("../../key-locator.js").KeyLocatorType,SecurityException=require("../security-exception.js").SecurityException,WireFormat=require("../../encoding/wire-format.js").WireFormat,
+SyncPromise=require("../../util/sync-promise.js").SyncPromise,PolicyManager=require("./policy-manager.js").PolicyManager,NdnCommon=require("../../util/ndn-common.js").NdnCommon,SelfVerifyPolicyManager=function(a){PolicyManager.call(this);this.identityStorage=a};SelfVerifyPolicyManager.prototype=new PolicyManager;SelfVerifyPolicyManager.prototype.name="SelfVerifyPolicyManager";exports.SelfVerifyPolicyManager=SelfVerifyPolicyManager;SelfVerifyPolicyManager.prototype.skipVerifyAndTrust=function(a){return!1};
+SelfVerifyPolicyManager.prototype.requireVerify=function(a){return!0};
+SelfVerifyPolicyManager.prototype.checkVerificationPolicy=function(a,b,c,d,e){e=e||WireFormat.getDefaultWireFormat();if(a instanceof Data)this.verify(a.getSignature(),a.wireEncode(),function(b,e){if(b)try{c(a)}catch(f){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(f))}else try{d(a,e)}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}});else if(a instanceof Interest){if(2>a.getName().size()){try{d(a,"The signed interest has less than 2 components: "+
+a.getName().toUri())}catch(f){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(f))}return}var g;try{g=e.decodeSignatureInfoAndValue(a.getName().get(-2).getValue().buf(),a.getName().get(-1).getValue().buf(),!1)}catch(h){try{d(a,"Error decoding the signed interest signature: "+h)}catch(k){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(k))}return}this.verify(g,a.wireEncode(),function(b,e){if(b)try{c(a)}catch(f){console.log("Error in onVerified: "+
+NdnCommon.getErrorWithStackTrace(f))}else try{d(a,e)}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}})}else throw new SecurityException(Error("checkVerificationPolicy: unrecognized type for dataOrInterest"));return null};SelfVerifyPolicyManager.prototype.checkSigningPolicy=function(a,b){return!0};SelfVerifyPolicyManager.prototype.inferSigningIdentity=function(a){return new Name};
+SelfVerifyPolicyManager.prototype.verify=function(a,b,c){if(KeyLocator.canGetFromSignature(a))this.getPublicKeyDer(KeyLocator.getFromSignature(a),function(d,f){if(d.isNull())c(!1,f);else try{PolicyManager.verifySignature(a,b,d,function(a){a?c(!0):c(!1,"The signature did not verify with the given public key")})}catch(g){c(!1,"Error in verifySignature: "+g)}});else try{PolicyManager.verifySignature(a,b,null,function(a){a?c(!0):c(!1,"The signature did not verify with the given public key")})}catch(d){c(!1,
+"Error in verifySignature: "+d)}};
+SelfVerifyPolicyManager.prototype.getPublicKeyDer=function(a,b){if(a.getType()==KeyLocatorType.KEYNAME&&null!=this.identityStorage){var c;try{c=IdentityCertificate.certificateNameToPublicKeyName(a.getKeyName())}catch(d){b(new Blob,"Cannot get a public key name from the certificate named: "+a.getKeyName().toUri());return}SyncPromise.complete(b,function(a){b(new Blob,"The identityStorage doesn't have the key named "+c.toUri())},this.identityStorage.getKeyPromise(c))}else b(new Blob,"The signature KeyLocator doesn't have a key name")};
+Crypto=require("../crypto.js");Name=require("../name.js").Name;Interest=require("../interest.js").Interest;Data=require("../data.js").Data;Blob=require("../util/blob.js").Blob;WireFormat=require("../encoding/wire-format.js").WireFormat;SecurityException=require("./security-exception.js").SecurityException;RsaKeyParams=require("./key-params.js").RsaKeyParams;IdentityCertificate=require("./certificate/identity-certificate.js").IdentityCertificate;SyncPromise=require("../util/sync-promise.js").SyncPromise;
+NdnCommon=require("../util/ndn-common.js").NdnCommon;IdentityManager=require("./identity/identity-manager.js").IdentityManager;NoVerifyPolicyManager=require("./policy/no-verify-policy-manager.js").NoVerifyPolicyManager;KeyChain=function(a,b){a||(a=new IdentityManager);b||(b=new NoVerifyPolicyManager);this.identityManager=a;this.policyManager=b;this.face=null};exports.KeyChain=KeyChain;
+KeyChain.prototype.createIdentityAndCertificate=function(a,b,c,d){d="function"===typeof b?c:d;c="function"===typeof b?b:c;b="function"!==typeof b&&b?b:KeyChain.DEFAULT_KEY_PARAMS;return this.identityManager.createIdentityAndCertificate(a,b,c,d)};KeyChain.prototype.createIdentity=function(a,b){return IdentityCertificate.certificateNameToPublicKeyName(this.createIdentityAndCertificate(a,b))};KeyChain.prototype.deleteIdentity=function(a,b,c){this.identityManager.deleteIdentity(a,b,c)};
+KeyChain.prototype.getDefaultIdentity=function(a,b){return this.identityManager.getDefaultIdentity(a,b)};KeyChain.prototype.getDefaultCertificateName=function(a,b){return this.identityManager.getDefaultCertificateName(a,b)};KeyChain.prototype.generateRSAKeyPair=function(a,b,c){(c="boolean"===typeof b?b:c)||(c=2048);return this.identityManager.generateRSAKeyPair(a,"boolean"===typeof b?b:!1,c)};
+KeyChain.prototype.setDefaultKeyForIdentity=function(a,b,c,d){return this.identityManager.setDefaultKeyForIdentity(a,b,c,d)};KeyChain.prototype.generateRSAKeyPairAsDefault=function(a,b,c){return this.identityManager.generateRSAKeyPairAsDefault(a,b,c)};KeyChain.prototype.createSigningRequest=function(a){return this.identityManager.getPublicKey(a).getKeyDer()};KeyChain.prototype.installIdentityCertificate=function(a,b,c){this.identityManager.addCertificate(a,b,c)};
+KeyChain.prototype.setDefaultCertificateForKey=function(a,b,c){this.identityManager.setDefaultCertificateForKey(a,b,c)};KeyChain.prototype.getCertificate=function(a,b,c){return this.identityManager.getCertificate(a,b,c)};KeyChain.prototype.getIdentityCertificate=function(a,b,c){return this.identityManager.getCertificate(a,b,c)};KeyChain.prototype.revokeKey=function(a){};KeyChain.prototype.revokeCertificate=function(a){};KeyChain.prototype.getIdentityManager=function(){return this.identityManager};
+KeyChain.prototype.getPolicyManager=function(){return this.policyManager};KeyChain.prototype.sign=function(a,b,c,d,e){var f=b,g=c,h=d;b=f instanceof Name?f:null;c=f instanceof WireFormat?f:g instanceof WireFormat?g:null;"function"===typeof f?(d=f,e=g):"function"===typeof g?(d=g,e=h):"function"===typeof h?d=h:e=d=null;return SyncPromise.complete(d,e,this.signPromise(a,b,c,!d))};
+KeyChain.prototype.signPromise=function(a,b,c,d){var e=b,f=c,g=d;b=e instanceof Name?e:null;c=e instanceof WireFormat?e:f instanceof WireFormat?f:null;d="boolean"===typeof e?e:"boolean"===typeof f?f:"boolean"===typeof g?g:!1;var h=this;return SyncPromise.resolve().then(function(){return null!=b?SyncPromise.resolve():h.identityManager.getDefaultCertificatePromise(d).then(function(a){return null!=a?(b=a.getName(),SyncPromise.resolve()):h.prepareDefaultCertificateNamePromise_(d).then(function(a){b=a;
+return SyncPromise.resolve()})})}).then(function(){return a instanceof Interest?h.identityManager.signInterestByCertificatePromise(a,b,c,d):a instanceof Data?h.identityManager.signByCertificatePromise(a,b,c,d):h.identityManager.signByCertificatePromise(a,b,d)})};
+KeyChain.prototype.signByIdentity=function(a,b,c,d,e){e="function"===typeof c?d:e;d="function"===typeof c?c:d;c="function"!==typeof c&&c?c:WireFormat.getDefaultWireFormat();var f=!d,g=this;null==b&&(b=new Name);if(a instanceof Data){var h=SyncPromise.resolve().then(function(){if(0==b.size()){var c=g.policyManager.inferSigningIdentity(a.getName());return 0==c.size()?g.identityManager.getDefaultCertificateNamePromise(f):g.identityManager.getDefaultCertificateNameForIdentityPromise(c,f)}return g.identityManager.getDefaultCertificateNameForIdentityPromise(b,
+f)}).then(function(b){if(0==b.size())throw new SecurityException(Error("No qualified certificate name found!"));if(!g.policyManager.checkSigningPolicy(a.getName(),b))throw new SecurityException(Error("Signing Cert name does not comply with signing policy"));return g.identityManager.signByCertificatePromise(a,b,c,f)});return SyncPromise.complete(d,e,h)}return SyncPromise.complete(d,e,this.identityManager.getDefaultCertificateNameForIdentityPromise(b,f).then(function(b){if(0==b.size())throw new SecurityException(Error("No qualified certificate name found!"));
+return g.identityManager.signByCertificatePromise(a,b,c,f)}))};KeyChain.prototype.signWithSha256=function(a,b){a instanceof Interest?this.identityManager.signInterestWithSha256(a,b):this.identityManager.signWithSha256(a,b)};
+KeyChain.prototype.verifyData=function(a,b,c,d){null==d&&(d=0);if(this.policyManager.requireVerify(a)){var e=this.policyManager.checkVerificationPolicy(a,d,b,c);if(null!=e){var f=this;this.face.expressInterest(e.interest,function(a,b){f.onCertificateData(a,b,e)},function(b){f.onCertificateInterestTimeout(b,e.retry,c,a,e)})}}else if(this.policyManager.skipVerifyAndTrust(a))try{b(a)}catch(g){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(g))}else try{c(a,"The packet has no verify rule but skipVerifyAndTrust is false")}catch(h){console.log("Error in onValidationFailed: "+
+NdnCommon.getErrorWithStackTrace(h))}};
+KeyChain.prototype.verifyInterest=function(a,b,c,d,e){null==d&&(d=0);e=e||WireFormat.getDefaultWireFormat();if(this.policyManager.requireVerify(a)){var f=this.policyManager.checkVerificationPolicy(a,d,b,c,e);if(null!=f){var g=this;this.face.expressInterest(f.interest,function(a,b){g.onCertificateData(a,b,f)},function(b){g.onCertificateInterestTimeout(b,f.retry,c,a,f)})}}else if(this.policyManager.skipVerifyAndTrust(a))try{b(a)}catch(h){console.log("Error in onVerified: "+NdnCommon.getErrorWithStackTrace(h))}else try{c(a,
+"The packet has no verify rule but skipVerifyAndTrust is false")}catch(k){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(k))}};KeyChain.prototype.setFace=function(a){this.face=a};
+KeyChain.signWithHmacWithSha256=function(a,b,c){c=c||WireFormat.getDefaultWireFormat();if(a instanceof Data)c=a.wireEncode(c),b=Crypto.createHmac("sha256",b.buf()),b.update(c.signedBuf()),a.getSignature().setSignature(new Blob(b.digest(),!1));else throw new SecurityException(Error("signWithHmacWithSha256: Unrecognized target type"));};
+KeyChain.verifyDataWithHmacWithSha256=function(a,b,c){c=c||WireFormat.getDefaultWireFormat();c=a.wireEncode(c);b=Crypto.createHmac("sha256",b.buf());b.update(c.signedBuf());return(new Blob(b.digest(),!1)).equals(a.getSignature().getSignature())};KeyChain.DEFAULT_KEY_PARAMS=new RsaKeyParams;KeyChain.prototype.onCertificateData=function(a,b,c){this.verifyData(b,c.onVerified,c.onValidationFailed,c.stepCount)};
+KeyChain.prototype.onCertificateInterestTimeout=function(a,b,c,d,e){if(0<b){var f=this;this.face.expressInterest(a,function(a,b){f.onCertificateData(a,b,e)},function(a){f.onCertificateInterestTimeout(a,b-1,c,d,e)})}else try{c(d,"The retry count is zero after timeout for fetching "+a.getName().toUri())}catch(g){console.log("Error in onValidationFailed: "+NdnCommon.getErrorWithStackTrace(g))}};
+KeyChain.prototype.prepareDefaultCertificateNamePromise_=function(a){var b,c=this;return this.identityManager.getDefaultCertificatePromise(a).then(function(d){b=d;return null!=b?SyncPromise.resolve():c.setDefaultCertificatePromise_(a).then(function(){return c.identityManager.getDefaultCertificatePromise(a)}).then(function(a){b=a;return SyncPromise.resolve()})}).then(function(){return SyncPromise.resolve(b.getName())})};
+KeyChain.prototype.setDefaultCertificatePromise_=function(a){var b=this;return this.identityManager.getDefaultCertificatePromise(a).then(function(c){if(null!=c)return SyncPromise.resolve();var d;return b.identityManager.getDefaultIdentityPromise(a).then(function(a){d=a;return SyncPromise.resolve()},function(a){randomComponent=Crypto.randomBytes(4);d=(new Name).append("tmp-identity").append(new Blob(randomComponent,!1));return SyncPromise.resolve()}).then(function(){return b.identityManager.createIdentityAndCertificatePromise(d,
+KeyChain.DEFAULT_KEY_PARAMS,a)}).then(function(){return b.identityManager.setDefaultIdentityPromise(d,a)})})};var Name=require("./name.js").Name,DataUtils=require("./encoding/data-utils.js").DataUtils,Blob=require("./util/blob.js").Blob,Exclude=function Exclude(b){this.values=[];if("object"===typeof b&&b instanceof Exclude)this.values=b.values.slice(0);else if(b)for(var c=this.changeCount=0;c<b.length;++c)b[c]==Exclude.ANY?this.appendAny():this.appendComponent(b[c]);this.changeCount=0};
+exports.Exclude=Exclude;Exclude.ANY="*";Exclude.prototype.size=function(){return this.values.length};Exclude.prototype.get=function(a){return this.values[a]};Exclude.prototype.appendAny=function(){this.values.push(Exclude.ANY);++this.changeCount;return this};Exclude.prototype.appendComponent=function(a){this.values.push(new Name.Component(a));++this.changeCount;return this};Exclude.prototype.clear=function(){++this.changeCount;this.values=[]};
+Exclude.prototype.toUri=function(){if(null==this.values||0==this.values.length)return"";for(var a="",b=0;b<this.values.length;++b)0<b&&(a+=","),a=this.values[b]==Exclude.ANY?a+"*":a+this.values[b].toEscapedString();return a};
+Exclude.prototype.matches=function(a){"object"==typeof a&&a instanceof Name.Component||(a=new Name.Component(a));for(var b=0;b<this.values.length;++b)if(this.values[b]==Exclude.ANY){var c=null;0<b&&(c=this.values[b-1]);var d,e=null;for(d=b+1;d<this.values.length;++d)if(this.values[d]!=Exclude.ANY){e=this.values[d];break}if(null!=e){if(null!=c){if(0<a.compare(c)&&0>a.compare(e))return!0}else if(0>a.compare(e))return!0;b=d-1}else if(null!=c){if(0<a.compare(c))return!0}else return!0}else if(a.equals(this.values[b]))return!0;
+return!1};Exclude.compareComponents=function(a,b){"object"==typeof a&&a instanceof Name.Component&&(a=a.getValue().buf());"object"==typeof b&&b instanceof Name.Component&&(b=b.getValue().buf());return Name.Component.compareBuffers(a,b)};Exclude.prototype.getChangeCount=function(){return this.changeCount};
+var Crypto=require("./crypto.js"),Blob=require("./util/blob.js").Blob,SignedBlob=require("./util/signed-blob.js").SignedBlob,ChangeCounter=require("./util/change-counter.js").ChangeCounter,Name=require("./name.js").Name,Exclude=require("./exclude.js").Exclude,Link=require("./link.js").Link,KeyLocator=require("./key-locator.js").KeyLocator,IncomingFaceId=require("./lp/incoming-face-id.js").IncomingFaceId,WireFormat=require("./encoding/wire-format.js").WireFormat,Interest=function Interest(b,c,d,e,
+f,g,h,k,l,m){if(e)throw Error("Interest constructor: PublisherPublicKeyDigest support has been removed.");if(h)throw Error("Interest constructor: answerOriginKind support has been removed. Use setMustBeFresh().");if(k)throw Error("Interest constructor: scope support has been removed.");"object"===typeof b&&b instanceof Interest?(this.name_=new ChangeCounter(new Name(b.getName())),this.maxSuffixComponents_=b.maxSuffixComponents_,this.minSuffixComponents_=b.minSuffixComponents_,this.keyLocator_=new ChangeCounter(new KeyLocator(b.getKeyLocator())),
+this.exclude_=new ChangeCounter(new Exclude(b.getExclude())),this.childSelector_=b.childSelector_,this.mustBeFresh_=b.mustBeFresh_,this.interestLifetimeMilliseconds_=b.interestLifetimeMilliseconds_,this.nonce_=b.nonce_,this.linkWireEncoding_=b.linkWireEncoding_,this.linkWireEncodingFormat_=b.linkWireEncodingFormat_,this.link_=new ChangeCounter(null),null!=b.link_.get()&&this.link_.set(new Link(b.link_.get())),this.selectedDelegationIndex_=b.selectedDelegationIndex_,this.defaultWireEncoding_=b.getDefaultWireEncoding(),
+this.defaultWireEncodingFormat_=b.defaultWireEncodingFormat_):(this.name_=new ChangeCounter("object"===typeof b&&b instanceof Name?new Name(b):new Name),this.maxSuffixComponents_=d,this.minSuffixComponents_=c,this.keyLocator_=new ChangeCounter(new KeyLocator),this.exclude_=new ChangeCounter("object"===typeof f&&f instanceof Exclude?new Exclude(f):new Exclude),this.childSelector_=g,this.mustBeFresh_=!0,this.interestLifetimeMilliseconds_=l,this.nonce_="object"===typeof m&&m instanceof Blob?m:new Blob(m,
+!0),this.linkWireEncoding_=new Blob,this.linkWireEncodingFormat_=null,this.link_=new ChangeCounter(null),this.selectedDelegationIndex_=null,this.defaultWireEncoding_=new SignedBlob,this.defaultWireEncodingFormat_=null);this.changeCount_=this.getDefaultWireEncodingChangeCount_=this.getNonceChangeCount_=0;this.lpPacket_=null};exports.Interest=Interest;Interest.RECURSIVE_POSTFIX="*";Interest.CHILD_SELECTOR_LEFT=0;Interest.CHILD_SELECTOR_RIGHT=1;
+Interest.prototype.matchesName=function(a){return!this.getName().match(a)||null!=this.minSuffixComponents_&&!(a.size()+1-this.getName().size()>=this.minSuffixComponents_)||null!=this.maxSuffixComponents_&&!(a.size()+1-this.getName().size()<=this.maxSuffixComponents_)||null!=this.getExclude()&&a.size()>this.getName().size()&&this.getExclude().matches(a.get(this.getName().size()))?!1:!0};Interest.prototype.matches_name=function(a){return this.matchesName(a)};
+Interest.prototype.matchesData=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=this.getName().size(),d=a.getName(),e=d.size()+1,f=null!=this.getMinSuffixComponents()?this.getMinSuffixComponents():0;if(!(c+f<=e&&(null==this.getMaxSuffixComponents()||c+this.getMaxSuffixComponents()>=e)))return!1;if(c===e)if(this.getName().get(-1).isImplicitSha256Digest()){if(!this.getName().equals(a.getFullName(b)))return!1}else return!1;else if(!this.getName().isPrefixOf(d))return!1;if(0<this.getExclude().size()&&
+e>c)if(c==e-1){if(this.getExclude().matches(a.getFullName(b).get(c)))return!1}else if(this.getExclude().matches(d.get(c)))return!1;c=this.getKeyLocator();return!c.getType()||(d=a.getSignature(),KeyLocator.canGetFromSignature(d)&&c.equals(KeyLocator.getFromSignature(d)))?!0:!1};Interest.prototype.clone=function(){return new Interest(this)};Interest.prototype.getName=function(){return this.name_.get()};Interest.prototype.getMinSuffixComponents=function(){return this.minSuffixComponents_};
+Interest.prototype.getMaxSuffixComponents=function(){return this.maxSuffixComponents_};Interest.prototype.getKeyLocator=function(){return this.keyLocator_.get()};Interest.prototype.getExclude=function(){return this.exclude_.get()};Interest.prototype.getChildSelector=function(){return this.childSelector_};Interest.prototype.getMustBeFresh=function(){return this.mustBeFresh_};
+Interest.prototype.getNonce=function(){this.getNonceChangeCount_!=this.getChangeCount()&&(this.nonce_=new Blob,this.getNonceChangeCount_=this.getChangeCount());return this.nonce_};Interest.prototype.getNonceAsBuffer=function(){return this.getNonce().buf()};Interest.prototype.hasLink=function(){return null!=this.link_.get()||!this.linkWireEncoding_.isNull()};
+Interest.prototype.getLink=function(){if(null!=this.link_.get())return this.link_.get();if(this.linkWireEncoding_.isNull())return null;var a=new Link;a.wireDecode(this.linkWireEncoding_,this.linkWireEncodingFormat_);this.link_.set(a);this.linkWireEncoding_=new Blob;this.linkWireEncodingFormat_=null;return a};
+Interest.prototype.getLinkWireEncoding=function(a){a=a||WireFormat.getDefaultWireFormat();if(!this.linkWireEncoding_.isNull()&&this.linkWireEncodingFormat_==a)return this.linkWireEncoding_;var b=this.getLink();return null!=b?b.wireEncode(a):new Blob};Interest.prototype.getSelectedDelegationIndex=function(){return this.selectedDelegationIndex_};Interest.prototype.getInterestLifetimeMilliseconds=function(){return this.interestLifetimeMilliseconds_};
+Interest.prototype.getDefaultWireEncoding=function(){this.getDefaultWireEncodingChangeCount_!=this.getChangeCount()&&(this.defaultWireEncoding_=new SignedBlob,this.defaultWireEncodingFormat_=null,this.getDefaultWireEncodingChangeCount_=this.getChangeCount());return this.defaultWireEncoding_};Interest.prototype.getDefaultWireEncodingFormat=function(){return this.defaultWireEncodingFormat_};
+Interest.prototype.getIncomingFaceId=function(){var a=null===this.lpPacket_?null:IncomingFaceId.getFirstHeader(this.lpPacket_);return null===a?null:a.getFaceId()};Interest.prototype.setName=function(a){this.name_.set("object"===typeof a&&a instanceof Name?new Name(a):new Name);++this.changeCount_;return this};Interest.prototype.setMinSuffixComponents=function(a){this.minSuffixComponents_=a;++this.changeCount_;return this};
+Interest.prototype.setMaxSuffixComponents=function(a){this.maxSuffixComponents_=a;++this.changeCount_;return this};Interest.prototype.setKeyLocator=function(a){this.keyLocator_.set("object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator);++this.changeCount_;return this};Interest.prototype.setExclude=function(a){this.exclude_.set("object"===typeof a&&a instanceof Exclude?new Exclude(a):new Exclude);++this.changeCount_;return this};
+Interest.prototype.setLinkWireEncoding=function(a,b){b=b||WireFormat.getDefaultWireFormat();this.linkWireEncoding_=a;this.linkWireEncodingFormat_=b;this.link_.set(null);++this.changeCount_;return this};Interest.prototype.unsetLink=function(){return this.setLinkWireEncoding(new Blob,null)};Interest.prototype.setSelectedDelegationIndex=function(a){this.selectedDelegationIndex_=a;++this.changeCount_;return this};
+Interest.prototype.setChildSelector=function(a){this.childSelector_=a;++this.changeCount_;return this};Interest.prototype.setMustBeFresh=function(a){this.mustBeFresh_=a?!0:!1;++this.changeCount_;return this};Interest.prototype.setInterestLifetimeMilliseconds=function(a){this.interestLifetimeMilliseconds_=a;++this.changeCount_;return this};
+Interest.prototype.setNonce=function(a){this.nonce_="object"===typeof a&&a instanceof Blob?a:new Blob(a,!0);++this.changeCount_;this.getNonceChangeCount_=this.getChangeCount();return this};
+Interest.prototype.toUri=function(){var a="";null!=this.minSuffixComponents_&&(a+="&ndn.MinSuffixComponents="+this.minSuffixComponents_);null!=this.maxSuffixComponents_&&(a+="&ndn.MaxSuffixComponents="+this.maxSuffixComponents_);null!=this.childSelector_&&(a+="&ndn.ChildSelector="+this.childSelector_);a+="&ndn.MustBeFresh="+(this.mustBeFresh_?1:0);null!=this.interestLifetimeMilliseconds_&&(a+="&ndn.InterestLifetime="+this.interestLifetimeMilliseconds_);0<this.getNonce().size()&&(a+="&ndn.Nonce="+
+Name.toEscapedString(this.getNonce().buf()));null!=this.getExclude()&&0<this.getExclude().size()&&(a+="&ndn.Exclude="+this.getExclude().toUri());var b=this.getName().toUri();""!=a&&(b+="?"+a.substr(1));return b};
+Interest.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();if(!this.getDefaultWireEncoding().isNull()&&this.getDefaultWireEncodingFormat()==a)return this.getDefaultWireEncoding();var b=a.encodeInterest(this),b=new SignedBlob(b.encoding,b.signedPortionBeginOffset,b.signedPortionEndOffset);a==WireFormat.getDefaultWireFormat()&&this.setDefaultWireEncoding(b,WireFormat.getDefaultWireFormat());return b};
+Interest.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c;c="object"===typeof a&&a instanceof Blob?b.decodeInterest(this,a.buf(),!1):b.decodeInterest(this,a,!0);b==WireFormat.getDefaultWireFormat()?this.setDefaultWireEncoding(new SignedBlob(new Blob(a,!0),c.signedPortionBeginOffset,c.signedPortionEndOffset),WireFormat.getDefaultWireFormat()):this.setDefaultWireEncoding(new SignedBlob,null)};
+Interest.prototype.refreshNonce=function(){var a=this.getNonce();if(0!==a.size()){for(var b;b=new Blob(Crypto.randomBytes(a.size()),!1),b.equals(a););this.nonce_=b;++this.changeCount_;this.getNonceChangeCount_=this.getChangeCount()}};Interest.prototype.setLpPacket=function(a){this.lpPacket_=a;return this};Interest.prototype.getChangeCount=function(){var a=this.name_.checkChanged(),a=this.keyLocator_.checkChanged()||a;(a=this.exclude_.checkChanged()||a)&&++this.changeCount_;return this.changeCount_};
+Interest.prototype.setDefaultWireEncoding=function(a,b){this.defaultWireEncoding_=a;this.defaultWireEncodingFormat_=b;this.getDefaultWireEncodingChangeCount_=this.getChangeCount()};Object.defineProperty(Interest.prototype,"name",{get:function(){return this.getName()},set:function(a){this.setName(a)}});Object.defineProperty(Interest.prototype,"minSuffixComponents",{get:function(){return this.getMinSuffixComponents()},set:function(a){this.setMinSuffixComponents(a)}});
+Object.defineProperty(Interest.prototype,"maxSuffixComponents",{get:function(){return this.getMaxSuffixComponents()},set:function(a){this.setMaxSuffixComponents(a)}});Object.defineProperty(Interest.prototype,"keyLocator",{get:function(){return this.getKeyLocator()},set:function(a){this.setKeyLocator(a)}});Object.defineProperty(Interest.prototype,"exclude",{get:function(){return this.getExclude()},set:function(a){this.setExclude(a)}});
+Object.defineProperty(Interest.prototype,"childSelector",{get:function(){return this.getChildSelector()},set:function(a){this.setChildSelector(a)}});Object.defineProperty(Interest.prototype,"interestLifetime",{get:function(){return this.getInterestLifetimeMilliseconds()},set:function(a){this.setInterestLifetimeMilliseconds(a)}});Object.defineProperty(Interest.prototype,"nonce",{get:function(){return this.getNonceAsBuffer()},set:function(a){this.setNonce(a)}});
+ForwardingFlags=function ForwardingFlags(b){"object"===typeof b&&b instanceof ForwardingFlags?(this.childInherit=b.childInherit,this.capture=b.capture):(this.childInherit=!0,this.capture=!1)};exports.ForwardingFlags=ForwardingFlags;ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT=1;ForwardingFlags.NfdForwardingFlags_CAPTURE=2;
+ForwardingFlags.prototype.getNfdForwardingFlags=function(){var a=0;this.childInherit&&(a|=ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT);this.capture&&(a|=ForwardingFlags.NfdForwardingFlags_CAPTURE);return a};ForwardingFlags.prototype.setNfdForwardingFlags=function(a){this.childInherit=0!=(a&ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT);this.capture=0!=(a&ForwardingFlags.NfdForwardingFlags_CAPTURE)};ForwardingFlags.prototype.getChildInherit=function(){return this.childInherit};
+ForwardingFlags.prototype.getCapture=function(){return this.capture};ForwardingFlags.prototype.setChildInherit=function(a){this.childInherit=a};ForwardingFlags.prototype.setCapture=function(a){this.capture=a};
+var ForwardingFlags=require("./forwarding-flags.js").ForwardingFlags,Name=require("./name.js").Name,WireFormat=require("./encoding/wire-format.js").WireFormat,Blob=require("./util/blob.js").Blob,ControlParameters=function ControlParameters(b){"object"===typeof b&&b instanceof ControlParameters?(this.name=null==b.name?null:new Name(b.name),this.faceId=b.faceId,this.uri=b.uri,this.localControlFeature=b.localControlFeature,this.origin=b.origin,this.cost=b.cost,this.forwardingFlags=new ForwardingFlags(b.forwardingFlags),
+this.strategy=new Name(b.strategy),this.expirationPeriod=b.expirationPeriod):(this.faceId=this.name=null,this.uri="",this.cost=this.origin=this.localControlFeature=null,this.forwardingFlags=new ForwardingFlags,this.strategy=new Name,this.expirationPeriod=null)};exports.ControlParameters=ControlParameters;
+ControlParameters.prototype.clear=function(){this.faceId=this.name=null;this.uri="";this.cost=this.origin=this.localControlFeature=null;this.forwardingFlags=new ForwardingFlags;this.strategy=new Name;this.expirationPeriod=null};ControlParameters.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeControlParameters(this)};
+ControlParameters.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeControlParameters(this,a.buf(),!1):b.decodeControlParameters(this,a,!0)};ControlParameters.prototype.getName=function(){return this.name};ControlParameters.prototype.getFaceId=function(){return this.faceId};ControlParameters.prototype.getUri=function(){return this.uri};ControlParameters.prototype.getLocalControlFeature=function(){return this.localControlFeature};
+ControlParameters.prototype.getOrigin=function(){return this.origin};ControlParameters.prototype.getCost=function(){return this.cost};ControlParameters.prototype.getForwardingFlags=function(){return this.forwardingFlags};ControlParameters.prototype.getStrategy=function(){return this.strategy};ControlParameters.prototype.getExpirationPeriod=function(){return this.expirationPeriod};ControlParameters.prototype.setName=function(a){this.name="object"===typeof a&&a instanceof Name?new Name(a):null};
+ControlParameters.prototype.setFaceId=function(a){this.faceId=a};ControlParameters.prototype.setUri=function(a){this.uri=a||""};ControlParameters.prototype.setLocalControlFeature=function(a){this.localControlFeature=a};ControlParameters.prototype.setOrigin=function(a){this.origin=a};ControlParameters.prototype.setCost=function(a){this.cost=a};ControlParameters.prototype.setForwardingFlags=function(a){this.forwardingFlags="object"===typeof a&&a instanceof ForwardingFlags?new ForwardingFlags(a):new ForwardingFlags};
+ControlParameters.prototype.setStrategy=function(a){this.strategy="object"===typeof a&&a instanceof Name?new Name(a):new Name};ControlParameters.prototype.setExpirationPeriod=function(a){this.expirationPeriod=a};
+var ControlParameters=require("./control-parameters.js").ControlParameters,WireFormat=require("./encoding/wire-format.js").WireFormat,Blob=require("./util/blob.js").Blob,ControlResponse=function ControlResponse(b){"object"===typeof b&&b instanceof ControlResponse?(this.statusCode_=b.statusCode_,this.statusText_=b.statusText_,this.bodyAsControlParameters_=null==b.bodyAsControlParameters_?null:new ControlParameters(b.bodyAsControlParameters_)):(this.statusCode_=null,this.statusText_="",this.bodyAsControlParameters_=
+null)};exports.ControlResponse=ControlResponse;ControlResponse.prototype.clear=function(){this.statusCode_=null;this.statusText_="";this.bodyAsControlParameters_=null};ControlResponse.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeControlResponse(this)};ControlResponse.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeControlResponse(this,a.buf(),!1):b.decodeControlResponse(this,a,!0)};
+ControlResponse.prototype.getStatusCode=function(){return this.statusCode_};ControlResponse.prototype.getStatusText=function(){return this.statusText_};ControlResponse.prototype.getBodyAsControlParameters=function(){return this.bodyAsControlParameters_};ControlResponse.prototype.setStatusCode=function(a){this.statusCode_=a;return this};ControlResponse.prototype.setStatusText=function(a){this.statusText_=a||"";return this};
+ControlResponse.prototype.setBodyAsControlParameters=function(a){this.bodyAsControlParameters_="object"===typeof a&&a instanceof ControlParameters?new ControlParameters(a):null;return this};Name=require("./name.js").Name;NdnRegexMatcher=require("./util/ndn-regex-matcher.js").NdnRegexMatcher;
+InterestFilter=function InterestFilter(b,c){"object"===typeof b&&b instanceof InterestFilter?(this.prefix=new Name(b.prefix),this.regexFilter=b.regexFilter,this.regexFilterPattern=b.regexFilterPattern):(this.prefix=new Name(b),c?(this.regexFilter=c,this.regexFilterPattern=InterestFilter.makePattern(c)):this.regexFilterPattern=this.regexFilter=null)};exports.InterestFilter=InterestFilter;
+InterestFilter.prototype.doesMatch=function(a){return a.size()<this.prefix.size()?!1:this.hasRegexFilter()?this.prefix.match(a)?null!=NdnRegexMatcher.match(this.regexFilterPattern,a.getSubName(this.prefix.size())):!1:this.prefix.match(a)};InterestFilter.prototype.getPrefix=function(){return this.prefix};InterestFilter.prototype.hasRegexFilter=function(){return null!=this.regexFilter};InterestFilter.prototype.getRegexFilter=function(){return this.regexFilter};
+InterestFilter.makePattern=function(a){if(0==a.length)return"^$";"^"!=a[0]&&(a="^"+a);"$"!=a[a.length-1]&&(a+="$");return a};var Name=require("./name.js").Name,Blob=require("./util/blob.js").Blob,WireFormat=require("./encoding/wire-format.js").WireFormat,DelegationSet=function DelegationSet(b){this.delegations_="object"===typeof b&&b instanceof DelegationSet?b.delegations_.slice(0):[]};exports.DelegationSet=DelegationSet;DelegationSet.Delegation=function(a,b){this.preference_=a;this.name_=new Name(b)};
+DelegationSet.Delegation.prototype.getPreference=function(){return this.preference_};DelegationSet.Delegation.prototype.getName=function(){return this.name_};DelegationSet.Delegation.prototype.compare=function(a){return this.preference_<a.preference_?-1:this.preference_>a.preference_?1:this.name_.compare(a.name_)};
+DelegationSet.prototype.add=function(a,b){this.remove(b);for(var c=new DelegationSet.Delegation(a,b),d=0;d<this.delegations_.length&&!(0<=this.delegations_[d].compare(c));)++d;this.delegations_.splice(d,0,c)};DelegationSet.prototype.addUnsorted=function(a,b){this.delegations_.push(new DelegationSet.Delegation(a,b))};DelegationSet.prototype.remove=function(a){for(var b=!1,c=this.delegations_.length-1;0<=c;--c)this.delegations_[c].getName().equals(a)&&(b=!0,this.delegations_.splice(c,1));return b};
+DelegationSet.prototype.clear=function(){this.delegations_=[]};DelegationSet.prototype.size=function(){return this.delegations_.length};DelegationSet.prototype.get=function(a){return this.delegations_[a]};DelegationSet.prototype.find=function(a){for(var b=0;b<this.delegations_.length;++b)if(this.delegations_[b].getName().equals(a))return b;return-1};DelegationSet.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeDelegationSet(this)};
+DelegationSet.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeDelegationSet(this,a.buf(),!1):b.decodeDelegationSet(this,a,!0)};DelegationSet=require("./delegation-set.js").DelegationSet;ContentType=require("./meta-info.js").ContentType;WireFormat=require("./encoding/wire-format.js").WireFormat;Data=require("./data.js").Data;
+Link=function(a){this.delegations_=new DelegationSet;if(a instanceof Data){if(Data.call(this,a),!this.getContent().isNull())try{this.delegations_.wireDecode(this.getContent()),this.getMetaInfo().setType(ContentType.LINK)}catch(b){this.delegations_.clear()}}else void 0!=a?Data.call(this,a):Data.call(this),this.getMetaInfo().setType(ContentType.LINK)};Link.prototype=new Data;Link.prototype.name="Link";exports.Link=Link;
+Link.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();Data.prototype.wireDecode.call(this,a,b);if(this.getMetaInfo().getType()!=ContentType.LINK)throw Error("Link.wireDecode: MetaInfo ContentType is not LINK.");this.delegations_.wireDecode(this.getContent())};Link.prototype.addDelegation=function(a,b,c){c=c||WireFormat.getDefaultWireFormat();this.delegations_.add(a,b);this.encodeContent(c);return this};
+Link.prototype.removeDelegation=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=this.delegations_.remove(a);c&&this.encodeContent(b);return c};Link.prototype.getDelegations=function(){return this.delegations_};Link.prototype.encodeContent=function(a){this.setContent(this.delegations_.wireEncode(a));this.getMetaInfo().setType(ContentType.LINK)};var NetworkNack=function NetworkNack(){this.reason_=NetworkNack.Reason.NONE;this.otherReasonCode_=-1};exports.NetworkNack=NetworkNack;
+NetworkNack.Reason={NONE:0,CONGESTION:50,DUPLICATE:100,NO_ROUTE:150,OTHER_CODE:32767};NetworkNack.prototype.getReason=function(){return this.reason_};NetworkNack.prototype.getOtherReasonCode=function(){return this.otherReasonCode_};NetworkNack.prototype.setReason=function(a){this.reason_=a};NetworkNack.prototype.setOtherReasonCode=function(a){if(0>a)throw Error("NetworkNack other reason code must be non-negative");this.otherReasonCode_=a};
+NetworkNack.getFirstHeader=function(a){for(var b=0;b<a.countHeaderFields();++b){var c=a.getHeaderField(b);if(c instanceof NetworkNack)return c}return null};
+var Crypto=require("../crypto.js"),Blob=require("../util/blob.js").Blob,Name=require("../name.js").Name,ForwardingFlags=require("../forwarding-flags").ForwardingFlags,Tlv=require("./tlv/tlv.js").Tlv,TlvEncoder=require("./tlv/tlv-encoder.js").TlvEncoder,TlvDecoder=require("./tlv/tlv-decoder.js").TlvDecoder,WireFormat=require("./wire-format.js").WireFormat,Exclude=require("../exclude.js").Exclude,ContentType=require("../meta-info.js").ContentType,KeyLocatorType=require("../key-locator.js").KeyLocatorType,
+Sha256WithRsaSignature=require("../sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("../sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,GenericSignature=require("../generic-signature.js").GenericSignature,HmacWithSha256Signature=require("../hmac-with-sha256-signature.js").HmacWithSha256Signature,DigestSha256Signature=require("../digest-sha256-signature.js").DigestSha256Signature,ControlParameters=require("../control-parameters.js").ControlParameters,
+ForwardingFlags=require("../forwarding-flags.js").ForwardingFlags,NetworkNack=require("../network-nack.js").NetworkNack,IncomingFaceId=require("../lp/incoming-face-id.js").IncomingFaceId,DecodingException=require("./decoding-exception.js").DecodingException,Tlv0_2WireFormat=function(){WireFormat.call(this)};Tlv0_2WireFormat.prototype=new WireFormat;Tlv0_2WireFormat.prototype.name="Tlv0_2WireFormat";exports.Tlv0_2WireFormat=Tlv0_2WireFormat;Tlv0_2WireFormat.instance=null;
+Tlv0_2WireFormat.prototype.encodeName=function(a){var b=new TlvEncoder;Tlv0_2WireFormat.encodeName(a,b);return new Blob(b.getOutput(),!1)};Tlv0_2WireFormat.prototype.decodeName=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);Tlv0_2WireFormat.decodeName(a,b,c)};
+Tlv0_2WireFormat.prototype.encodeInterest=function(a){var b=new TlvEncoder(256),c=b.getLength();b.writeOptionalNonNegativeIntegerTlv(Tlv.SelectedDelegation,a.getSelectedDelegationIndex());var d=a.getLinkWireEncoding(this);d.isNull()||b.writeBuffer(d.buf());b.writeOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime,a.getInterestLifetimeMilliseconds());if(a.getNonce().isNull()||0==a.getNonce().size())b.writeBlobTlv(Tlv.Nonce,Crypto.randomBytes(4));else if(4>a.getNonce().size()){d=Buffer(4);a.getNonce().buf().copy(d);
+for(var e=a.getNonce().size();4>e;++e)d[e]=Crypto.randomBytes(1)[0];b.writeBlobTlv(Tlv.Nonce,d)}else 4==a.getNonce().size()?b.writeBlobTlv(Tlv.Nonce,a.getNonce().buf()):b.writeBlobTlv(Tlv.Nonce,a.getNonce().buf().slice(0,4));Tlv0_2WireFormat.encodeSelectors(a,b);d=Tlv0_2WireFormat.encodeName(a.getName(),b);a=b.getLength()-d.signedPortionBeginOffset;d=b.getLength()-d.signedPortionEndOffset;b.writeTypeAndLength(Tlv.Interest,b.getLength()-c);c=b.getLength()-a;a=b.getLength()-d;return{encoding:new Blob(b.getOutput(),
+!1),signedPortionBeginOffset:c,signedPortionEndOffset:a}};
+Tlv0_2WireFormat.prototype.decodeInterest=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);var d=b.readNestedTlvsStart(Tlv.Interest),e=Tlv0_2WireFormat.decodeName(a.getName(),b,c);b.peekType(Tlv.Selectors,d)&&Tlv0_2WireFormat.decodeSelectors(a,b,c);var f=b.readBlobTlv(Tlv.Nonce);a.setInterestLifetimeMilliseconds(b.readOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime,d));if(b.peekType(Tlv.Data,d)){var g=b.getOffset(),h=b.readNestedTlvsStart(Tlv.Data);b.seek(h);a.setLinkWireEncoding(new Blob(b.getSlice(g,
+h),c),this)}else a.unsetLink();a.setSelectedDelegationIndex(b.readOptionalNonNegativeIntegerTlv(Tlv.SelectedDelegation,d));if(null!=a.getSelectedDelegationIndex()&&0<=a.getSelectedDelegationIndex()&&!a.hasLink())throw Error("Interest has a selected delegation, but no link object");a.setNonce(new Blob(f,c));b.finishNestedTlvs(d);return e};
+Tlv0_2WireFormat.prototype.encodeData=function(a){var b=new TlvEncoder(1500),c=b.getLength();b.writeBlobTlv(Tlv.SignatureValue,a.getSignature().getSignature().buf());var d=b.getLength();Tlv0_2WireFormat.encodeSignatureInfo_(a.getSignature(),b);b.writeBlobTlv(Tlv.Content,a.getContent().buf());Tlv0_2WireFormat.encodeMetaInfo(a.getMetaInfo(),b);Tlv0_2WireFormat.encodeName(a.getName(),b);a=b.getLength();b.writeTypeAndLength(Tlv.Data,b.getLength()-c);c=b.getLength()-a;d=b.getLength()-d;return{encoding:new Blob(b.getOutput(),
+!1),signedPortionBeginOffset:c,signedPortionEndOffset:d}};
+Tlv0_2WireFormat.prototype.decodeData=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);var d=b.readNestedTlvsStart(Tlv.Data),e=b.getOffset();Tlv0_2WireFormat.decodeName(a.getName(),b,c);Tlv0_2WireFormat.decodeMetaInfo(a.getMetaInfo(),b,c);a.setContent(new Blob(b.readBlobTlv(Tlv.Content),c));Tlv0_2WireFormat.decodeSignatureInfo(a,b,c);var f=b.getOffset();a.getSignature().setSignature(new Blob(b.readBlobTlv(Tlv.SignatureValue),c));b.finishNestedTlvs(d);return{signedPortionBeginOffset:e,signedPortionEndOffset:f}};
+Tlv0_2WireFormat.prototype.encodeControlParameters=function(a){var b=new TlvEncoder(256);Tlv0_2WireFormat.encodeControlParameters(a,b);return new Blob(b.getOutput(),!1)};Tlv0_2WireFormat.prototype.decodeControlParameters=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);Tlv0_2WireFormat.decodeControlParameters(a,b,c)};
+Tlv0_2WireFormat.prototype.encodeControlResponse=function(a){var b=new TlvEncoder(256),c=b.getLength();null!=a.getBodyAsControlParameters()&&Tlv0_2WireFormat.encodeControlParameters(a.getBodyAsControlParameters(),b);b.writeBlobTlv(Tlv.NfdCommand_StatusText,(new Blob(a.getStatusText())).buf());b.writeNonNegativeIntegerTlv(Tlv.NfdCommand_StatusCode,a.getStatusCode());b.writeTypeAndLength(Tlv.NfdCommand_ControlResponse,b.getLength()-c);return new Blob(b.getOutput(),!1)};
+Tlv0_2WireFormat.prototype.decodeControlResponse=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);var d=b.readNestedTlvsStart(Tlv.NfdCommand_ControlResponse);a.setStatusCode(b.readNonNegativeIntegerTlv(Tlv.NfdCommand_StatusCode));var e=new Blob(b.readBlobTlv(Tlv.NfdCommand_StatusText),!1);a.setStatusText(e.toString());b.peekType(Tlv.ControlParameters_ControlParameters,d)?(a.setBodyAsControlParameters(new ControlParameters),Tlv0_2WireFormat.decodeControlParameters(a.getBodyAsControlParameters(),
+b,c)):a.setBodyAsControlParameters(null);b.finishNestedTlvs(d)};Tlv0_2WireFormat.prototype.encodeSignatureInfo=function(a){var b=new TlvEncoder(256);Tlv0_2WireFormat.encodeSignatureInfo_(a,b);return new Blob(b.getOutput(),!1)};Tlv0_2WireFormat.SignatureHolder=function(){};Tlv0_2WireFormat.SignatureHolder.prototype.setSignature=function(a){this.signature=a};Tlv0_2WireFormat.SignatureHolder.prototype.getSignature=function(){return this.signature};
+Tlv0_2WireFormat.prototype.decodeSignatureInfoAndValue=function(a,b,c){null==c&&(c=!0);var d=new Tlv0_2WireFormat.SignatureHolder;a=new TlvDecoder(a);Tlv0_2WireFormat.decodeSignatureInfo(d,a,c);a=new TlvDecoder(b);d.getSignature().setSignature(new Blob(a.readBlobTlv(Tlv.SignatureValue),c));return d.getSignature()};Tlv0_2WireFormat.prototype.encodeSignatureValue=function(a){var b=new TlvEncoder(256);b.writeBlobTlv(Tlv.SignatureValue,a.getSignature().buf());return new Blob(b.getOutput(),!1)};
+Tlv0_2WireFormat.prototype.decodeLpPacket=function(a,b,c){null==c&&(c=!0);a.clear();for(var d=new TlvDecoder(b),e=d.readNestedTlvsStart(Tlv.LpPacket_LpPacket);d.getOffset()<e;){var f=d.readVarNumber(),g=d.readVarNumber(),h=d.getOffset()+g;if(h>b.length)throw new DecodingException(Error("TLV length exceeds the buffer length"));if(f==Tlv.LpPacket_Fragment){a.setFragmentWireEncoding(new Blob(d.getSlice(d.getOffset(),h),c));d.seek(h);break}else if(f==Tlv.LpPacket_Nack)g=new NetworkNack,f=d.readOptionalNonNegativeIntegerTlv(Tlv.LpPacket_NackReason,
+h),0>f||f==NetworkNack.Reason.NONE?g.setReason(NetworkNack.Reason.NONE):f==NetworkNack.Reason.CONGESTION||f==NetworkNack.Reason.DUPLICATE||f==NetworkNack.Reason.NO_ROUTE?g.setReason(f):(g.setReason(NetworkNack.Reason.OTHER_CODE),g.setOtherReasonCode(f)),a.addHeaderField(g);else if(f==Tlv.LpPacket_IncomingFaceId)f=new IncomingFaceId,f.setFaceId(d.readNonNegativeInteger(g)),a.addHeaderField(f);else{if(!(f>=Tlv.LpPacket_IGNORE_MIN&&f<=Tlv.LpPacket_IGNORE_MAX&&1===(f&1)))throw new DecodingException(Error("Did not get the expected TLV type"));
+d.seek(h)}d.finishNestedTlvs(h)}d.finishNestedTlvs(e)};Tlv0_2WireFormat.prototype.encodeDelegationSet=function(a){for(var b=new TlvEncoder(256),c=a.size()-1;0<=c;--c){var d=b.getLength();Tlv0_2WireFormat.encodeName(a.get(c).getName(),b);b.writeNonNegativeIntegerTlv(Tlv.Link_Preference,a.get(c).getPreference());b.writeTypeAndLength(Tlv.Link_Delegation,b.getLength()-d)}return new Blob(b.getOutput(),!1)};
+Tlv0_2WireFormat.prototype.decodeDelegationSet=function(a,b,c){null==c&&(c=!0);var d=new TlvDecoder(b);b=b.length;for(a.clear();d.getOffset()<b;){d.readTypeAndLength(Tlv.Link_Delegation);var e=d.readNonNegativeIntegerTlv(Tlv.Link_Preference),f=new Name;Tlv0_2WireFormat.decodeName(f,d,c);a.addUnsorted(e,f)}};
+Tlv0_2WireFormat.prototype.encodeEncryptedContent=function(a){var b=new TlvEncoder(256),c=b.getLength();b.writeBlobTlv(Tlv.Encrypt_EncryptedPayload,a.getPayload().buf());b.writeOptionalBlobTlv(Tlv.Encrypt_InitialVector,a.getInitialVector().buf());b.writeNonNegativeIntegerTlv(Tlv.Encrypt_EncryptionAlgorithm,a.getAlgorithmType());Tlv0_2WireFormat.encodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b);b.writeTypeAndLength(Tlv.Encrypt_EncryptedContent,b.getLength()-c);return new Blob(b.getOutput(),!1)};
+Tlv0_2WireFormat.prototype.decodeEncryptedContent=function(a,b,c){null==c&&(c=!0);b=new TlvDecoder(b);var d=b.readNestedTlvsStart(Tlv.Encrypt_EncryptedContent);Tlv0_2WireFormat.decodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b,c);a.setAlgorithmType(b.readNonNegativeIntegerTlv(Tlv.Encrypt_EncryptionAlgorithm));a.setInitialVector(new Blob(b.readOptionalBlobTlv(Tlv.Encrypt_InitialVector,d),c));a.setPayload(new Blob(b.readBlobTlv(Tlv.Encrypt_EncryptedPayload),c));b.finishNestedTlvs(d)};
+Tlv0_2WireFormat.get=function(){null===Tlv0_2WireFormat.instance&&(Tlv0_2WireFormat.instance=new Tlv0_2WireFormat);return Tlv0_2WireFormat.instance};Tlv0_2WireFormat.encodeNameComponent=function(a,b){var c=a.isImplicitSha256Digest()?Tlv.ImplicitSha256DigestComponent:Tlv.NameComponent;b.writeBlobTlv(c,a.getValue().buf())};
+Tlv0_2WireFormat.decodeNameComponent=function(a,b){null==b&&(b=!0);var c=a.getOffset(),d=a.readVarNumber();a.seek(c);c=new Blob(a.readBlobTlv(d),b);return d===Tlv.ImplicitSha256DigestComponent?Name.Component.fromImplicitSha256Digest(c):new Name.Component(c)};
+Tlv0_2WireFormat.encodeName=function(a,b){for(var c=b.getLength(),d,e=a.size()-1;0<=e;--e)Tlv0_2WireFormat.encodeNameComponent(a.get(e),b),e==a.size()-1&&(d=b.getLength());e=b.getLength();b.writeTypeAndLength(Tlv.Name,b.getLength()-c);c=b.getLength()-e;d=0==a.size()?c:b.getLength()-d;return{signedPortionBeginOffset:c,signedPortionEndOffset:d}};
+Tlv0_2WireFormat.decodeName=function(a,b,c){a.clear();for(var d=b.readNestedTlvsStart(Tlv.Name),e=b.getOffset(),f=e;b.getOffset()<d;)f=b.getOffset(),a.append(Tlv0_2WireFormat.decodeNameComponent(b,c));b.finishNestedTlvs(d);return{signedPortionBeginOffset:e,signedPortionEndOffset:f}};
+Tlv0_2WireFormat.encodeSelectors=function(a,b){var c=b.getLength();a.getMustBeFresh()&&b.writeTypeAndLength(Tlv.MustBeFresh,0);b.writeOptionalNonNegativeIntegerTlv(Tlv.ChildSelector,a.getChildSelector());0<a.getExclude().size()&&Tlv0_2WireFormat.encodeExclude(a.getExclude(),b);null!=a.getKeyLocator().getType()&&Tlv0_2WireFormat.encodeKeyLocator(Tlv.PublisherPublicKeyLocator,a.getKeyLocator(),b);b.writeOptionalNonNegativeIntegerTlv(Tlv.MaxSuffixComponents,a.getMaxSuffixComponents());b.writeOptionalNonNegativeIntegerTlv(Tlv.MinSuffixComponents,
+a.getMinSuffixComponents());b.getLength()!=c&&b.writeTypeAndLength(Tlv.Selectors,b.getLength()-c)};
+Tlv0_2WireFormat.decodeSelectors=function(a,b,c){null==c&&(c=!0);var d=b.readNestedTlvsStart(Tlv.Selectors);a.setMinSuffixComponents(b.readOptionalNonNegativeIntegerTlv(Tlv.MinSuffixComponents,d));a.setMaxSuffixComponents(b.readOptionalNonNegativeIntegerTlv(Tlv.MaxSuffixComponents,d));b.peekType(Tlv.PublisherPublicKeyLocator,d)?Tlv0_2WireFormat.decodeKeyLocator(Tlv.PublisherPublicKeyLocator,a.getKeyLocator(),b,c):a.getKeyLocator().clear();b.peekType(Tlv.Exclude,d)?Tlv0_2WireFormat.decodeExclude(a.getExclude(),
+b,c):a.getExclude().clear();a.setChildSelector(b.readOptionalNonNegativeIntegerTlv(Tlv.ChildSelector,d));a.setMustBeFresh(b.readBooleanTlv(Tlv.MustBeFresh,d));b.finishNestedTlvs(d)};Tlv0_2WireFormat.encodeExclude=function(a,b){for(var c=b.getLength(),d=a.size()-1;0<=d;--d){var e=a.get(d);e==Exclude.ANY?b.writeTypeAndLength(Tlv.Any,0):Tlv0_2WireFormat.encodeNameComponent(e,b)}b.writeTypeAndLength(Tlv.Exclude,b.getLength()-c)};
+Tlv0_2WireFormat.decodeExclude=function(a,b,c){null==c&&(c=!0);var d=b.readNestedTlvsStart(Tlv.Exclude);for(a.clear();b.getOffset()<d;)b.peekType(Tlv.Any,d)?(b.readBooleanTlv(Tlv.Any,d),a.appendAny()):a.appendComponent(Tlv0_2WireFormat.decodeNameComponent(b,c));b.finishNestedTlvs(d)};
+Tlv0_2WireFormat.encodeKeyLocator=function(a,b,c){var d=c.getLength();if(null!=b.getType())if(b.getType()==KeyLocatorType.KEYNAME)Tlv0_2WireFormat.encodeName(b.getKeyName(),c);else if(b.getType()==KeyLocatorType.KEY_LOCATOR_DIGEST&&0<b.getKeyData().size())c.writeBlobTlv(Tlv.KeyLocatorDigest,b.getKeyData().buf());else throw Error("Unrecognized KeyLocatorType "+b.getType());c.writeTypeAndLength(a,c.getLength()-d)};
+Tlv0_2WireFormat.decodeKeyLocator=function(a,b,c,d){null==d&&(d=!0);a=c.readNestedTlvsStart(a);b.clear();if(c.getOffset()!=a){if(c.peekType(Tlv.Name,a))b.setType(KeyLocatorType.KEYNAME),Tlv0_2WireFormat.decodeName(b.getKeyName(),c,d);else if(c.peekType(Tlv.KeyLocatorDigest,a))b.setType(KeyLocatorType.KEY_LOCATOR_DIGEST),b.setKeyData(new Blob(c.readBlobTlv(Tlv.KeyLocatorDigest),d));else throw new DecodingException(Error("decodeKeyLocator: Unrecognized key locator type"));c.finishNestedTlvs(a)}};
+Tlv0_2WireFormat.encodeSignatureInfo_=function(a,b){if(a instanceof GenericSignature){var c=a.getSignatureInfoEncoding();try{var d=new TlvDecoder(c.buf()),e=d.readNestedTlvsStart(Tlv.SignatureInfo);d.readNonNegativeIntegerTlv(Tlv.SignatureType);d.finishNestedTlvs(e)}catch(f){throw Error("The GenericSignature encoding is not a valid NDN-TLV SignatureInfo: "+f.message);}b.writeBuffer(c.buf())}else{c=b.getLength();if(a instanceof Sha256WithRsaSignature)Tlv0_2WireFormat.encodeKeyLocator(Tlv.KeyLocator,
+a.getKeyLocator(),b),b.writeNonNegativeIntegerTlv(Tlv.SignatureType,Tlv.SignatureType_SignatureSha256WithRsa);else if(a instanceof Sha256WithEcdsaSignature)Tlv0_2WireFormat.encodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b),b.writeNonNegativeIntegerTlv(Tlv.SignatureType,Tlv.SignatureType_SignatureSha256WithEcdsa);else if(a instanceof HmacWithSha256Signature)Tlv0_2WireFormat.encodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b),b.writeNonNegativeIntegerTlv(Tlv.SignatureType,Tlv.SignatureType_SignatureHmacWithSha256);
+else if(a instanceof DigestSha256Signature)b.writeNonNegativeIntegerTlv(Tlv.SignatureType,Tlv.SignatureType_DigestSha256);else throw Error("encodeSignatureInfo: Unrecognized Signature object type");b.writeTypeAndLength(Tlv.SignatureInfo,b.getLength()-c)}};
+Tlv0_2WireFormat.decodeSignatureInfo=function(a,b,c){null==c&&(c=!0);var d=b.getOffset(),e=b.readNestedTlvsStart(Tlv.SignatureInfo),f=b.readNonNegativeIntegerTlv(Tlv.SignatureType);f==Tlv.SignatureType_SignatureSha256WithRsa?(a.setSignature(new Sha256WithRsaSignature),a=a.getSignature(),Tlv0_2WireFormat.decodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b,c)):f==Tlv.SignatureType_SignatureSha256WithEcdsa?(a.setSignature(new Sha256WithEcdsaSignature),a=a.getSignature(),Tlv0_2WireFormat.decodeKeyLocator(Tlv.KeyLocator,
+a.getKeyLocator(),b,c)):f==Tlv.SignatureType_SignatureHmacWithSha256?(a.setSignature(new HmacWithSha256Signature),a=a.getSignature(),Tlv0_2WireFormat.decodeKeyLocator(Tlv.KeyLocator,a.getKeyLocator(),b,c)):f==Tlv.SignatureType_DigestSha256?a.setSignature(new DigestSha256Signature):(a.setSignature(new GenericSignature),a=a.getSignature(),a.setSignatureInfoEncoding(new Blob(b.getSlice(d,e),c),f));b.finishNestedTlvs(e)};
+Tlv0_2WireFormat.encodeMetaInfo=function(a,b){var c=b.getLength(),d=a.getFinalBlockId().getValue().buf();null!=d&&0<d.length&&(d=b.getLength(),Tlv0_2WireFormat.encodeNameComponent(a.getFinalBlockId(),b),b.writeTypeAndLength(Tlv.FinalBlockId,b.getLength()-d));b.writeOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod,a.getFreshnessPeriod());if(a.getType()!=ContentType.BLOB)if(a.getType()==ContentType.LINK||a.getType()==ContentType.KEY||a.getType()==ContentType.NACK)b.writeNonNegativeIntegerTlv(Tlv.ContentType,
+a.getType());else if(a.getType()==ContentType.OTHER_CODE)b.writeNonNegativeIntegerTlv(Tlv.ContentType,a.getOtherTypeCode());else throw Error("unrecognized TLV ContentType");b.writeTypeAndLength(Tlv.MetaInfo,b.getLength()-c)};
+Tlv0_2WireFormat.decodeMetaInfo=function(a,b,c){null==c&&(c=!0);var d=b.readNestedTlvsStart(Tlv.MetaInfo),e=b.readOptionalNonNegativeIntegerTlv(Tlv.ContentType,d);null==e||0>e||e===ContentType.BLOB?a.setType(ContentType.BLOB):e===ContentType.LINK||e===ContentType.KEY||e===ContentType.NACK?a.setType(e):(a.setType(ContentType.OTHER_CODE),a.setOtherTypeCode(e));a.setFreshnessPeriod(b.readOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod,d));b.peekType(Tlv.FinalBlockId,d)?(e=b.readNestedTlvsStart(Tlv.FinalBlockId),
+a.setFinalBlockId(Tlv0_2WireFormat.decodeNameComponent(b,c)),b.finishNestedTlvs(e)):a.setFinalBlockId(null);b.finishNestedTlvs(d)};
+Tlv0_2WireFormat.encodeControlParameters=function(a,b){var c=b.getLength();b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_ExpirationPeriod,a.getExpirationPeriod());if(0<a.getStrategy().size()){var d=b.getLength();Tlv0_2WireFormat.encodeName(a.getStrategy(),b);b.writeTypeAndLength(Tlv.ControlParameters_Strategy,b.getLength()-d)}d=a.getForwardingFlags().getNfdForwardingFlags();d!=(new ForwardingFlags).getNfdForwardingFlags()&&b.writeNonNegativeIntegerTlv(Tlv.ControlParameters_Flags,d);b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Cost,
+a.getCost());b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin,a.getOrigin());b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_LocalControlFeature,a.getLocalControlFeature());0!=a.getUri().length&&b.writeBlobTlv(Tlv.ControlParameters_Uri,(new Blob(a.getUri())).buf());b.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId,a.getFaceId());null!=a.getName()&&Tlv0_2WireFormat.encodeName(a.getName(),b);b.writeTypeAndLength(Tlv.ControlParameters_ControlParameters,b.getLength()-
+c)};
+Tlv0_2WireFormat.decodeControlParameters=function(a,b,c){null==c&&(c=!0);a.clear();var d=b.readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);if(b.peekType(Tlv.Name,d)){var e=new Name;Tlv0_2WireFormat.decodeName(e,b,c);a.setName(e)}a.setFaceId(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId,d));b.peekType(Tlv.ControlParameters_Uri,d)&&(e=new Blob(b.readOptionalBlobTlv(Tlv.ControlParameters_Uri,d),!1),a.setUri(e.toString()));a.setLocalControlFeature(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_LocalControlFeature,d));
+a.setOrigin(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin,d));a.setCost(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Cost,d));b.peekType(Tlv.ControlParameters_Flags,d)&&(e=new ForwardingFlags,e.setNfdForwardingFlags(b.readNonNegativeIntegerTlv(Tlv.ControlParameters_Flags,d)),a.setForwardingFlags(e));b.peekType(Tlv.ControlParameters_Strategy,d)&&(e=b.readNestedTlvsStart(Tlv.ControlParameters_Strategy),Tlv0_2WireFormat.decodeName(a.getStrategy(),b,c),b.finishNestedTlvs(e));
+a.setExpirationPeriod(b.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_ExpirationPeriod,d));b.finishNestedTlvs(d)};var Tlv0_2WireFormat=require("./tlv-0_2-wire-format.js").Tlv0_2WireFormat,Tlv0_1_1WireFormat=function(){Tlv0_2WireFormat.call(this)};Tlv0_1_1WireFormat.prototype=new Tlv0_2WireFormat;Tlv0_1_1WireFormat.prototype.name="Tlv0_1_1WireFormat";exports.Tlv0_1_1WireFormat=Tlv0_1_1WireFormat;Tlv0_1_1WireFormat.instance=null;
+Tlv0_1_1WireFormat.get=function(){null===Tlv0_1_1WireFormat.instance&&(Tlv0_1_1WireFormat.instance=new Tlv0_1_1WireFormat);return Tlv0_1_1WireFormat.instance};var WireFormat=require("./wire-format.js").WireFormat,Tlv0_1_1WireFormat=require("./tlv-0_1_1-wire-format.js").Tlv0_1_1WireFormat,Tlv0_1WireFormat=function(){Tlv0_1_1WireFormat.call(this)};Tlv0_1WireFormat.prototype=new Tlv0_1_1WireFormat;Tlv0_1WireFormat.prototype.name="Tlv0_1WireFormat";exports.Tlv0_1WireFormat=Tlv0_1WireFormat;
+Tlv0_1WireFormat.instance=null;Tlv0_1WireFormat.get=function(){null===Tlv0_1WireFormat.instance&&(Tlv0_1WireFormat.instance=new Tlv0_1WireFormat);return Tlv0_1WireFormat.instance};WireFormat=require("./wire-format.js").WireFormat;Tlv0_2WireFormat=require("./tlv-0_2-wire-format.js").Tlv0_2WireFormat;TlvWireFormat=function(){Tlv0_2WireFormat.call(this)};TlvWireFormat.prototype=new Tlv0_2WireFormat;TlvWireFormat.prototype.name="TlvWireFormat";exports.TlvWireFormat=TlvWireFormat;
+TlvWireFormat.instance=null;TlvWireFormat.get=function(){null===TlvWireFormat.instance&&(TlvWireFormat.instance=new TlvWireFormat);return TlvWireFormat.instance};WireFormat.setDefaultWireFormat(TlvWireFormat.get());
+var DataUtils=require("./data-utils.js").DataUtils,KeyLocatorType=require("../key-locator.js").KeyLocatorType,Interest=require("../interest.js").Interest,Data=require("../data.js").Data,Sha256WithRsaSignature=require("../sha256-with-rsa-signature.js").Sha256WithRsaSignature,Sha256WithEcdsaSignature=require("../sha256-with-ecdsa-signature.js").Sha256WithEcdsaSignature,HmacWithSha256Signature=require("../hmac-with-sha256-signature.js").HmacWithSha256Signature,DigestSha256Signature=require("../digest-sha256-signature.js").DigestSha256Signature,
+ContentType=require("../meta-info.js").ContentType,WireFormat=require("./wire-format.js").WireFormat,EncodingUtils=function(){};exports.EncodingUtils=EncodingUtils;EncodingUtils.encodeToHexInterest=function(a,b){b=b||WireFormat.getDefaultWireFormat();return DataUtils.toHex(a.wireEncode(b).buf())};EncodingUtils.encodeToHexData=function(a,b){b=b||WireFormat.getDefaultWireFormat();return DataUtils.toHex(a.wireEncode(b).buf())};
+EncodingUtils.decodeHexInterest=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=new Interest;c.wireDecode(DataUtils.toNumbers(a),b);return c};EncodingUtils.decodeHexData=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=new Data;c.wireDecode(DataUtils.toNumbers(a),b);return c};
+EncodingUtils.decodeSubjectPublicKeyInfo=function(a){a=DataUtils.toHex(a).toLowerCase();a=_x509_getPublicKeyHexArrayFromCertHex(a,_x509_getSubjectPublicKeyPosFromCertHex(a,0));var b=new RSAKey;b.setPublic(a[0],a[1]);return b};
+EncodingUtils.dataToHtml=function(a){function b(a){a=a.replace(/&/g,"&amp;");a=a.replace(/</g,"&lt;");c+=a;c+="<br/>"}if(-1==a)return"NO CONTENT FOUND";if(-2==a)return"CONTENT NAME IS EMPTY";var c="";b("name: "+a.getName().toUri());0<a.getContent().size()?(b("content (raw): "+a.getContent().buf().toString("binary")),b("content (hex): "+a.getContent().toHex())):b("content: <empty>");a.getMetaInfo().getType()!=ContentType.BLOB&&(a.getMetaInfo().getType()==ContentType.KEY?b("metaInfo.type: KEY"):a.getMetaInfo().getType()==
+ContentType.LINK?b("metaInfo.type: LINK"):a.getMetaInfo().getType()==ContentType.NACK?b("metaInfo.type: NACK"):a.getMetaInfo().getType()==ContentType.OTHER_CODE&&b("metaInfo.type: other code "+a.getMetaInfo().getOtherTypeCode()));b("metaInfo.freshnessPeriod (milliseconds): "+(0<=a.getMetaInfo().getFreshnessPeriod()?""+a.getMetaInfo().getFreshnessPeriod():"<none>"));b("metaInfo.finalBlockId: "+(0<a.getMetaInfo().getFinalBlockId().getValue().size()?a.getMetaInfo().getFinalBlockId().getValue().toHex():
+"<none>"));var d=null,e=a.getSignature();e instanceof Sha256WithRsaSignature?(e=a.getSignature(),b("Sha256WithRsa signature.signature: "+(0<e.getSignature().size()?e.getSignature().toHex():"<none>")),d=e.getKeyLocator()):e instanceof Sha256WithEcdsaSignature?(e=a.getSignature(),b("Sha256WithEcdsa signature.signature: "+(0<e.getSignature().size()?e.getSignature().toHex():"<none>")),d=e.getKeyLocator()):e instanceof HmacWithSha256Signature?(e=a.getSignature(),b("HmacWithSha256 signature.signature: "+
+(0<e.getSignature().size()?e.getSignature().toHex():"<none>")),d=e.getKeyLocator()):e instanceof DigestSha256Signature&&(e=a.getSignature(),b("DigestSha256 signature.signature: "+(0<e.getSignature().size()?e.getSignature().toHex():"<none>")));null!==d&&(null==d.getType()?b("signature.keyLocator: <none>"):d.getType()==KeyLocatorType.KEY_LOCATOR_DIGEST?b("signature.keyLocator: KeyLocatorDigest: "+d.getKeyData().toHex()):d.getType()==KeyLocatorType.KEYNAME?b("signature.keyLocator: KeyName: "+d.getKeyName().toUri()):
+b("signature.keyLocator: <unrecognized ndn_KeyLocatorType>"));return c};var encodeToHexInterest=function(a){return EncodingUtils.encodeToHexInterest(a)},decodeHexInterest=function(a){return EncodingUtils.decodeHexInterest(a)},decodeSubjectPublicKeyInfo=function(a){return EncodingUtils.decodeSubjectPublicKeyInfo(a)};function encodeToBinaryInterest(a){return a.wireEncode().buf()}
+var Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,DecryptKey=require("../decrypt-key.js").DecryptKey,EncryptKey=require("../encrypt-key.js").EncryptKey,EncryptAlgorithmType=require("./encrypt-params.js").EncryptAlgorithmType,UseSubtleCrypto=require("../../use-subtle-crypto-node.js").UseSubtleCrypto,SyncPromise=require("../../util/sync-promise.js").SyncPromise,AesAlgorithm=function(){};exports.AesAlgorithm=AesAlgorithm;
+AesAlgorithm.generateKey=function(a){a=Crypto.randomBytes(a.getKeySize()/8);return new DecryptKey(new Blob(a,!1))};AesAlgorithm.deriveEncryptKey=function(a){return new EncryptKey(a)};
+AesAlgorithm.decryptPromise=function(a,b,c,d){if(UseSubtleCrypto()&&!d&&c.getAlgorithmType()!=EncryptAlgorithmType.AesEcb)return c.getAlgorithmType()==EncryptAlgorithmType.AesCbc?crypto.subtle.importKey("raw",a.buf(),{name:"AES-CBC"},!1,["encrypt","decrypt"]).then(function(a){return crypto.subtle.decrypt({name:"AES-CBC",iv:c.getInitialVector().buf()},a,b.buf())}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!1))}):Promise.reject(Error("unsupported encryption mode"));if(c.getAlgorithmType()==
+EncryptAlgorithmType.AesEcb)try{var e=Crypto.createDecipheriv("aes-128-ecb",a.buf(),"");return SyncPromise.resolve(new Blob(Buffer.concat([e.update(b.buf()),e["final"]()]),!1))}catch(f){return SyncPromise.reject(f)}else if(c.getAlgorithmType()==EncryptAlgorithmType.AesCbc)try{return e=Crypto.createDecipheriv("aes-128-cbc",a.buf(),c.getInitialVector().buf()),SyncPromise.resolve(new Blob(Buffer.concat([e.update(b.buf()),e["final"]()]),!1))}catch(g){return SyncPromise.reject(g)}else return SyncPromise.reject(Error("unsupported encryption mode"))};
+AesAlgorithm.decrypt=function(a,b,c){return SyncPromise.getValue(this.decryptPromise(a,b,c,!0))};
+AesAlgorithm.encryptPromise=function(a,b,c,d){return c.getAlgorithmType()==EncryptAlgorithmType.AesCbc&&c.getInitialVector().size()!=AesAlgorithm.BLOCK_SIZE?SyncPromise.reject(Error("incorrect initial vector size")):UseSubtleCrypto()&&!d&&c.getAlgorithmType()!=EncryptAlgorithmType.AesEcb?c.getAlgorithmType()==EncryptAlgorithmType.AesCbc?crypto.subtle.importKey("raw",a.buf(),{name:"AES-CBC"},!1,["encrypt","decrypt"]).then(function(a){return crypto.subtle.encrypt({name:"AES-CBC",iv:c.getInitialVector().buf()},
+a,b.buf())}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!1))}):Promise.reject(Error("unsupported encryption mode")):c.getAlgorithmType()==EncryptAlgorithmType.AesEcb?(a=Crypto.createCipheriv("aes-128-ecb",a.buf(),""),SyncPromise.resolve(new Blob(Buffer.concat([a.update(b.buf()),a["final"]()]),!1))):c.getAlgorithmType()==EncryptAlgorithmType.AesCbc?(a=Crypto.createCipheriv("aes-128-cbc",a.buf(),c.getInitialVector().buf()),SyncPromise.resolve(new Blob(Buffer.concat([a.update(b.buf()),
+a["final"]()]),!1))):SyncPromise.reject(Error("unsupported encryption mode"))};AesAlgorithm.encrypt=function(a,b,c){return SyncPromise.getValue(this.encryptPromise(a,b,c,!0))};AesAlgorithm.BLOCK_SIZE=16;Crypto=require("../../crypto.js");Blob=require("../../util/blob.js").Blob;EncryptAlgorithmType=function(){};exports.EncryptAlgorithmType=EncryptAlgorithmType;EncryptAlgorithmType.AesEcb=0;EncryptAlgorithmType.AesCbc=1;EncryptAlgorithmType.RsaPkcs=2;EncryptAlgorithmType.RsaOaep=3;
+var EncryptParams=function(a,b){this.algorithmType_=a;if(null!=b&&0<b){var c=Crypto.randomBytes(b);this.initialVector_=new Blob(c,!1)}else this.initialVector_=new Blob};exports.EncryptParams=EncryptParams;EncryptParams.prototype.getAlgorithmType=function(){return this.algorithmType_};EncryptParams.prototype.getInitialVector=function(){return this.initialVector_};EncryptParams.prototype.setAlgorithmType=function(a){this.algorithmType_=a;return this};
+EncryptParams.prototype.setInitialVector=function(a){this.initialVector_="object"===typeof a&&a instanceof Blob?a:new Blob(a);return this};
+var Crypto=require("../../crypto.js"),Name=require("../../name.js").Name,KeyLocator=require("../../key-locator.js").KeyLocator,KeyLocatorType=require("../../key-locator.js").KeyLocatorType,TlvWireFormat=require("../../encoding/tlv-wire-format.js").TlvWireFormat,Blob=require("../../util/blob.js").Blob,AesAlgorithm=require("./aes-algorithm.js").AesAlgorithm,RsaAlgorithm=require("./rsa-algorithm.js").RsaAlgorithm,EncryptParams=require("./encrypt-params.js").EncryptParams,EncryptAlgorithmType=require("./encrypt-params.js").EncryptAlgorithmType,
+EncryptedContent=require("../encrypted-content.js").EncryptedContent,SyncPromise=require("../../util/sync-promise.js").SyncPromise,Encryptor=function(a){};exports.Encryptor=Encryptor;Encryptor.NAME_COMPONENT_FOR=new Name.Component("FOR");Encryptor.NAME_COMPONENT_READ=new Name.Component("READ");Encryptor.NAME_COMPONENT_SAMPLE=new Name.Component("SAMPLE");Encryptor.NAME_COMPONENT_ACCESS=new Name.Component("ACCESS");Encryptor.NAME_COMPONENT_E_KEY=new Name.Component("E-KEY");
+Encryptor.NAME_COMPONENT_D_KEY=new Name.Component("D-KEY");Encryptor.NAME_COMPONENT_C_KEY=new Name.Component("C-KEY");
+Encryptor.encryptDataPromise=function(a,b,c,d,e,f){a.getName().append(Encryptor.NAME_COMPONENT_FOR).append(c);var g=e.getAlgorithmType();return g==EncryptAlgorithmType.AesCbc||g==EncryptAlgorithmType.AesEcb?Encryptor.encryptSymmetricPromise_(b,d,c,e,f).then(function(b){a.setContent(b.wireEncode(TlvWireFormat.get()));return SyncPromise.resolve()}):g==EncryptAlgorithmType.RsaPkcs||g==EncryptAlgorithmType.RsaOaep?Encryptor.encryptAsymmetricPromise_(b,d,c,e,f).then(function(b){a.setContent(b.wireEncode(TlvWireFormat.get()));
+return SyncPromise.resolve()},function(g){if(0>g.message.indexOf("data too large for key size"))throw g;g=Crypto.randomBytes(16);var k=new Blob(g,!1);g=new Name(c);g.append("nonce");var l=new EncryptParams(EncryptAlgorithmType.AesCbc,AesAlgorithm.BLOCK_SIZE),m;return Encryptor.encryptSymmetricPromise_(b,k,g,l,f).then(function(a){m=a;return Encryptor.encryptAsymmetricPromise_(k,d,c,e,f)}).then(function(b){var c=m.wireEncode();b=b.wireEncode();var d=new Buffer(c.size()+b.size());b.buf().copy(d,0);c.buf().copy(d,
+b.size());a.setContent(new Blob(d,!1));return SyncPromise.resolve()})}):SyncPromise.reject(Error("Unsupported encryption method"))};Encryptor.encryptData=function(a,b,c,d,e){return SyncPromise.getValue(Encryptor.encryptDataPromise(a,b,c,d,e,!0))};
+Encryptor.encryptSymmetricPromise_=function(a,b,c,d,e){var f=d.getAlgorithmType(),g=d.getInitialVector(),h=new KeyLocator;h.setType(KeyLocatorType.KEYNAME);h.setKeyName(c);return f==EncryptAlgorithmType.AesCbc||f==EncryptAlgorithmType.AesEcb?f==EncryptAlgorithmType.AesCbc&&g.size()!=AesAlgorithm.BLOCK_SIZE?SyncPromise.reject(Error("incorrect initial vector size")):AesAlgorithm.encryptPromise(b,a,d,e).then(function(a){var b=new EncryptedContent;b.setAlgorithmType(f);b.setKeyLocator(h);b.setPayload(a);
+b.setInitialVector(g);return SyncPromise.resolve(b)}):SyncPromise.reject(Error("Unsupported encryption method"))};
+Encryptor.encryptAsymmetricPromise_=function(a,b,c,d,e){var f=d.getAlgorithmType(),g=new KeyLocator;g.setType(KeyLocatorType.KEYNAME);g.setKeyName(c);return f==EncryptAlgorithmType.RsaPkcs||f==EncryptAlgorithmType.RsaOaep?RsaAlgorithm.encryptPromise(b,a,d,e).then(function(a){var b=new EncryptedContent;b.setAlgorithmType(f);b.setKeyLocator(g);b.setPayload(a);return SyncPromise.resolve(b)}):SyncPromise.reject(Error("Unsupported encryption method"))};
+var constants=require("constants"),Crypto=require("../../crypto.js"),Blob=require("../../util/blob.js").Blob,DecryptKey=require("../decrypt-key.js").DecryptKey,EncryptKey=require("../encrypt-key.js").EncryptKey,EncryptAlgorithmType=require("./encrypt-params.js").EncryptAlgorithmType,DerNode=require("../../encoding/der/der-node.js").DerNode,OID=require("../../encoding/oid.js").OID,PrivateKeyStorage=require("../../security/identity/private-key-storage.js").PrivateKeyStorage,UseSubtleCrypto=require("../../use-subtle-crypto-node.js").UseSubtleCrypto,
+SyncPromise=require("../../util/sync-promise.js").SyncPromise,rsaKeygen=null;try{rsaKeygen=require("rsa-keygen")}catch(e$$48){}RsaAlgorithm=function(){};exports.RsaAlgorithm=RsaAlgorithm;
+RsaAlgorithm.generateKeyPromise=function(a,b){if(UseSubtleCrypto()&&!b)return crypto.subtle.generateKey({name:"RSASSA-PKCS1-v1_5",modulusLength:a.getKeySize(),publicExponent:new Uint8Array([1,0,1]),hash:{name:"SHA-256"}},!0,["sign","verify"]).then(function(a){return crypto.subtle.exportKey("pkcs8",a.privateKey)}).then(function(a){return Promise.resolve(new DecryptKey(new Blob(new Uint8Array(a),!1)))});if(!rsaKeygen)return SyncPromise.reject(Error("Need to install rsa-keygen: sudo npm install rsa-keygen"));
+try{var c=rsaKeygen.generate(a.getKeySize()).private_key.toString().replace("-----BEGIN RSA PRIVATE KEY-----","").replace("-----END RSA PRIVATE KEY-----",""),d=new Buffer(c,"base64"),e=PrivateKeyStorage.encodePkcs8PrivateKey(d,new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),new DerNode.DerNull).buf();return SyncPromise.resolve(new DecryptKey(e))}catch(f){return SyncPromise.reject(f)}};RsaAlgorithm.generateKey=function(a){return SyncPromise.getValue(this.generateKeyPromise(a,!0))};
+RsaAlgorithm.deriveEncryptKey=function(a){a=RsaAlgorithm.getRsaPrivateKeyDer(a);var b=DerNode.parse(a.buf(),0).getChildren();a=b[1];var b=b[2],c=new DerNode.DerSequence;c.addChild(a);c.addChild(b);a=c.encode();b=new DerNode.DerSequence;b.addChild(new DerNode.DerOid(new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID)));b.addChild(new DerNode.DerNull);c=new DerNode.DerSequence;c.addChild(b);c.addChild(new DerNode.DerBitString(a.buf(),0));return new EncryptKey(c.encode())};
+RsaAlgorithm.decryptPromise=function(a,b,c,d){if(UseSubtleCrypto()&&!d&&c.getAlgorithmType()!=EncryptAlgorithmType.RsaPkcs)return c.getAlgorithmType()==EncryptAlgorithmType.RsaOaep?crypto.subtle.importKey("pkcs8",a.buf(),{name:"RSA-OAEP",hash:{name:"SHA-1"}},!1,["decrypt"]).then(function(a){return crypto.subtle.decrypt({name:"RSA-OAEP"},a,b.buf())}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!1))}):Promise.reject(Error("unsupported padding scheme"));d=RsaAlgorithm.getRsaPrivateKeyDer(a).buf().toString("base64");
+a="-----BEGIN RSA PRIVATE KEY-----\n";for(var e=0;e<d.length;e+=64)a+=d.substr(e,64)+"\n";a+="-----END RSA PRIVATE KEY-----";if(c.getAlgorithmType()==EncryptAlgorithmType.RsaPkcs)c=constants.RSA_PKCS1_PADDING;else if(c.getAlgorithmType()==EncryptAlgorithmType.RsaOaep)c=constants.RSA_PKCS1_OAEP_PADDING;else return SyncPromise.reject(Error("unsupported padding scheme"));try{return SyncPromise.resolve(new Blob(Crypto.privateDecrypt({key:a,padding:c},b.buf()),!1))}catch(f){return SyncPromise.reject(f)}};
+RsaAlgorithm.decrypt=function(a,b,c){return SyncPromise.getValue(this.decryptPromise(a,b,c,!0))};
+RsaAlgorithm.encryptPromise=function(a,b,c,d){if(UseSubtleCrypto()&&!d&&c.getAlgorithmType()!=EncryptAlgorithmType.RsaPkcs)return c.getAlgorithmType()==EncryptAlgorithmType.RsaOaep?crypto.subtle.importKey("spki",a.buf(),{name:"RSA-OAEP",hash:{name:"SHA-1"}},!1,["encrypt"]).then(function(a){return crypto.subtle.encrypt({name:"RSA-OAEP"},a,b.buf())}).then(function(a){return Promise.resolve(new Blob(new Uint8Array(a),!1))}):Promise.reject(Error("unsupported padding scheme"));d=a.buf().toString("base64");
+a="-----BEGIN PUBLIC KEY-----\n";for(var e=0;e<d.length;e+=64)a+=d.substr(e,64)+"\n";a+="-----END PUBLIC KEY-----";if(c.getAlgorithmType()==EncryptAlgorithmType.RsaPkcs)c=constants.RSA_PKCS1_PADDING;else if(c.getAlgorithmType()==EncryptAlgorithmType.RsaOaep)c=constants.RSA_PKCS1_OAEP_PADDING;else return SyncPromise.reject(Error("unsupported padding scheme"));try{return SyncPromise.resolve(new Blob(Crypto.publicEncrypt({key:a,padding:c},b.buf()),!1))}catch(f){return SyncPromise.reject(f)}};
+RsaAlgorithm.encrypt=function(a,b,c){return SyncPromise.getValue(this.encryptPromise(a,b,c,!0))};RsaAlgorithm.getRsaPrivateKeyDer=function(a){a=DerNode.parse(a.buf(),0).getChildren();if(DerNode.getSequence(a,1).getChildren()[0].toVal()!=PrivateKeyStorage.RSA_ENCRYPTION_OID)throw Error("The PKCS #8 private key is not RSA_ENCRYPTION");return a[2].getPayload()};var SyncPromise=require("../util/sync-promise.js").SyncPromise,ConsumerDb=function(){};exports.ConsumerDb=ConsumerDb;
+ConsumerDb.Error=function(a){if(a)return a.__proto__=ConsumerDb.Error.prototype,a};ConsumerDb.Error.prototype=Error();ConsumerDb.Error.prototype.name="ConsumerDbError";ConsumerDb.prototype.getKeyPromise=function(a,b){return SyncPromise.reject(Error("ConsumerDb.getKeyPromise is not implemented"))};ConsumerDb.prototype.addKeyPromise=function(a,b,c){return SyncPromise.reject(Error("ConsumerDb.addKeyPromise is not implemented"))};ConsumerDb.prototype.deleteKeyPromise=function(a,b){return SyncPromise.reject(Error("ConsumerDb.addKeyPromise is not implemented"))};
+var Blob=require("../util/blob.js").Blob,Name=require("../name.js").Name,Interest=require("../interest.js").Interest,NetworkNack=require("../network-nack.js").NetworkNack,Link=require("../link.js").Link,EncryptedContent=require("./encrypted-content.js").EncryptedContent,EncryptError=require("./encrypt-error.js").EncryptError,EncryptParams=require("./algo/encrypt-params.js").EncryptParams,EncryptAlgorithmType=require("./algo/encrypt-params.js").EncryptAlgorithmType,RsaAlgorithm=require("./algo/rsa-algorithm.js").RsaAlgorithm,
+AesAlgorithm=require("./algo/aes-algorithm.js").AesAlgorithm,Encryptor=require("./algo/encryptor.js").Encryptor,SyncPromise=require("../util/sync-promise.js").SyncPromise,NdnCommon=require("../util/ndn-common.js").NdnCommon,Consumer=function Consumer(b,c,d,e,f,g,h){this.database_=f;this.keyChain_=c;this.face_=b;this.groupName_=new Name(d);this.consumerName_=new Name(e);this.cKeyLink_=void 0==g?Consumer.NO_LINK:new Link(g);this.dKeyLink_=void 0==h?Consumer.NO_LINK:new Link(h);this.cKeyMap_={};this.dKeyMap_=
+{}};exports.Consumer=Consumer;Consumer.prototype.consume=function(a,b,c,d){void 0==d&&(d=Consumer.NO_LINK);a=new Interest(a);var e=this;this.sendInterest_(a,1,new Link(d),function(a){e.decryptContent_(a,function(c){try{b(a,c)}catch(d){console.log("Error in onConsumeComplete: "+NdnCommon.getErrorWithStackTrace(d))}},c)},c)};Consumer.prototype.setGroup=function(a){this.groupName_=new Name(a)};
+Consumer.prototype.addDecryptionKeyPromise=function(a,b,c){return this.consumerName_.match(a)?this.database_.addKeyPromise(a,b,c):SyncPromise.reject(Error("addDecryptionKey: The consumer name must be a prefix of the key name"))};Consumer.prototype.addDecryptionKey=function(a,b,c,d){return SyncPromise.complete(c,d,this.addDecryptionKeyPromise(a,b,!c))};Consumer.Error=function(a,b){this.errorCode=a;this.message=b};
+Consumer.Error.callOnError=function(a,b,c){c||(c="");if(b instanceof Consumer.Error)try{a(b.errorCode,b.message)}catch(d){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(d))}else try{a(EncryptError.ErrorCode.General,c+b)}catch(e){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(e))}};
+Consumer.decryptPromise_=function(a,b){return SyncPromise.resolve().then(function(){if("object"==typeof a&&a instanceof Blob){var c=a;a=new EncryptedContent;a.wireDecode(c)}c=a.getPayload();if(a.getAlgorithmType()==EncryptAlgorithmType.AesCbc){var d=new EncryptParams(EncryptAlgorithmType.AesCbc);d.setInitialVector(a.getInitialVector());return AesAlgorithm.decryptPromise(b,c,d)}return a.getAlgorithmType()==EncryptAlgorithmType.RsaOaep?(d=new EncryptParams(EncryptAlgorithmType.RsaOaep),RsaAlgorithm.decryptPromise(b,
+c,d)):SyncPromise.reject(new Consumer.Error(EncryptError.ErrorCode.UnsupportedEncryptionScheme,""+a.getAlgorithmType()))})};Consumer.decrypt_=function(a,b,c,d){Consumer.decryptPromise_(a,b).then(function(a){c(a)},function(a){Consumer.Error.callOnError(d,a)})};
+Consumer.prototype.decryptContent_=function(a,b,c){var d=new EncryptedContent;try{d.wireDecode(a.getContent())}catch(e){Consumer.Error.callOnError(c,e,"Error decoding EncryptedContent: ");return}var f=d.getKeyLocator().getKeyName();if(a=this.cKeyMap_[f.toUri()])this.decrypt_(d,a,b,c);else{a=new Name(f);a.append(Encryptor.NAME_COMPONENT_FOR).append(this.groupName_);a=new Interest(a);var g=this;this.sendInterest_(a,1,this.cKeyLink_,function(a){g.decryptCKey_(a,function(a){g.cKeyMap_[f.toUri()]=a;Consumer.decrypt_(d,
+a,b,c)},c)},c)}};
+Consumer.prototype.decryptCKey_=function(a,b,c){a=a.getContent();var d=new EncryptedContent;try{d.wireDecode(a)}catch(e){Consumer.Error.callOnError(c,e,"Error decoding EncryptedContent: ");return}a=d.getKeyLocator().getKeyName();var f=a.getPrefix(-3);f.append(Encryptor.NAME_COMPONENT_D_KEY).append(a.getSubName(-2));if(a=this.dKeyMap_[f.toUri()])this.decrypt_(d,a,b,c);else{a=new Name(f);a.append(Encryptor.NAME_COMPONENT_FOR).append(this.consumerName_);a=new Interest(a);var g=this;this.sendInterest_(a,
+1,this.dKeyLink_,function(a){g.decryptDKeyPromise_(a).then(function(a){g.dKeyMap_[f.toUri()]=a;Consumer.decrypt_(d,a,b,c)},function(a){Consumer.Error.callOnError(c,a,"decryptDKey error: ")})},c)}};
+Consumer.prototype.decryptDKeyPromise_=function(a){var b,c,d,e=this;return SyncPromise.resolve().then(function(){b=a.getContent();c=new EncryptedContent;c.wireDecode(b);var d=c.getKeyLocator().getKeyName();return e.getDecryptionKeyPromise_(d)}).then(function(a){if(0==a.size())return SyncPromise.reject(new Consumer.Error(EncryptError.ErrorCode.NoDecryptKey,"The desired consumer decryption key in not in the database"));var e=b.buf().slice(c.wireEncode().size());d=new Blob(e,!1);return 0==d.size()?SyncPromise.reject(new Consumer.Error(EncryptError.ErrorCode.InvalidEncryptedFormat,
+"The data packet does not satisfy the D-KEY packet format")):Consumer.decryptPromise_(c,a)}).then(function(a){return Consumer.decryptPromise_(d,a)})};
+Consumer.prototype.sendInterest_=function(a,b,c,d,e){function f(a,b){try{e(EncryptError.ErrorCode.DataRetrievalFailure,a.getName().toUri())}catch(c){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(c))}}var g=this,h=function(a,b){try{g.keyChain_.verifyData(b,d,function(a,b){try{e(EncryptError.ErrorCode.Validation,"verifyData failed. Reason: "+b)}catch(c){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(c))}})}catch(c){Consumer.Error.callOnError(e,c,"verifyData error: ")}},
+k=function(a){0<b?g.sendInterest_(a,b-1,c,d,e):f(a,new NetworkNack)};0!==c.getDelegations().size()&&(a=new Interest(a),a.setLinkWireEncoding(c.wireEncode()));try{this.face_.expressInterest(a,h,k,f)}catch(l){Consumer.Error.callOnError(e,l,"expressInterest error: ")}};Consumer.prototype.getDecryptionKeyPromise_=function(a){return this.database_.getKeyPromise(a)};Consumer.NO_LINK=new Link;Blob=require("../util/blob.js").Blob;
+DecryptKey=function DecryptKey(b){this.keyBits_="object"===typeof b&&b instanceof DecryptKey?b.keyBits_:"object"===typeof b&&b instanceof Blob?b:new Blob(b)};exports.DecryptKey=DecryptKey;DecryptKey.prototype.getKeyBits=function(){return this.keyBits_};EncryptError=function(){};exports.EncryptError=EncryptError;EncryptError.ErrorCode={Timeout:1,Validation:2,UnsupportedEncryptionScheme:32,InvalidEncryptedFormat:33,NoDecryptKey:34,EncryptionFailure:35,DataRetrievalFailure:36,General:100};Blob=require("../util/blob.js").Blob;
+EncryptKey=function EncryptKey(b){this.keyBits_="object"===typeof b&&b instanceof EncryptKey?b.keyBits_:"object"===typeof b&&b instanceof Blob?b:new Blob(b)};exports.EncryptKey=EncryptKey;EncryptKey.prototype.getKeyBits=function(){return this.keyBits_};KeyLocator=require("../key-locator.js").KeyLocator;WireFormat=require("../encoding/wire-format.js").WireFormat;Blob=require("../util/blob.js").Blob;
+EncryptedContent=function EncryptedContent(b){"object"===typeof b&&b instanceof EncryptedContent?(this.algorithmType_=b.algorithmType_,this.keyLocator_=new KeyLocator(b.keyLocator_),this.initialVector_=b.initialVector_,this.payload_=b.payload_):(this.algorithmType_=null,this.keyLocator_=new KeyLocator,this.initialVector_=new Blob,this.payload_=new Blob)};exports.EncryptedContent=EncryptedContent;EncryptedContent.prototype.getAlgorithmType=function(){return this.algorithmType_};
+EncryptedContent.prototype.getKeyLocator=function(){return this.keyLocator_};EncryptedContent.prototype.getInitialVector=function(){return this.initialVector_};EncryptedContent.prototype.getPayload=function(){return this.payload_};EncryptedContent.prototype.setAlgorithmType=function(a){this.algorithmType_=a;return this};EncryptedContent.prototype.setKeyLocator=function(a){this.keyLocator_="object"===typeof a&&a instanceof KeyLocator?new KeyLocator(a):new KeyLocator;return this};
+EncryptedContent.prototype.setInitialVector=function(a){this.initialVector_="object"===typeof a&&a instanceof Blob?a:new Blob(a);return this};EncryptedContent.prototype.setPayload=function(a){this.payload_="object"===typeof a&&a instanceof Blob?a:new Blob(a);return this};EncryptedContent.prototype.wireEncode=function(a){a=a||WireFormat.getDefaultWireFormat();return a.encodeEncryptedContent(this)};
+EncryptedContent.prototype.wireDecode=function(a,b){b=b||WireFormat.getDefaultWireFormat();"object"===typeof a&&a instanceof Blob?b.decodeEncryptedContent(this,a.buf(),!1):b.decodeEncryptedContent(this,a,!0)};var SyncPromise=require("../util/sync-promise.js").SyncPromise,GroupManagerDb=function(){};exports.GroupManagerDb=GroupManagerDb;GroupManagerDb.Error=function(a){if(a)return a.__proto__=GroupManagerDb.Error.prototype,a};GroupManagerDb.Error.prototype=Error();
+GroupManagerDb.Error.prototype.name="GroupManagerDbError";GroupManagerDb.prototype.hasSchedulePromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.hasSchedulePromise is not implemented"))};GroupManagerDb.prototype.listAllScheduleNamesPromise=function(a){return SyncPromise.reject(Error("GroupManagerDb.listAllScheduleNamesPromise is not implemented"))};GroupManagerDb.prototype.getSchedulePromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.getSchedulePromise is not implemented"))};
+GroupManagerDb.prototype.getScheduleMembersPromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.getScheduleMembersPromise is not implemented"))};GroupManagerDb.prototype.addSchedulePromise=function(a,b,c){return SyncPromise.reject(Error("GroupManagerDb.addSchedulePromise is not implemented"))};GroupManagerDb.prototype.deleteSchedulePromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.deleteSchedulePromise is not implemented"))};
+GroupManagerDb.prototype.renameSchedulePromise=function(a,b,c){return SyncPromise.reject(Error("GroupManagerDb.renameSchedulePromise is not implemented"))};GroupManagerDb.prototype.updateSchedulePromise=function(a,b,c){return SyncPromise.reject(Error("GroupManagerDb.updateSchedulePromise is not implemented"))};GroupManagerDb.prototype.hasMemberPromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.hasMemberPromise is not implemented"))};
+GroupManagerDb.prototype.listAllMembersPromise=function(a){return SyncPromise.reject(Error("GroupManagerDb.listAllMembersPromise is not implemented"))};GroupManagerDb.prototype.getMemberSchedulePromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.getMemberSchedulePromise is not implemented"))};GroupManagerDb.prototype.addMemberPromise=function(a,b,c,d){return SyncPromise.reject(Error("GroupManagerDb.addMemberPromise is not implemented"))};
+GroupManagerDb.prototype.updateMemberSchedulePromise=function(a,b,c){return SyncPromise.reject(Error("GroupManagerDb.updateMemberSchedulePromise is not implemented"))};GroupManagerDb.prototype.deleteMemberPromise=function(a,b){return SyncPromise.reject(Error("GroupManagerDb.deleteMemberPromise is not implemented"))};
+var Name=require("../name.js").Name,Data=require("../data.js").Data,SyncPromise=require("../util/sync-promise.js").SyncPromise,IdentityCertificate=require("../security/certificate/identity-certificate.js").IdentityCertificate,SecurityException=require("../security/security-exception.js").SecurityException,RsaKeyParams=require("../security/key-params.js").RsaKeyParams,EncryptParams=require("./algo/encrypt-params.js").EncryptParams,EncryptAlgorithmType=require("./algo/encrypt-params.js").EncryptAlgorithmType,
+Encryptor=require("./algo/encryptor.js").Encryptor,RsaAlgorithm=require("./algo/rsa-algorithm.js").RsaAlgorithm,Interval=require("./interval.js").Interval,Schedule=require("./schedule.js").Schedule,GroupManager=function(a,b,c,d,e,f){this.namespace_=(new Name(a)).append(Encryptor.NAME_COMPONENT_READ).append(b);this.database_=c;this.keySize_=d;this.freshnessHours_=e;this.keyChain_=f};exports.GroupManager=GroupManager;
+GroupManager.prototype.getGroupKeyPromise=function(a,b){var c=[],d=[],e=this,f,g,h,k;return this.calculateIntervalPromise_(a,c,b).then(function(a){if(!1==a.isValid())return SyncPromise.resolve(d);h=Schedule.toIsoString(a.getStartTime());k=Schedule.toIsoString(a.getEndTime());return e.generateKeyPairPromise_(b).then(function(a){f=a.privateKeyBlob;g=a.publicKeyBlob;return e.createEKeyDataPromise_(h,k,g,b)}).then(function(a){function g(a){return a>=c.length?SyncPromise.resolve():e.createDKeyDataPromise_(h,
+k,c[a].keyName,f,c[a].publicKey,b).then(function(b){d.push(b);return g(a+1)})}d.push(a);return g(0)}).then(function(){return SyncPromise.resolve(d)})})};GroupManager.prototype.addSchedulePromise=function(a,b,c){return this.database_.addSchedulePromise(a,b,c)};GroupManager.prototype.deleteSchedulePromise=function(a,b){return this.database_.deleteSchedulePromise(a,b)};GroupManager.prototype.updateSchedulePromise=function(a,b,c){return this.database_.updateSchedulePromise(b,schedule,c)};
+GroupManager.prototype.addMemberPromise=function(a,b,c){b=new IdentityCertificate(b);return this.database_.addMemberPromise(a,b.getPublicKeyName(),b.getPublicKeyInfo().getKeyDer(),c)};GroupManager.prototype.removeMemberPromise=function(a,b){return this.database_.deleteMemberPromise(a,b)};GroupManager.prototype.updateMemberSchedulePromise=function(a,b,c){return this.database_.updateMemberSchedulePromise(a,b,c)};
+GroupManager.prototype.calculateIntervalPromise_=function(a,b,c){var d=new Interval,e=new Interval;b.splice(0,b.length);var f=this;return this.database_.listAllScheduleNamesPromise(c).then(function(g){function h(k){if(k>=g.length)return SyncPromise.resolve();var l=g[k];return f.database_.getSchedulePromise(l,c).then(function(g){g=g.getCoveringInterval(a);var q=g.interval;if(g.isPositive)return d.isValid()||(d=q),d.intersectWith(q),f.database_.getScheduleMembersPromise(l,c).then(function(a){for(var c=
+0;c<a.length;++c)GroupManager.memberKeysAdd_(b,a[c]);return h(k+1)});e.isValid()||(e=q);e.intersectWith(q);return h(k+1)})}return h(0)}).then(function(){if(!d.isValid())return SyncPromise.resolve(new Interval(!1));var a;a=e.isValid()?d.intersectWith(e):d;return SyncPromise.resolve(a)})};GroupManager.memberKeysAdd_=function(a,b){for(var c=0;c<a.length;){var d=a[c].keyName.compare(b.keyName);if(0==d)return;if(0<d)break;c+=1}a.splice(c,0,b)};
+GroupManager.prototype.generateKeyPairPromise_=function(a){a=new RsaKeyParams(this.keySize_);return RsaAlgorithm.generateKeyPromise(a).then(function(a){a=a.getKeyBits();var c=RsaAlgorithm.deriveEncryptKey(a).getKeyBits();return SyncPromise.resolve({privateKeyBlob:a,publicKeyBlob:c})})};
+GroupManager.prototype.createEKeyDataPromise_=function(a,b,c,d){d=new Name(this.namespace_);d.append(Encryptor.NAME_COMPONENT_E_KEY).append(a).append(b);a=new Data(d);a.getMetaInfo().setFreshnessPeriod(this.freshnessHours_*GroupManager.MILLISECONDS_IN_HOUR);a.setContent(c);return this.keyChain_.signPromise(a)};
+GroupManager.prototype.createDKeyDataPromise_=function(a,b,c,d,e,f){var g=new Name(this.namespace_);g.append(Encryptor.NAME_COMPONENT_D_KEY);g.append(a).append(b);var h=new Data(g);h.getMetaInfo().setFreshnessPeriod(this.freshnessHours_*GroupManager.MILLISECONDS_IN_HOUR);a=new EncryptParams(EncryptAlgorithmType.RsaOaep);var k=this;return Encryptor.encryptDataPromise(h,d,c,e,a,f)["catch"](function(a){return SyncPromise.reject(SecurityException(Error("createDKeyData: Error in encryptData: "+a)))}).then(function(){return k.keyChain_.signPromise(h)})};
+GroupManager.MILLISECONDS_IN_HOUR=36E5;Interval=function Interval(b,c){if("object"===typeof b&&b instanceof Interval)this.startTime_=b.startTime_,this.endTime_=b.endTime_,this.isValid_=b.isValid_;else if("number"===typeof b){if(!(b<c))throw Error("Interval start time must be less than the end time");this.startTime_=b;this.endTime_=c;this.isValid_=!0}else this.startTime_=-Number.MAX_VALUE,this.endTime_=-Number.MAX_VALUE,this.isValid_=b?!0:!1};exports.Interval=Interval;
+Interval.prototype.set=function(a){this.startTime_=a.startTime_;this.endTime_=a.endTime_;this.isValid_=a.isValid_};Interval.prototype.covers=function(a){if(!this.isValid_)throw Error("Interval.covers: This Interval is invalid");return this.isEmpty()?!1:this.startTime_<=a&&a<this.endTime_};
+Interval.prototype.intersectWith=function(a){if(!this.isValid_)throw Error("Interval.intersectWith: This Interval is invalid");if(!a.isValid_)throw Error("Interval.intersectWith: The other Interval is invalid");if(this.isEmpty()||a.isEmpty()||this.startTime_>=a.endTime_||this.endTime_<=a.startTime_)return this.startTime_=this.endTime_,this;this.startTime_<=a.startTime_&&(this.startTime_=a.startTime_);this.endTime_>a.endTime_&&(this.endTime_=a.endTime_);return this};
+Interval.prototype.unionWith=function(a){if(!this.isValid_)throw Error("Interval.intersectWith: This Interval is invalid");if(!a.isValid_)throw Error("Interval.intersectWith: The other Interval is invalid");if(this.isEmpty())return this.startTime_=a.startTime_,this.endTime_=a.endTime_,this;if(a.isEmpty())return this;if(this.startTime_>=a.endTime_||this.endTime_<=a.startTime_)throw Error("Interval.unionWith: The two intervals do not have an intersection");this.startTime_>a.startTime_&&(this.startTime_=
+a.startTime_);this.endTime_<a.endTime_&&(this.endTime_=a.endTime_);return this};Interval.prototype.getStartTime=function(){if(!this.isValid_)throw Error("Interval.getStartTime: This Interval is invalid");return this.startTime_};Interval.prototype.getEndTime=function(){if(!this.isValid_)throw Error("Interval.getEndTime: This Interval is invalid");return this.endTime_};Interval.prototype.isValid=function(){return this.isValid_};
+Interval.prototype.isEmpty=function(){if(!this.isValid_)throw Error("Interval.isEmpty: This Interval is invalid");return this.startTime_==this.endTime_};var SyncPromise=require("../util/sync-promise.js").SyncPromise,ProducerDb=function(){};exports.ProducerDb=ProducerDb;ProducerDb.Error=function(a){if(a)return a.__proto__=ProducerDb.Error.prototype,a};ProducerDb.Error.prototype=Error();ProducerDb.Error.prototype.name="ProducerDbError";ProducerDb.prototype.hasContentKeyPromise=function(a,b){return SyncPromise.reject(Error("ProducerDb.hasContentKeyPromise is not implemented"))};
+ProducerDb.prototype.getContentKeyPromise=function(a,b){return SyncPromise.reject(Error("ProducerDb.getContentKeyPromise is not implemented"))};ProducerDb.prototype.addContentKeyPromise=function(a,b,c){return SyncPromise.reject(Error("ProducerDb.addContentKeyPromise is not implemented"))};ProducerDb.prototype.deleteContentKeyPromise=function(a,b){return SyncPromise.reject(Error("ProducerDb.deleteContentKeyPromise is not implemented"))};
+ProducerDb.getFixedTimeSlot=function(a){return Math.floor(Math.round(a)/36E5)};
+var Name=require("../name.js").Name,Interest=require("../interest.js").Interest,Data=require("../data.js").Data,Link=require("../link.js").Link,NetworkNack=require("../network-nack.js").NetworkNack,Exclude=require("../exclude.js").Exclude,Encryptor=require("./algo/encryptor.js").Encryptor,EncryptParams=require("./algo/encrypt-params.js").EncryptParams,EncryptAlgorithmType=require("./algo/encrypt-params.js").EncryptAlgorithmType,AesKeyParams=require("../security/key-params.js").AesKeyParams,AesAlgorithm=
+require("./algo/aes-algorithm.js").AesAlgorithm,Schedule=require("./schedule.js").Schedule,EncryptError=require("./encrypt-error.js").EncryptError,NdnCommon=require("../util/ndn-common.js").NdnCommon,SyncPromise=require("../util/sync-promise.js").SyncPromise,Producer=function Producer(b,c,d,e,f,g,h){this.face_=d;this.keyChain_=e;this.database_=f;this.maxRepeatAttempts_=void 0==g?3:g;this.keyRetrievalLink_=void 0==h?Producer.NO_LINK:new Link(h);this.eKeyInfo_={};this.keyRequests_={};d=new Name(b);
+e=new Name(c);for(d.append(Encryptor.NAME_COMPONENT_READ);0<e.size();)f=new Name(d),f.append(e),f.append(Encryptor.NAME_COMPONENT_E_KEY),this.eKeyInfo_[f.toUri()]={keyName:f,keyInfo:new Producer.KeyInfo_},e=e.getPrefix(-1);d.append(c);this.namespace_=new Name(b);this.namespace_.append(Encryptor.NAME_COMPONENT_SAMPLE);this.namespace_.append(c)};exports.Producer=Producer;
+Producer.prototype.createContentKey=function(a,b,c,d){d||(d=Producer.defaultOnError);var e=Producer.getRoundedTimeSlot_(a),f=new Name(this.namespace_);f.append(Encryptor.NAME_COMPONENT_C_KEY);f.append(Schedule.toIsoString(e));var g,h=this;this.database_.hasContentKeyPromise(a).then(function(e){e?null!=c&&c(f):(e=new AesKeyParams(128),g=AesAlgorithm.generateKey(e).getKeyBits(),h.database_.addContentKeyPromise(a,g).then(function(){var e=Math.round(a);h.keyRequests_[e]=new Producer.KeyRequest_(h.getEKeyInfoSize_());
+var e=h.keyRequests_[e],g=new Exclude;Producer.excludeAfter(g,new Name.Component(Schedule.toIsoString(a)));for(var k in h.eKeyInfo_){var p=h.eKeyInfo_[k],s=p.keyInfo;a<s.beginTimeSlot||a>=s.endTimeSlot?(e.repeatAttempts[k]=0,h.sendKeyInterest_((new Interest(p.keyName)).setExclude(g).setChildSelector(1),a,b,d)):(p=new Name(p.keyName),p.append(Schedule.toIsoString(s.beginTimeSlot)),p.append(Schedule.toIsoString(s.endTimeSlot)),h.encryptContentKeyPromise_(s.keyBits,p,a,b,d))}null!=c&&c(f)}))})};
+Producer.prototype.produce=function(a,b,c,d,e){e||(e=Producer.defaultOnError);var f=this;this.createContentKey(b,null,function(g){f.database_.getContentKeyPromise(b).then(function(d){var e=new Name(f.namespace_);e.append(Schedule.toIsoString(b));a.setName(e);e=new EncryptParams(EncryptAlgorithmType.AesCbc,16);return Encryptor.encryptData(a,c,g,d,e)}).then(function(){return f.keyChain_.signPromise(a)}).then(function(){try{d()}catch(a){console.log("Error in onComplete: "+NdnCommon.getErrorWithStackTrace(a))}},
+function(a){try{e(EncryptError.ErrorCode.General,""+a)}catch(b){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(b))}})},e)};Producer.defaultOnError=function(a,b){};Producer.KeyInfo_=function(){this.endTimeSlot=this.beginTimeSlot=0;this.keyBits=null};Producer.KeyRequest_=function(a){this.interestCount=a;this.repeatAttempts={};this.encryptedKeys=[]};Producer.getRoundedTimeSlot_=function(a){return Math.round(36E5*Math.floor(Math.round(a)/36E5))};
+Producer.prototype.sendKeyInterest_=function(a,b,c,d){var e=this;0!==this.keyRetrievalLink_.getDelegations().size()&&(a=new Interest(a),a.setLinkWireEncoding(this.keyRetrievalLink_.wireEncode()));this.face_.expressInterest(a,function(a,g){e.handleCoveringKey_(a,g,b,c,d)},function(a){e.handleTimeout_(a,b,c,d)},function(a,g){e.handleNetworkNack_(a,g,b,c,d)})};
+Producer.prototype.handleTimeout_=function(a,b,c,d){var e=Math.round(b),e=this.keyRequests_[e],f=a.getName().toUri();e.repeatAttempts[f]<this.maxRepeatAttempts_?(++e.repeatAttempts[f],this.sendKeyInterest_(a,b,c,d)):this.handleNetworkNack_(a,new NetworkNack,b,c,d)};Producer.prototype.handleNetworkNack_=function(a,b,c,d,e){a=Math.round(c);this.updateKeyRequest_(this.keyRequests_[a],a,d)};
+Producer.prototype.updateKeyRequest_=function(a,b,c){--a.interestCount;if(0==a.interestCount&&null!=c){try{c(a.encryptedKeys)}catch(d){console.log("Error in onEncryptedKeys: "+NdnCommon.getErrorWithStackTrace(d))}delete this.keyRequests_[b]}};
+Producer.prototype.handleCoveringKey_=function(a,b,c,d,e){var f=Math.round(c),f=this.keyRequests_[f],g=a.getName(),h=g.toUri(),k=b.getName(),l=Schedule.fromIsoString(k.get(Producer.START_TIME_STAMP_INDEX).getValue().toString()),m=Schedule.fromIsoString(k.get(Producer.END_TIME_STAMP_INDEX).getValue().toString());if(c>=m)a=new Exclude(a.getExclude()),Producer.excludeBefore(a,k.get(Producer.START_TIME_STAMP_INDEX)),f.repeatAttempts[h]=0,this.sendKeyInterest_((new Interest(g)).setExclude(a).setChildSelector(1),
+c,d,e);else{var q=b.getContent(),p=this;this.encryptContentKeyPromise_(q,k,c,d,e).then(function(a){a&&(a=p.eKeyInfo_[h].keyInfo,a.beginTimeSlot=l,a.endTimeSlot=m,a.keyBits=q)})}};
+Producer.prototype.encryptContentKeyPromise_=function(a,b,c,d,e){var f=Math.round(c),g=this.keyRequests_[f],h=new Name(this.namespace_);h.append(Encryptor.NAME_COMPONENT_C_KEY);h.append(Schedule.toIsoString(Producer.getRoundedTimeSlot_(c)));var k,l=this;return this.database_.getContentKeyPromise(c).then(function(c){k=new Data;k.setName(h);var d=new EncryptParams(EncryptAlgorithmType.RsaOaep);return Encryptor.encryptDataPromise(k,c,b,a,d)}).then(function(){return SyncPromise.resolve(!0)},function(a){try{e(EncryptError.ErrorCode.EncryptionFailure,
+"encryptData failed: "+a)}catch(b){console.log("Error in onError: "+NdnCommon.getErrorWithStackTrace(b))}return SyncPromise.resolve(!1)}).then(function(a){return a?l.keyChain_.signPromise(k).then(function(){g.encryptedKeys.push(k);l.updateKeyRequest_(g,f,d);return SyncPromise.resolve(!0)}):SyncPromise.resolve(!1)})};Producer.prototype.getEKeyInfoSize_=function(){var a=0;for(key in this.eKeyInfo_)this.eKeyInfo_.hasOwnProperty(key)&&++a;return a};
+Producer.ExcludeEntry=function(a,b){this.component_=a;this.anyFollowsComponent_=b};Producer.getExcludeEntries=function(a){for(var b=[],c=0;c<a.size();++c)a.get(c)==Exclude.ANY?0==b.length?b.push(new Producer.ExcludeEntry(new Name.Component,!0)):b[b.length-1].anyFollowsComponent_=!0:b.push(new Producer.ExcludeEntry(a.get(c),!1));return b};
+Producer.setExcludeEntries=function(a,b){a.clear();for(var c=0;c<b.length;++c){var d=b[c];0==c&&0==d.component_.getValue().size()&&d.anyFollowsComponent_?a.appendAny():(a.appendComponent(d.component_),d.anyFollowsComponent_&&a.appendAny())}};Producer.findEntryBeforeOrAt=function(a,b){for(var c=a.length-1;0<=c&&!(0>=a[c].component_.compare(b));)--c;return c};
+Producer.excludeAfter=function(a,b){var c=Producer.getExcludeEntries(a),d;d=Producer.findEntryBeforeOrAt(c,b);if(0>d)c.splice(0,0,new Producer.ExcludeEntry(b,!0)),d=0;else{var e=c[d];e.anyFollowsComponent_||(e.component_.equals(b)?e.anyFollowsComponent_=!0:(c.splice(d+1,0,new Producer.ExcludeEntry(b,!0)),d+=1))}d+=1;c.splice(d,c.length-d);Producer.setExcludeEntries(a,c)};Producer.excludeBefore=function(a,b){Producer.excludeRange(a,new Name.Component,b)};
+Producer.excludeRange=function(a,b,c){if(0<=b.compare(c)){if(0==b.compare(c))throw Error("excludeRange: from == to. To exclude a single component, sue excludeOne.");throw Error("excludeRange: from must be less than to. Invalid range: ["+b.toEscapedString()+", "+c.toEscapedString()+"]");}var d=Producer.getExcludeEntries(a),e=Producer.findEntryBeforeOrAt(d,b);if(0>e)d.splice(0,0,new Producer.ExcludeEntry(b,!0)),b=0;else{var f=d[e];f.anyFollowsComponent_?b=e:f.component_.equals(b)?(f.anyFollowsComponent_=
+!0,b=e):(d.splice(e+1,0,new Producer.ExcludeEntry(b,!0)),b=e+1)}e=Producer.findEntryBeforeOrAt(d,c);f=d[e];e==b?d.splice(b+1,0,new Producer.ExcludeEntry(c,!1)):(f.anyFollowsComponent_?c=e+1:f.component_.equals(c)?c=e:(d.splice(e+1,0,new Producer.ExcludeEntry(c,!1)),c=e+1),b+=1,d.splice(b,c-b));Producer.setExcludeEntries(a,d)};Producer.START_TIME_STAMP_INDEX=-2;Producer.END_TIME_STAMP_INDEX=-1;Producer.NO_LINK=new Link;
+var Interval=require("./interval.js").Interval,RepetitiveInterval=function RepetitiveInterval(b,c,d,e,f,g){if("object"===typeof b&&b instanceof RepetitiveInterval)repetitiveInterval=b,this.startDate_=repetitiveInterval.startDate_,this.endDate_=repetitiveInterval.endDate_,this.intervalStartHour_=repetitiveInterval.intervalStartHour_,this.intervalEndHour_=repetitiveInterval.intervalEndHour_,this.nRepeats_=repetitiveInterval.nRepeats_,this.repeatUnit_=repetitiveInterval.repeatUnit_;else if("number"===
+typeof b){void 0==f&&(f=0);void 0==g&&(g=RepetitiveInterval.RepeatUnit.NONE);this.startDate_=RepetitiveInterval.toDateOnlyMilliseconds_(b);this.endDate_=RepetitiveInterval.toDateOnlyMilliseconds_(c);this.intervalStartHour_=Math.round(d);this.intervalEndHour_=Math.round(e);this.nRepeats_=Math.round(f);this.repeatUnit_=g;if(!(this.intervalStartHour_<this.intervalEndHour_))throw Error("ReptitiveInterval: startHour must be less than endHour");if(!(this.startDate_<=this.endDate_))throw Error("ReptitiveInterval: startDate must be earlier than or same as endDate");
+if(!(0<=this.intervalStartHour_))throw Error("ReptitiveInterval: intervalStartHour must be non-negative");if(!(1<=this.intervalEndHour_&&24>=this.intervalEndHour_))throw Error("ReptitiveInterval: intervalEndHour must be from 1 to 24");if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.NONE&&this.startDate_!=this.endDate_)throw Error("ReptitiveInterval: With RepeatUnit.NONE, startDate must equal endDate");}else this.startDate_=-Number.MAX_VALUE,this.endDate_=-Number.MAX_VALUE,this.intervalStartHour_=
+0,this.intervalEndHour_=24,this.nRepeats_=0,this.repeatUnit_=RepetitiveInterval.RepeatUnit.NONE};exports.RepetitiveInterval=RepetitiveInterval;RepetitiveInterval.RepeatUnit={NONE:0,DAY:1,MONTH:2,YEAR:3};
+RepetitiveInterval.prototype.getInterval=function(a){var b,c;this.hasIntervalOnDate_(a)?(b=RepetitiveInterval.toDateOnlyMilliseconds_(a)+this.intervalStartHour_*RepetitiveInterval.MILLISECONDS_IN_HOUR,c=RepetitiveInterval.toDateOnlyMilliseconds_(a)+this.intervalEndHour_*RepetitiveInterval.MILLISECONDS_IN_HOUR,a<b?(c=b,b=RepetitiveInterval.toDateOnlyMilliseconds_(a),a=!1):a>c?(b=c,c=RepetitiveInterval.toDateOnlyMilliseconds_(a)+RepetitiveInterval.MILLISECONDS_IN_DAY,a=!1):a=!0):(b=RepetitiveInterval.toDateOnlyMilliseconds_(a),
+c=RepetitiveInterval.toDateOnlyMilliseconds_(a)+24*RepetitiveInterval.MILLISECONDS_IN_HOUR,a=!1);return{isPositive:a,interval:new Interval(b,c)}};
+RepetitiveInterval.prototype.compare=function(a){return this.startDate_<a.startDate_?-1:this.startDate_>a.startDate_?1:this.endDate_<a.endDate_?-1:this.endDate_>a.endDate_?1:this.intervalStartHour_<a.intervalStartHour_?-1:this.intervalStartHour_>a.intervalStartHour_?1:this.intervalEndHour_<a.intervalEndHour_?-1:this.intervalEndHour_>a.intervalEndHour_?1:this.nRepeats_<a.nRepeats_?-1:this.nRepeats_>a.nRepeats_?1:this.repeatUnit_<a.repeatUnit_?-1:this.repeatUnit_>a.repeatUnit_?1:0};
+RepetitiveInterval.prototype.getStartDate=function(){return this.startDate_};RepetitiveInterval.prototype.getEndDate=function(){return this.endDate_};RepetitiveInterval.prototype.getIntervalStartHour=function(){return this.intervalStartHour_};RepetitiveInterval.prototype.getIntervalEndHour=function(){return this.intervalEndHour_};RepetitiveInterval.prototype.getNRepeats=function(){return this.nRepeats_};RepetitiveInterval.prototype.getRepeatUnit=function(){return this.repeatUnit_};
+RepetitiveInterval.prototype.hasIntervalOnDate_=function(a){a=RepetitiveInterval.toDateOnlyMilliseconds_(a);if(a<this.startDate_||a>this.endDate_)return!1;if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.NONE)return!0;if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.DAY){if(0==(a-this.startDate_)/RepetitiveInterval.MILLISECONDS_IN_DAY%this.nRepeats_)return!0}else{a=new Date(a);var b=new Date(this.startDate_);if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.MONTH&&a.getUTCDate()==b.getUTCDate()){if(0==
+(12*(a.getUTCFullYear()-b.getUTCFullYear())+a.getUTCMonth()-b.getUTCMonth())%this.nRepeats_)return!0}else if(this.repeatUnit_==RepetitiveInterval.RepeatUnit.YEAR&&a.getUTCDate()==b.getUTCDate()&&a.getUTCMonth()==b.getUTCMonth()&&0==(a.getUTCFullYear()-b.getUTCFullYear())%this.nRepeats_)return!0}return!1};RepetitiveInterval.toDateOnlyMilliseconds_=function(a){a=Math.round(a);return a-=a%RepetitiveInterval.MILLISECONDS_IN_DAY};RepetitiveInterval.MILLISECONDS_IN_HOUR=36E5;
+RepetitiveInterval.MILLISECONDS_IN_DAY=864E5;Interval=require("./interval.js").Interval;RepetitiveInterval=require("./repetitive-interval.js").RepetitiveInterval;Tlv=require("../encoding/tlv/tlv.js").Tlv;TlvEncoder=require("../encoding/tlv/tlv-encoder.js").TlvEncoder;TlvDecoder=require("../encoding/tlv/tlv-decoder.js").TlvDecoder;Blob=require("../util/blob.js").Blob;
+Schedule=function Schedule(b){"object"===typeof b&&b instanceof Schedule?(this.whiteIntervalList_=b.whiteIntervalList_.slice(0),this.blackIntervalList_=b.blackIntervalList_.slice(0)):(this.whiteIntervalList_=[],this.blackIntervalList_=[])};exports.Schedule=Schedule;Schedule.prototype.addWhiteInterval=function(a){Schedule.sortedSetAdd_(this.whiteIntervalList_,a);return this};Schedule.prototype.addBlackInterval=function(a){Schedule.sortedSetAdd_(this.blackIntervalList_,a);return this};
+Schedule.prototype.getCoveringInterval=function(a){var b=new Interval(!0),c=new Interval(!0),d=new Interval,e=new Interval;Schedule.calculateIntervalResult_(this.blackIntervalList_,a,b,d);if(!b.isEmpty())return{isPositive:!1,interval:b};Schedule.calculateIntervalResult_(this.whiteIntervalList_,a,c,e);return c.isEmpty()&&!e.isValid()?(a=RepetitiveInterval.toDateOnlyMilliseconds_(a),{isPositive:!1,interval:new Interval(a,a+RepetitiveInterval.MILLISECONDS_IN_DAY)}):c.isEmpty()?{isPositive:!1,interval:e}:
+d.isValid()?{isPositive:!0,interval:c.intersectWith(d)}:{isPositive:!0,interval:c}};
+Schedule.prototype.wireEncode=function(){for(var a=new TlvEncoder(256),b=a.getLength(),c=a.getLength(),d=this.blackIntervalList_.length-1;0<=d;d--)Schedule.encodeRepetitiveInterval_(this.blackIntervalList_[d],a);a.writeTypeAndLength(Tlv.Encrypt_BlackIntervalList,a.getLength()-c);c=a.getLength();for(d=this.whiteIntervalList_.length-1;0<=d;d--)Schedule.encodeRepetitiveInterval_(this.whiteIntervalList_[d],a);a.writeTypeAndLength(Tlv.Encrypt_WhiteIntervalList,a.getLength()-c);a.writeTypeAndLength(Tlv.Encrypt_Schedule,
+a.getLength()-b);return new Blob(a.getOutput(),!1)};
+Schedule.prototype.wireDecode=function(a){a="object"===typeof a&&a instanceof Blob?a.buf():a;a=new TlvDecoder(a);var b=a.readNestedTlvsStart(Tlv.Encrypt_Schedule);this.whiteIntervalList_=[];for(var c=a.readNestedTlvsStart(Tlv.Encrypt_WhiteIntervalList);a.getOffset()<c;)Schedule.sortedSetAdd_(this.whiteIntervalList_,Schedule.decodeRepetitiveInterval_(a));a.finishNestedTlvs(c);this.blackIntervalList_=[];for(c=a.readNestedTlvsStart(Tlv.Encrypt_BlackIntervalList);a.getOffset()<c;)Schedule.sortedSetAdd_(this.blackIntervalList_,
+Schedule.decodeRepetitiveInterval_(a));a.finishNestedTlvs(c);a.finishNestedTlvs(b)};Schedule.sortedSetAdd_=function(a,b){for(var c=0;c<a.length;){var d=a[c].compare(b);if(0==d)return;if(!(0>d))break;++c}a.splice(c,0,b)};
+Schedule.encodeRepetitiveInterval_=function(a,b){var c=b.getLength();b.writeNonNegativeIntegerTlv(Tlv.Encrypt_RepeatUnit,a.getRepeatUnit());b.writeNonNegativeIntegerTlv(Tlv.Encrypt_NRepeats,a.getNRepeats());b.writeNonNegativeIntegerTlv(Tlv.Encrypt_IntervalEndHour,a.getIntervalEndHour());b.writeNonNegativeIntegerTlv(Tlv.Encrypt_IntervalStartHour,a.getIntervalStartHour());b.writeBlobTlv(Tlv.Encrypt_EndDate,(new Blob(Schedule.toIsoString(a.getEndDate()))).buf());b.writeBlobTlv(Tlv.Encrypt_StartDate,
+(new Blob(Schedule.toIsoString(a.getStartDate()))).buf());b.writeTypeAndLength(Tlv.Encrypt_RepetitiveInterval,b.getLength()-c)};
+Schedule.decodeRepetitiveInterval_=function(a){var b=a.readNestedTlvsStart(Tlv.Encrypt_RepetitiveInterval),c=Schedule.fromIsoString((new Blob(a.readBlobTlv(Tlv.Encrypt_StartDate),!0)).toString()),d=Schedule.fromIsoString((new Blob(a.readBlobTlv(Tlv.Encrypt_EndDate),!0)).toString()),e=a.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalStartHour),f=a.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalEndHour),g=a.readNonNegativeIntegerTlv(Tlv.Encrypt_NRepeats),h=a.readNonNegativeIntegerTlv(Tlv.Encrypt_RepeatUnit);
+a.finishNestedTlvs(b);return new RepetitiveInterval(c,d,e,f,g,h)};Schedule.calculateIntervalResult_=function(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e].getInterval(b),g=f.interval;!0==f.isPositive?c.unionWith(g):d.isValid()?d.intersectWith(g):d.set(g)}};
+Schedule.toIsoString=function(a){a=new Date(Math.round(a));return a.getUTCFullYear()+Schedule.to2DigitString(a.getUTCMonth()+1)+Schedule.to2DigitString(a.getUTCDate())+"T"+Schedule.to2DigitString(a.getUTCHours())+Schedule.to2DigitString(a.getUTCMinutes())+Schedule.to2DigitString(a.getUTCSeconds())};Schedule.to2DigitString=function(a){a=a.toString();return 1===a.length?"0"+a:a};
+Schedule.fromIsoString=function(a){if(15!=a.length||"T"!=a.substr(8,1))throw Error("fromIsoString: Format is not the expected yyyymmddThhmmss");return Date.UTC(parseInt(a.substr(0,4)),parseInt(a.substr(4,2)-1),parseInt(a.substr(6,2)),parseInt(a.substr(9,2)),parseInt(a.substr(11,2)),parseInt(a.substr(13,2)))};var IndexedDbConsumerDb=function(a){ConsumerDb.call(this);this.database=new Dexie(a);this.database.version(1).stores({decryptionKeys:"keyName"});this.database.open()};
+IndexedDbConsumerDb.prototype=new ConsumerDb;IndexedDbConsumerDb.prototype.name="IndexedDbConsumerDb";
+IndexedDbConsumerDb.prototype.getKeyPromise=function(a,b){return b?Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.getKeyPromise is only supported for async"))):this.database.decryptionKeys.get(a.toUri()).then(function(a){return a?Promise.resolve(new Blob(a.key)):Promise.resolve(new Blob)})["catch"](function(a){return Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.getKeyPromise: Error: "+a)))})};
+IndexedDbConsumerDb.prototype.addKeyPromise=function(a,b,c){return c?Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.addKeyPromise is only supported for async"))):this.database.decryptionKeys.add({keyName:a.toUri(),key:b.buf()})["catch"](function(a){return Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.addKeyPromise: Error: "+a)))})};
+IndexedDbConsumerDb.prototype.deleteKeyPromise=function(a,b){return b?Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.deleteKeyPromise is only supported for async"))):this.database.decryptionKeys["delete"](a.toUri())["catch"](function(a){return Promise.reject(new ConsumerDb.Error(Error("IndexedDbConsumerDb.deleteKeyPromise: Error: "+a)))})};
+var IndexedDbGroupManagerDb=function(a){GroupManagerDb.call(this);this.database=new Dexie(a);this.database.version(1).stores({schedules:"++scheduleId, &scheduleName",members:"memberNameUri, scheduleId"});this.database.open()};IndexedDbGroupManagerDb.prototype=new GroupManagerDb;IndexedDbGroupManagerDb.prototype.name="IndexedDbGroupManagerDb";
+IndexedDbGroupManagerDb.prototype.hasSchedulePromise=function(a,b){return b?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.hasSchedulePromise is only supported for async"))):this.getScheduleIdPromise_(a).then(function(a){return Promise.resolve(-1!=a)})};
+IndexedDbGroupManagerDb.prototype.listAllScheduleNamesPromise=function(a){if(a)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllScheduleNamesPromise is only supported for async")));var b=[];return this.database.schedules.each(function(a){b.push(a.scheduleName)}).then(function(){return Promise.resolve(b)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllScheduleNamesPromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.getSchedulePromise=function(a,b){if(b)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getSchedulePromise is only supported for async")));var c=this;return this.getScheduleIdPromise_(a).then(function(a){return-1!=a?c.database.schedules.get(a).then(function(a){var b=new Schedule;b.wireDecode(new Blob(a.schedule,!1));return Promise.resolve(b)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getSchedulePromise: Error: "+
+a)))}):Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getSchedulePromise: Cannot get the result from the database")))})};
+IndexedDbGroupManagerDb.prototype.getScheduleMembersPromise=function(a,b){if(b)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleMembersPromise is only supported for async")));var c=[],d=this;return this.getScheduleIdPromise_(a).then(function(a){if(-1==a)return Promise.resolve(c);var b=null;return d.database.members.where("scheduleId").equals(a).each(function(a){try{var d=new Name;d.wireDecode(new Blob(a.keyName,!1),TlvWireFormat.get());c.push({keyName:d,publicKey:new Blob(a.publicKey,
+!1)})}catch(e){b=new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error decoding name: "+e))}}).then(function(){return b?Promise.reject(b):Promise.resolve(c)},function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error: "+a)))})})};
+IndexedDbGroupManagerDb.prototype.addSchedulePromise=function(a,b,c){return c?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addSchedulePromise is only supported for async"))):0==a.length?Promise.reject(new GroupManagerDb.Error("IndexedDbGroupManagerDb.addSchedulePromise: The schedule name cannot be empty")):this.database.schedules.add({scheduleName:a,schedule:b.wireEncode().buf()})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addContentKeyPromise: Error: "+
+a)))})};
+IndexedDbGroupManagerDb.prototype.deleteSchedulePromise=function(a,b){if(b)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.deleteSchedulePromise is only supported for async")));var c,d=this;return this.getScheduleIdPromise_(a).then(function(a){c=a;return d.database.members.where("scheduleId").equals(c).toArray()}).then(function(a){a=a.map(function(a){return d.database.members["delete"](a.memberNameUri)});return Promise.all(a)}).then(function(){return d.database.schedules["delete"](c)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.deleteSchedulePromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.renameSchedulePromise=function(a,b,c){if(c)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.renameSchedulePromise is only supported for async")));if(0==b.length)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.renameSchedule: The schedule newName cannot be empty")));var d=this;return this.getScheduleIdPromise_(a).then(function(a){return-1==a?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.renameSchedule: The schedule oldName does not exist"))):
+d.database.schedules.update(a,{scheduleName:b})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.renameSchedulePromise: Error: "+a)))})})};
+IndexedDbGroupManagerDb.prototype.updateSchedulePromise=function(a,b,c){if(c)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateSchedulePromise is only supported for async")));var d=this;return this.getScheduleIdPromise_(a).then(function(c){return-1==c?d.addSchedulePromise(a,b):d.database.schedules.update(c,{schedule:b.wireEncode().buf()})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateSchedulePromise: Error: "+
+a)))})})};IndexedDbGroupManagerDb.prototype.hasMemberPromise=function(a,b){return b?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.hasMemberPromise is only supported for async"))):this.database.members.get(a.toUri()).then(function(a){return Promise.resolve(void 0!=a)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.hasMemberPromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.listAllMembersPromise=function(a){if(a)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllMembersPromise is only supported for async")));var b=[],c=null;return this.database.members.each(function(a){try{var e=new Name;e.wireDecode(new Blob(a.memberName,!1),TlvWireFormat.get());b.push(e)}catch(f){c=new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllMembersPromise: Error decoding name: "+f))}}).then(function(){return c?
+Promise.reject(c):Promise.resolve(b)},function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.listAllMembersPromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.getMemberSchedulePromise=function(a,b){if(b)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getMemberSchedulePromise is only supported for async")));var c=this;return this.database.members.get(a.toUri()).then(function(a){if(!a)throw Error("The member identity name does not exist in the database");return c.database.schedules.get(a.scheduleId)}).then(function(a){if(!a)throw Error("The schedule ID for the member identity name does not exist in the database");
+return Promise.resolve(a.scheduleName)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.addMemberPromise=function(a,b,c,d){if(d)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addMemberPromise is only supported for async")));var e=this;return this.getScheduleIdPromise_(a).then(function(a){if(-1==a)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addMemberPromise: The schedule does not exist")));var d=b.getPrefix(-1);return e.database.members.add({memberNameUri:d.toUri(),memberName:d.wireEncode(TlvWireFormat.get()).buf(),
+scheduleId:a,keyName:b.wireEncode(TlvWireFormat.get()).buf(),publicKey:c.buf()})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.addMemberPromise: Error: "+a)))})})};
+IndexedDbGroupManagerDb.prototype.updateMemberSchedulePromise=function(a,b,c){if(c)return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateMemberSchedulePromise is only supported for async")));var d=this;return this.getScheduleIdPromise_(b).then(function(b){return-1==b?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateMemberSchedulePromise: The schedule does not exist"))):d.database.members.update(a.toUri(),{scheduleId:b})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.updateMemberSchedulePromise: Error: "+
+a)))})})};IndexedDbGroupManagerDb.prototype.deleteMemberPromise=function(a,b){return b?Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.deleteMemberPromise is only supported for async"))):this.database.members["delete"](a.toUri())["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.deleteMemberPromise: Error: "+a)))})};
+IndexedDbGroupManagerDb.prototype.getScheduleIdPromise_=function(a){var b=-1;return this.database.schedules.where("scheduleName").equals(a).each(function(a){b=a.scheduleId}).then(function(){return Promise.resolve(b)})["catch"](function(a){return Promise.reject(new GroupManagerDb.Error(Error("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: "+a)))})};var IndexedDbProducerDb=function(a){ProducerDb.call(this);this.database=new Dexie(a);this.database.version(1).stores({contentKeys:"timeSlot"});this.database.open()};
+IndexedDbProducerDb.prototype=new ProducerDb;IndexedDbProducerDb.prototype.name="IndexedDbProducerDb";
+IndexedDbProducerDb.prototype.hasContentKeyPromise=function(a,b){if(b)return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.hasContentKeyPromise is only supported for async")));var c=ProducerDb.getFixedTimeSlot(a);return this.database.contentKeys.get(c).then(function(a){return Promise.resolve(void 0!=a)})["catch"](function(a){return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.hasContentKeyPromise: Error: "+a)))})};
+IndexedDbProducerDb.prototype.getContentKeyPromise=function(a,b){if(b)return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.getContentKeyPromise is only supported for async")));var c=ProducerDb.getFixedTimeSlot(a);return this.database.contentKeys.get(c).then(function(a){return a?Promise.resolve(new Blob(a.key)):Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.getContentKeyPromise: Cannot get the key from the database")))},function(a){return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.getContentKeyPromise: Error: "+
+a)))})};IndexedDbProducerDb.prototype.addContentKeyPromise=function(a,b,c){if(c)return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.addContentKeyPromise is only supported for async")));a=ProducerDb.getFixedTimeSlot(a);return this.database.contentKeys.add({timeSlot:a,key:b.buf()})["catch"](function(a){return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.addContentKeyPromise: Error: "+a)))})};
+IndexedDbProducerDb.prototype.deleteContentKeyPromise=function(a,b){if(b)return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.deleteContentKeyPromise is only supported for async")));var c=ProducerDb.getFixedTimeSlot(a);return this.database.contentKeys["delete"](c)["catch"](function(a){return Promise.reject(new ProducerDb.Error(Error("IndexedDbProducerDb.deleteContentKeyPromise: Error: "+a)))})};
+var DigestTree=require("./digest-tree.js").DigestTree,Interest=require("../interest.js").Interest,Data=require("../data.js").Data,Name=require("../name.js").Name,Blob=require("../util/blob.js").Blob,MemoryContentCache=require("../util/memory-content-cache.js").MemoryContentCache,SyncStateProto=require("./sync-state.js").SyncStateProto,NdnCommon=require("../util/ndn-common.js").NdnCommon,ChronoSync2013=function ChronoSync2013(b,c,d,e,f,g,h,k,l,m){this.onReceivedSyncState=b;this.onInitialized=c;this.applicationDataPrefixUri=
+d.toUri();this.applicationBroadcastPrefix=e;this.session=f;this.face=g;this.keyChain=h;this.certificateName=k;this.sync_lifetime=l;this.usrseq=-1;this.digest_tree=new DigestTree;this.contentCache=new MemoryContentCache(g);this.digest_log=[];this.digest_log.push(new ChronoSync2013.DigestLogEntry("00",[]));this.contentCache.registerPrefix(this.applicationBroadcastPrefix,m,this.onInterest.bind(this));this.enabled=!0;b=new Interest(this.applicationBroadcastPrefix);b.getName().append("00");b.setInterestLifetimeMilliseconds(1E3);
+var q;try{q=dcodeIO.ProtoBuf.newBuilder()["import"](SyncStateProto).build("Sync")}catch(p){q=require("protobufjs").newBuilder()["import"](SyncStateProto).build("Sync")}this.SyncStateMsg=q.SyncStateMsg;this.SyncState=q.SyncState;this.face.expressInterest(b,this.onData.bind(this),this.initialTimeOut.bind(this))};exports.ChronoSync2013=ChronoSync2013;ChronoSync2013.prototype.getProducerSequenceNo=function(a,b){var c=this.digest_tree.find(a,b);return 0>c?-1:this.digest_tree.get(c).getSequenceNo()};
+ChronoSync2013.prototype.publishNextSequenceNo=function(){this.usrseq++;var a=[new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:this.usrseq,session:this.session}})],b=new this.SyncStateMsg({ss:a});this.broadcastSyncState(this.digest_tree.getRoot(),b);this.update(a)||console.log("Warning: ChronoSync: update did not create a new digest log entry");a=new Interest(this.applicationBroadcastPrefix);a.getName().append(this.digest_tree.getRoot());a.setInterestLifetimeMilliseconds(this.sync_lifetime);
+this.face.expressInterest(a,this.onData.bind(this),this.syncTimeout.bind(this))};ChronoSync2013.prototype.getSequenceNo=function(){return this.usrseq};ChronoSync2013.DigestLogEntry=function(a,b){this.digest=a;this.data=b};ChronoSync2013.DigestLogEntry.prototype.getDigest=function(){return this.digest};ChronoSync2013.DigestLogEntry.prototype.getData=function(){return this.data};ChronoSync2013.prototype.shutdown=function(){this.enabled=!1;this.contentCache.unregisterAll()};
+ChronoSync2013.SyncState=function(a,b,c){this.dataPrefixUri_=a;this.sessionNo_=b;this.sequenceNo_=c};ChronoSync2013.SyncState.prototype.getDataPrefix=function(){return this.dataPrefixUri_};ChronoSync2013.SyncState.prototype.getSessionNo=function(){return this.sessionNo_};ChronoSync2013.SyncState.prototype.getSequenceNo=function(){return this.sequenceNo_};
+ChronoSync2013.prototype.broadcastSyncState=function(a,b){var c=new Uint8Array(b.toArrayBuffer()),d=new Data(this.applicationBroadcastPrefix);d.getName().append(a);d.setContent(new Blob(c,!1));var e=this;this.keyChain.sign(d,this.certificateName,function(){e.contentCache.add(d)})};
+ChronoSync2013.prototype.update=function(a){for(var b=0;b<a.length;b++)0==a[b].type&&this.digest_tree.update(a[b].name,a[b].seqno.session,a[b].seqno.seq)&&this.applicationDataPrefixUri==a[b].name&&(this.usrseq=a[b].seqno.seq);return-1==this.logfind(this.digest_tree.getRoot())?(a=new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(),a),this.digest_log.push(a),!0):!1};
+ChronoSync2013.prototype.logfind=function(a){for(var b=0;b<this.digest_log.length;b++)if(a==this.digest_log[b].digest)return b;return-1};
+ChronoSync2013.prototype.onInterest=function(a,b,c,d,e){this.enabled&&(a=b.getName().get(this.applicationBroadcastPrefix.size()).toEscapedString(),b.getName().size()==this.applicationBroadcastPrefix.size()+2&&(a=b.getName().get(this.applicationBroadcastPrefix.size()+1).toEscapedString()),b.getName().size()==this.applicationBroadcastPrefix.size()+2||"00"==a?this.processRecoveryInst(b,a,c):(this.contentCache.storePendingInterest(b,c),a!=this.digest_tree.getRoot()&&(b=this.logfind(a),-1==b?(b=new Interest(new Name("/local/timeout")),
+b.setInterestLifetimeMilliseconds(2E3),this.face.expressInterest(b,this.dummyOnData,this.judgeRecovery.bind(this,b,a,c))):this.processSyncInst(b,a,c))))};
+ChronoSync2013.prototype.onData=function(a,b){if(this.enabled){var c=new Uint8Array(b.getContent().size());c.set(b.getContent().buf());var c=this.SyncStateMsg.decode(c.buffer).ss,d=!1;"00"==this.digest_tree.getRoot()?(d=!0,this.initialOndata(c)):(this.update(c),d=a.getName().size()==this.applicationBroadcastPrefix.size()+2?!0:!1);for(var e=[],f=0;f<c.length;f++)0==c[f].type&&e.push(new ChronoSync2013.SyncState(c[f].name,c[f].seqno.session,c[f].seqno.seq));try{this.onReceivedSyncState(e,d)}catch(g){console.log("Error in onReceivedSyncState: "+
+NdnCommon.getErrorWithStackTrace(g))}c=new Name(this.applicationBroadcastPrefix);c.append(this.digest_tree.getRoot());a=new Interest(c);a.setInterestLifetimeMilliseconds(this.sync_lifetime);this.face.expressInterest(a,this.onData.bind(this),this.syncTimeout.bind(this))}};
+ChronoSync2013.prototype.initialTimeOut=function(a){if(this.enabled){console.log("no other people");this.usrseq++;try{this.onInitialized()}catch(b){console.log("Error in onInitialized: "+NdnCommon.getErrorWithStackTrace(b))}a=[new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:this.usrseq,session:this.session}})];this.update(a);a=new Name(this.applicationBroadcastPrefix);a.append(this.digest_tree.getRoot());a=new Interest(a);a.setInterestLifetimeMilliseconds(this.sync_lifetime);
+this.face.expressInterest(a,this.onData.bind(this),this.syncTimeout.bind(this))}};
+ChronoSync2013.prototype.processRecoveryInst=function(a,b,c){if(-1!=this.logfind(b)){b=[];for(var d=0;d<this.digest_tree.digestnode.length;d++)b[d]=new this.SyncState({name:this.digest_tree.digestnode[d].getDataPrefix(),type:"UPDATE",seqno:{seq:this.digest_tree.digestnode[d].getSequenceNo(),session:this.digest_tree.digestnode[d].getSessionNo()}});if(0!=b.length){b=new this.SyncStateMsg({ss:b});b=new Uint8Array(b.toArrayBuffer());var e=new Data(a.getName());e.setContent(new Blob(b,!1));"00"==a.getName().get(-1).toEscapedString()&&
+e.getMetaInfo().setFreshnessPeriod(1E3);this.keyChain.sign(e,this.certificateName,function(){try{c.putData(e)}catch(a){console.log(a.toString())}})}}};
+ChronoSync2013.prototype.processSyncInst=function(a,b,c){for(var d=[],e=[],f=[],g=[],h=a+1;h<this.digest_log.length;h++)for(var k=this.digest_log[h].getData(),l=0;l<k.length;l++)0==k[l].type&&-1!=this.digest_tree.find(k[l].name,k[l].seqno.session)&&(a=e.indexOf(k[l].name),-1==a?(e.push(k[l].name),f.push(k[l].seqno.seq),g.push(k[l].seqno.session)):(f[a]=k[l].seqno.seq,g[a]=k[l].seqno.session));for(l=0;l<e.length;l++)d[l]=new this.SyncState({name:e[l],type:"UPDATE",seqno:{seq:f[l],session:g[l]}});if(0!=
+d.length){d=new this.SyncStateMsg({ss:d});d=new Uint8Array(d.toArrayBuffer());a=new Name(this.prefix);a.append(this.chatroom).append(b);var m=new Data(a);m.setContent(new Blob(d,!1));this.keyChain.sign(m,this.certificateName,function(){try{c.putData(m)}catch(a){console.log(a.toString())}})}};
+ChronoSync2013.prototype.sendRecovery=function(a){var b=new Name(this.applicationBroadcastPrefix);b.append("recovery").append(a);a=new Interest(b);a.setInterestLifetimeMilliseconds(this.sync_lifetime);this.face.expressInterest(a,this.onData.bind(this),this.syncTimeout.bind(this))};ChronoSync2013.prototype.judgeRecovery=function(a,b,c){a=this.logfind(b);-1!=a?b!=this.digest_tree.root&&this.processSyncInst(a,b,c):this.sendRecovery(b)};
+ChronoSync2013.prototype.syncTimeout=function(a){if(this.enabled&&a.getName().get(4).toEscapedString()==this.digest_tree.root){var b=new Name(a.getName()),b=new Interest(b);a.setInterestLifetimeMilliseconds(this.sync_lifetime);this.face.expressInterest(b,this.onData.bind(this),this.syncTimeout.bind(this))}};
+ChronoSync2013.prototype.initialOndata=function(a){this.update(a);for(var b=this.digest_tree.getRoot(),c=0;c<a.length;c++)if(a[c].name==this.applicationDataPrefixUri&&a[c].seqno.session==this.session){var d=[new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:a[c].seqno.seq+1,session:this.session}})];if(this.update(d)){d=new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(),d);this.digest_log.push(d);try{this.onInitialized()}catch(e){console.log("Error in onInitialized: "+
+NdnCommon.getErrorWithStackTrace(e))}}}d=0<=this.usrseq?new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:this.usrseq,session:this.session}}):new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:0,session:this.session}});a=new this.SyncStateMsg({ss:d});this.broadcastSyncState(b,a);if(-1==this.digest_tree.find(this.applicationDataPrefixUri,this.session)&&(this.usrseq++,a=[new this.SyncState({name:this.applicationDataPrefixUri,type:"UPDATE",seqno:{seq:this.usrseq,
+session:this.session}})],this.update(a)))try{this.onInitialized()}catch(f){console.log("Error in onInitialized: "+NdnCommon.getErrorWithStackTrace(f))}};ChronoSync2013.prototype.dummyOnData=function(a,b){console.log("*** dummyOnData called. ***")};Crypto=require("../crypto.js");DigestTree=function(){this.root="00";this.digestnode=[]};exports.DigestTree=DigestTree;DigestTree.Node=function(a,b,c){this.dataPrefix=a;this.seqno_session=b;this.seqno_seq=c;this.recomputeDigest()};
+DigestTree.Node.prototype.getDataPrefix=function(){return this.dataPrefix};DigestTree.Node.prototype.getSessionNo=function(){return this.seqno_session};DigestTree.Node.prototype.getSequenceNo=function(){return this.seqno_seq};DigestTree.Node.prototype.getDigest=function(){return this.digest};DigestTree.Node.prototype.setSequenceNo=function(a){this.seqno_seq=a;this.recomputeDigest()};
+DigestTree.Node.prototype.Int32ToBuffer=function(a){for(var b=new Buffer(4),c=0;4>c;c++)b[c]=a%256,a=Math.floor(a/256);return b};DigestTree.Node.prototype.recomputeDigest=function(){var a=Crypto.createHash("sha256");a.update(this.Int32ToBuffer(this.seqno_session));a.update(this.Int32ToBuffer(this.seqno_seq));var a=a.digest(),b=Crypto.createHash("sha256");b.update(this.dataPrefix);var b=b.digest(),c=Crypto.createHash("sha256");c.update(b);c.update(a);this.digest=c.digest("hex")};
+DigestTree.Node.Compare=function(a,b){return a.dataPrefix!=b.dataPrefix?a.dataPrefix<b.dataPrefix:a.seqno_session<b.seqno_session};DigestTree.prototype.update=function(a,b,c){var d=this.find(a,b);if(0<=d)if(this.digestnode[d].getSequenceNo()<c)this.digestnode[d].setSequenceNo(c);else return!1;else a=new DigestTree.Node(a,b,c),this.digestnode.push(a),this.digestnode.sort(this.sortNodes);this.recomputeRoot();return!0};
+DigestTree.prototype.sortNodes=function(){for(var a,b=this.digestnode.length;0<b;b--)for(var c=0;c<b-1;c++)this.digestnode[c].getDataPrefix()>this.digestnode[c+1].getDataPrefix()&&(a=this.digestnode[c],this.digestnode[c]=this.digestnode[c+1],this.digestnode[c+1]=a)};
+DigestTree.prototype.sortNodes=function(a,b){return a.getDataPrefix()==b.getDataPrefix()&&a.getSessionNo()==b.getSessionNo()?0:a.getDataPrefix()>b.getDataPrefix()||a.getDataPrefix()==b.getDataPrefix()&&a.getSessionNo()>b.getSessionNo()?1:-1};DigestTree.prototype.find=function(a,b){for(var c=0;c<this.digestnode.length;++c)if(this.digestnode[c].getDataPrefix()==a&&this.digestnode[c].getSessionNo()==b)return c;return-1};DigestTree.prototype.size=function(){return this.digestnode.size()};
+DigestTree.prototype.get=function(a){return this.digestnode[a]};DigestTree.prototype.getRoot=function(){return this.root};DigestTree.prototype.recomputeRoot=function(){for(var a=Crypto.createHash("sha256"),b=0;b<this.digestnode.length;b++)a.update(new Buffer(this.digestnode[b].digest,"hex"));this.root=a.digest("hex")};
+SyncStateProto={"package":"Sync",messages:[{name:"SyncState",fields:[{rule:"required",type:"string",name:"name",id:1,options:{}},{rule:"required",type:"ActionType",name:"type",id:2,options:{}},{rule:"optional",type:"SeqNo",name:"seqno",id:3,options:{}}],enums:[{name:"ActionType",values:[{name:"UPDATE",id:0},{name:"DELETE",id:1},{name:"OTHER",id:2}],options:{}}],messages:[{name:"SeqNo",fields:[{rule:"required",type:"uint32",name:"seq",id:1,options:{}},{rule:"required",type:"uint32",name:"session",
+id:2,options:{}}],enums:[],messages:[],options:{}}],options:{}},{name:"SyncStateMsg",fields:[{rule:"repeated",type:"SyncState",name:"ss",id:1,options:{}}],enums:[],messages:[],options:{}}],enums:[],imports:[],options:{}};exports.SyncStateProto=SyncStateProto;
+var Crypto=require("../crypto.js"),WireFormat=require("../encoding/wire-format.js").WireFormat,TlvEncoder=require("../encoding/tlv/tlv-encoder.js").TlvEncoder,Blob=require("./blob.js").Blob,CommandInterestGenerator=function(){this.lastTimestamp=Math.round((new Date).getTime())};exports.CommandInterestGenerator=CommandInterestGenerator;
+CommandInterestGenerator.prototype.generate=function(a,b,c,d,e){e="function"===typeof d?d:e;d="function"!==typeof d&&d?d:WireFormat.getDefaultWireFormat();for(var f=Math.round((new Date).getTime());f<=this.lastTimestamp;)f+=1;var g=new TlvEncoder(8);g.writeNonNegativeInteger(f);a.getName().append(new Blob(g.getOutput(),!1));a.getName().append(new Blob(Crypto.randomBytes(8),!1));this.lastTimestamp=f;b.sign(a,c,d,function(){(null==a.getInterestLifetimeMilliseconds()||0>a.getInterestLifetimeMilliseconds())&&
+a.setInterestLifetimeMilliseconds(1E3);e&&e()})};var LOG=require("../log.js").Log.LOG,InterestFilterTable=function(){this.table_=[]};exports.InterestFilterTable=InterestFilterTable;InterestFilterTable.Entry=function(a,b,c,d){this.interestFilterId_=a;this.filter_=b;this.onInterest_=c;this.face_=d};InterestFilterTable.Entry.prototype.getInterestFilterId=function(){return this.interestFilterId_};InterestFilterTable.Entry.prototype.getFilter=function(){return this.filter_};
+InterestFilterTable.Entry.prototype.getOnInterest=function(){return this.onInterest_};InterestFilterTable.Entry.prototype.getFace=function(){return this.face_};InterestFilterTable.prototype.setInterestFilter=function(a,b,c,d){this.table_.push(new InterestFilterTable.Entry(a,b,c,d))};InterestFilterTable.prototype.getMatchedFilters=function(a,b){for(var c=0;c<this.table_.length;++c){var d=this.table_[c];d.getFilter().doesMatch(a.getName())&&b.push(d)}};
+InterestFilterTable.prototype.unsetInterestFilter=function(a){for(var b=0,c=this.table_.length-1;0<=c;--c)this.table_[c].getInterestFilterId()==a&&(++b,this.table_.splice(c,1));0===b&&0<LOG&&console.log("unsetInterestFilter: Didn't find interestFilterId "+a)};var NdnCommon=require("../util/ndn-common.js").NdnCommon,LOG=require("../log.js").Log.LOG,PendingInterestTable=function(){this.table_=[];this.removeRequests_=[]};exports.PendingInterestTable=PendingInterestTable;
+PendingInterestTable.Entry=function(a,b,c,d,e){this.pendingInterestId_=a;this.interest_=b;this.onData_=c;this.onTimeout_=d;this.onNetworkNack_=e;this.timerId_=-1};PendingInterestTable.Entry.prototype.getPendingInterestId=function(){return this.pendingInterestId_};PendingInterestTable.Entry.prototype.getInterest=function(){return this.interest_};PendingInterestTable.Entry.prototype.getOnData=function(){return this.onData_};PendingInterestTable.Entry.prototype.getOnNetworkNack=function(){return this.onNetworkNack_};
+PendingInterestTable.Entry.prototype.callTimeout=function(){if(this.onTimeout_)try{this.onTimeout_(this.interest_)}catch(a){console.log("Error in onTimeout: "+NdnCommon.getErrorWithStackTrace(a))}};PendingInterestTable.Entry.prototype.setTimeout=function(a,b){-1===this.timerId_&&(this.timerId_=setTimeout(a,b))};PendingInterestTable.Entry.prototype.clearTimeout=function(){-1!==this.timerId_&&(clearTimeout(this.timerId_),this.timerId_=-1)};
+PendingInterestTable.prototype.add=function(a,b,c,d,e){var f=this.removeRequests_.indexOf(a);if(0<=f)return this.removeRequests_.splice(f,1),null;var g=new PendingInterestTable.Entry(a,b,c,d,e);this.table_.push(g);a=b.getInterestLifetimeMilliseconds()||4E3;var h=this;g.setTimeout(function(){1<LOG&&console.log("Interest time out: "+b.getName().toUri());var a=h.table_.indexOf(g);0<=a&&h.table_.splice(a,1);g.callTimeout()},a);return g};
+PendingInterestTable.prototype.extractEntriesForExpressedInterest=function(a,b){for(var c=this.table_.length-1;0<=c;--c){var d=this.table_[c];d.getInterest().matchesData(a)&&(d.clearTimeout(),b.push(d),this.table_.splice(c,1))}};PendingInterestTable.prototype.extractEntriesForNackInterest=function(a,b){for(var c=a.wireEncode(),d=this.table_.length-1;0<=d;--d){var e=this.table_[d];null!=e.getOnNetworkNack()&&e.getInterest().wireEncode().equals(c)&&(e.clearTimeout(),b.push(e),this.table_.splice(d,1))}};
+PendingInterestTable.prototype.removePendingInterest=function(a){if(null!=a){for(var b=0,c=this.table_.length-1;0<=c;--c){var d=this.table_[c];d.getPendingInterestId()==a&&(d.clearTimeout(),this.table_.splice(c,1),++b)}0===b&&0<LOG&&console.log("removePendingInterest: Didn't find pendingInterestId "+a);0===b&&0>this.removeRequests_.indexOf(a)&&this.removeRequests_.push(a)}};
+var LOG=require("../log.js").Log.LOG,RegisteredPrefixTable=function(a){this.interestFilterTable_=a;this.table_=[];this.removeRequests_=[]};exports.RegisteredPrefixTable=RegisteredPrefixTable;RegisteredPrefixTable.prototype.add=function(a,b,c){var d=this.removeRequests_.indexOf(a);if(0<=d)return this.removeRequests_.splice(d,1),!1;this.table_.push(new RegisteredPrefixTable._Entry(a,b,c));return!0};
+RegisteredPrefixTable.prototype.removeRegisteredPrefix=function(a){for(var b=0,c=this.table_.length-1;0<=c;--c){var d=this.table_[c];d.getRegisteredPrefixId()==a&&(++b,0<d.getRelatedInterestFilterId()&&this.interestFilterTable_.unsetInterestFilter(d.getRelatedInterestFilterId()),this.table_.splice(c,1))}0===b&&0<LOG&&console.log("removeRegisteredPrefix: Didn't find registeredPrefixId "+a);0===b&&0>this.removeRequests_.indexOf(a)&&this.removeRequests_.push(a)};
+RegisteredPrefixTable._Entry=function(a,b,c){this.registeredPrefixId_=a;this.prefix_=b;this.relatedInterestFilterId_=c};RegisteredPrefixTable._Entry.prototype.getRegisteredPrefixId=function(){return this.registeredPrefixId};RegisteredPrefixTable._Entry.prototype.getPrefix=function(){return this.prefix};RegisteredPrefixTable._Entry.prototype.getRelatedInterestFilterId=function(){return this.relatedInterestFilterId};IncomingFaceId=function(){this.faceId_=null};exports.IncomingFaceId=IncomingFaceId;
+IncomingFaceId.prototype.getFaceId=function(){return this.faceId_};IncomingFaceId.prototype.setFaceId=function(a){this.faceId_=a};IncomingFaceId.getFirstHeader=function(a){for(var b=0;b<a.countHeaderFields();++b){var c=a.getHeaderField(b);if(c instanceof IncomingFaceId)return c}return null};var Blob=require("../util/blob.js").Blob,LpPacket=function(){this.headerFields_=[];this.fragmentWireEncoding_=new Blob};exports.LpPacket=LpPacket;LpPacket.prototype.getFragmentWireEncoding=function(){return this.fragmentWireEncoding_};
+LpPacket.prototype.countHeaderFields=function(){return this.headerFields_.length};LpPacket.prototype.getHeaderField=function(a){return this.headerFields_[a]};LpPacket.prototype.clear=function(){this.headerFields_=[];this.fragmentWireEncoding_=new Blob};LpPacket.prototype.setFragmentWireEncoding=function(a){this.fragmentWireEncoding_="object"===typeof a&&a instanceof Blob?a:new Blob(a)};LpPacket.prototype.addHeaderField=function(a){this.headerFields_.push(a)};
+var DataUtils=require("./encoding/data-utils.js").DataUtils,Name=require("./name.js").Name,Interest=require("./interest.js").Interest,Data=require("./data.js").Data,ControlParameters=require("./control-parameters.js").ControlParameters,ControlResponse=require("./control-response.js").ControlResponse,InterestFilter=require("./interest-filter.js").InterestFilter,WireFormat=require("./encoding/wire-format.js").WireFormat,TlvWireFormat=require("./encoding/tlv-wire-format.js").TlvWireFormat,Tlv=require("./encoding/tlv/tlv.js").Tlv,
+TlvDecoder=require("./encoding/tlv/tlv-decoder.js").TlvDecoder,ForwardingFlags=require("./forwarding-flags.js").ForwardingFlags,Transport=require("./transport/transport.js").Transport,TcpTransport=require("./transport/tcp-transport.js").TcpTransport,UnixTransport=require("./transport/unix-transport.js").UnixTransport,CommandInterestGenerator=require("./util/command-interest-generator.js").CommandInterestGenerator,Blob=require("./util/blob.js").Blob,NdnCommon=require("./util/ndn-common.js").NdnCommon,
+NetworkNack=require("./network-nack.js").NetworkNack,LpPacket=require("./lp/lp-packet.js").LpPacket,InterestFilterTable=require("./impl/interest-filter-table.js").InterestFilterTable,PendingInterestTable=require("./impl/pending-interest-table.js").PendingInterestTable,RegisteredPrefixTable=require("./impl/registered-prefix-table.js").RegisteredPrefixTable,fs=require("fs"),LOG=require("./log.js").Log.LOG;
+Face=function Face(b,c){if(!Face.supported)throw Error("The necessary JavaScript support is not available on this platform.");var d;if("object"==typeof b&&b instanceof Transport){if(this.getConnectionInfo=null,this.transport=b,this.connectionInfo=c||null,d={},null==this.connectionInfo&&this.transport&&this.transport.__proto__&&"UnixTransport"==this.transport.__proto__.name){var e=Face.getUnixSocketFilePathForLocalhost();null!=e?this.connectionInfo=new UnixTransport.ConnectionInfo(e):console.log("Face constructor: Cannot determine the default Unix socket file path for UnixTransport");
+0<LOG&&console.log("Using "+this.connectionInfo.toString())}}else d=b||{},this.transport=(d.getTransport||function(){return new TcpTransport})(),this.getConnectionInfo=d.getConnectionInfo||this.transport.defaultGetConnectionInfo,this.connectionInfo=d.connectionInfo||null,null==this.connectionInfo&&(e=void 0!==d.host?d.host:null,this.transport&&this.transport.__proto__&&"UnixTransport"==this.transport.__proto__.name?null!=e?this.connectionInfo=new UnixTransport.ConnectionInfo(e):null==this.getConnectionInfo&&
+(e=Face.getUnixSocketFilePathForLocalhost(),null!=e?this.connectionInfo=new UnixTransport.ConnectionInfo(e):console.log("Face constructor: Cannot determine the default Unix socket file path for UnixTransport")):null!=e&&(this.connectionInfo="undefined"!=typeof WebSocketTransport?new WebSocketTransport.ConnectionInfo(e,d.port||9696):new TcpTransport.ConnectionInfo(e,d.port||6363)));null==this.connectionInfo?this.host=this.host=null:(this.host=this.connectionInfo.host,this.host=this.connectionInfo.port);
+this.readyStatus=Face.UNOPEN;this.onopen=d.onopen||function(){3<LOG&&console.log("Face connection established.")};this.onclose=d.onclose||function(){3<LOG&&console.log("Face connection closed.")};this.onConnectedCallbacks=[];this.commandKeyChain=null;this.commandCertificateName=new Name;this.commandInterestGenerator=new CommandInterestGenerator;this.timeoutPrefix=new Name("/local/timeout");this.pendingInterestTable_=new PendingInterestTable;this.interestFilterTable_=new InterestFilterTable;this.registeredPrefixTable_=
+new RegisteredPrefixTable(this.interestFilterTable_);this.lastEntryId=0};exports.Face=Face;Face.UNOPEN=0;Face.OPEN_REQUESTED=1;Face.OPENED=2;Face.CLOSED=3;TcpTransport.importFace(Face);Face.getUnixSocketFilePathForLocalhost=function(){var a="/var/run/nfd.sock";if(fs.existsSync(a))return a;a="/tmp/.ndnd.sock";return fs.existsSync(a)?a:""};Face.getSupported=function(){try{(new Buffer(1)).slice(0,1)}catch(a){return console.log("NDN not available: Buffer not supported. "+a),!1}return!0};
+Face.supported=Face.getSupported();Face.prototype.createRoute=function(a,b){this.connectionInfo=a instanceof Transport.ConnectionInfo?a:new TcpTransport.ConnectionInfo(a,b);this.host=this.connectionInfo.host;this.host=this.connectionInfo.port};Face.prototype.close=function(){this.readyStatus==Face.OPENED&&(this.readyStatus=Face.CLOSED,this.transport.close())};Face.prototype.getNextEntryId=function(){return++this.lastEntryId};
+Face.makeShuffledHostGetConnectionInfo=function(a,b,c){a=a.slice(0,a.length);DataUtils.shuffle(a);return function(){return 0==a.length?null:c(a.splice(0,1)[0],b)}};
+Face.prototype.expressInterest=function(a,b,c,d,e,f){var g;"object"===typeof a&&a instanceof Interest?g=new Interest(a):b&&"object"===typeof b&&b instanceof Interest?(g=new Interest(b),g.setName(a),b=c,c=d,d=e,e=f):(g=new Interest(a),g.setInterestLifetimeMilliseconds(4E3));var h=b,k,l,m;k="function"===typeof c?c:function(){};l="function"===typeof d?d:null;m=c instanceof WireFormat?c:d instanceof WireFormat?d:e instanceof WireFormat?e:WireFormat.getDefaultWireFormat();var q=this.getNextEntryId();g.setNonce(Face.nonceTemplate_);
+g.refreshNonce();if(null==this.connectionInfo)if(null==this.getConnectionInfo)console.log("ERROR: connectionInfo is NOT SET");else{var p=this;this.connectAndExecute(function(){p.reconnectAndExpressInterest(q,g,h,k,l,m)})}else this.reconnectAndExpressInterest(q,g,h,k,l,m);return q};
+Face.prototype.reconnectAndExpressInterest=function(a,b,c,d,e,f){var g=this;if(this.connectionInfo.equals(this.transport.connectionInfo)&&this.readyStatus!==Face.UNOPEN)if(this.readyStatus===Face.OPEN_REQUESTED)this.onConnectedCallbacks.push(function(){g.expressInterestHelper(a,b,c,d,e,f)});else if(this.readyStatus===Face.OPENED)this.expressInterestHelper(a,b,c,d,e,f);else throw Error("reconnectAndExpressInterest: unexpected connection is not opened");else this.readyStatus=Face.OPEN_REQUESTED,this.onConnectedCallbacks.push(function(){g.expressInterestHelper(a,
+b,c,d,e,f)}),this.transport.connect(this.connectionInfo,this,function(){for(g.readyStatus=Face.OPENED;0<g.onConnectedCallbacks.length;)try{g.onConnectedCallbacks.shift()()}catch(a){console.log("Face.reconnectAndExpressInterest: ignoring exception from onConnectedCallbacks: "+a)}if(g.onopen)g.onopen()},function(){g.closeByTransport()})};
+Face.prototype.expressInterestHelper=function(a,b,c,d,e,f){if(null!=this.pendingInterestTable_.add(a,b,c,d,e)&&!this.timeoutPrefix.match(b.getName())){a=b.wireEncode(f);if(a.size()>Face.getMaxNdnPacketSize())throw Error("The encoded interest size exceeds the maximum limit getMaxNdnPacketSize()");this.transport.send(a.buf())}};Face.prototype.removePendingInterest=function(a){this.pendingInterestTable_.removePendingInterest(a)};
+Face.prototype.setCommandSigningInfo=function(a,b){this.commandKeyChain=a;this.commandCertificateName=new Name(b)};Face.prototype.setCommandCertificateName=function(a){this.commandCertificateName=new Name(a)};Face.prototype.makeCommandInterest=function(a,b,c){c="function"===typeof b?b:c;b="function"!==typeof b&&b?b:WireFormat.getDefaultWireFormat();this.nodeMakeCommandInterest(a,this.commandKeyChain,this.commandCertificateName,b,c)};
+Face.prototype.nodeMakeCommandInterest=function(a,b,c,d,e){this.commandInterestGenerator.generate(a,b,c,d,e)};
+Face.prototype.registerPrefix=function(a,b,c,d,e,f){var g=d,h=e,k=f;d="function"===typeof g?g:null;e=g instanceof ForwardingFlags?g:h instanceof ForwardingFlags?h:new ForwardingFlags;f=g instanceof WireFormat?g:h instanceof WireFormat?h:k instanceof WireFormat?k:WireFormat.getDefaultWireFormat();c||(c=function(){});var l=this.getNextEntryId(),m=this,g=function(){m.nfdRegisterPrefix(l,a,b,e,c,d,m.commandKeyChain,m.commandCertificateName,f)};null==this.connectionInfo?null==this.getConnectionInfo?console.log("ERROR: connectionInfo is NOT SET"):
+this.connectAndExecute(g):g();return l};Face.getMaxNdnPacketSize=function(){return NdnCommon.MAX_NDN_PACKET_SIZE};Face.RegisterResponse=function(a,b,c,d,e,f){this.prefix=a;this.onRegisterFailed=b;this.onRegisterSuccess=c;this.registeredPrefixId=d;this.parent=e;this.onInterest=f};
+Face.RegisterResponse.prototype.onData=function(a,b){var c=new ControlResponse;try{c.wireDecode(b.getContent(),TlvWireFormat.get())}catch(d){0<LOG&&console.log("Register prefix failed: Error decoding the NFD response: "+d);if(this.onRegisterFailed)try{this.onRegisterFailed(this.prefix)}catch(e){console.log("Error in onRegisterFailed: "+NdnCommon.getErrorWithStackTrace(e))}return}if(200!=c.getStatusCode()){if(0<LOG&&console.log("Register prefix failed: Expected NFD status code 200, got: "+c.getStatusCode()),
+this.onRegisterFailed)try{this.onRegisterFailed(this.prefix)}catch(f){console.log("Error in onRegisterFailed: "+NdnCommon.getErrorWithStackTrace(f))}}else{if(0!=this.registeredPrefixId&&(c=0,null!=this.onInterest&&(c=this.parent.setInterestFilter(new InterestFilter(this.prefix),this.onInterest)),!this.parent.registeredPrefixTable_.add(this.registeredPrefixId,this.prefix,c))){0<c&&this.parent.unsetInterestFilter(c);return}2<LOG&&console.log("Register prefix succeeded with the NFD forwarder for prefix "+
+this.prefix.toUri());if(null!=this.onRegisterSuccess)try{this.onRegisterSuccess(this.prefix,this.registeredPrefixId)}catch(g){console.log("Error in onRegisterSuccess: "+NdnCommon.getErrorWithStackTrace(g))}}};Face.RegisterResponse.prototype.onTimeout=function(a){2<LOG&&console.log("Timeout for NFD register prefix command.");if(this.onRegisterFailed)try{this.onRegisterFailed(this.prefix)}catch(b){console.log("Error in onRegisterFailed: "+NdnCommon.getErrorWithStackTrace(b))}};
+Face.prototype.nfdRegisterPrefix=function(a,b,c,d,e,f,g,h,k){if(null==g)throw Error("registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo.");if(0==h.size())throw Error("registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo.");var l=new ControlParameters;l.setName(b);l.setForwardingFlags(d);var m=this;this.isLocal(function(d){var p=new Interest;d?(p.setName(new Name("/localhost/nfd/rib/register")),p.setInterestLifetimeMilliseconds(2E3)):
+(p.setName(new Name("/localhop/nfd/rib/register")),p.setInterestLifetimeMilliseconds(4E3));p.getName().append(l.wireEncode(TlvWireFormat.get()));m.nodeMakeCommandInterest(p,g,h,TlvWireFormat.get(),function(){var d=new Face.RegisterResponse(b,e,f,a,m,c);m.reconnectAndExpressInterest(null,p,d.onData.bind(d),d.onTimeout.bind(d),null,k)})},function(a){0<LOG&&console.log("Error in Transport.isLocal: "+a);if(e)try{e(b)}catch(c){console.log("Error in onRegisterFailed: "+NdnCommon.getErrorWithStackTrace(c))}})};
+Face.prototype.removeRegisteredPrefix=function(a){this.registeredPrefixTable_.removeRegisteredPrefix(a)};Face.prototype.setInterestFilter=function(a,b){var c=this.getNextEntryId();this.interestFilterTable_.setInterestFilter(c,new InterestFilter(a),b,this);return c};Face.prototype.unsetInterestFilter=function(a){this.interestFilterTable_.unsetInterestFilter(a)};
+Face.prototype.putData=function(a,b){b=b||WireFormat.getDefaultWireFormat();var c=a.wireEncode(b);if(c.size()>Face.getMaxNdnPacketSize())throw Error("The encoded Data packet size exceeds the maximum limit getMaxNdnPacketSize()");this.transport.send(c.buf())};Face.prototype.send=function(a){if(a.length>Face.getMaxNdnPacketSize())throw Error("The encoded packet size exceeds the maximum limit getMaxNdnPacketSize()");this.transport.send(a)};
+Face.prototype.isLocal=function(a,b){null==this.connectionInfo?a(!1):this.transport.isLocal(this.connectionInfo,a,b)};
+Face.prototype.onReceivedElement=function(a){3<LOG&&console.log("Complete element received. Length "+a.length+". Start decoding.");var b=null;a[0]==Tlv.LpPacket_LpPacket&&(b=new LpPacket,TlvWireFormat.get().decodeLpPacket(b,a,!1),a=b.getFragmentWireEncoding().buf());var c=null,d=null;if(a[0]==Tlv.Interest||a[0]==Tlv.Data){var e=new TlvDecoder(a);e.peekType(Tlv.Interest,a.length)?(c=new Interest,c.wireDecode(a,TlvWireFormat.get()),null!=b&&c.setLpPacket(b)):e.peekType(Tlv.Data,a.length)&&(d=new Data,
+d.wireDecode(a,TlvWireFormat.get()),null!=b&&d.setLpPacket(b))}if(null!==b&&(b.setFragmentWireEncoding(new Blob),b=NetworkNack.getFirstHeader(b),null!=b)){if(null==c)return;d=[];this.pendingInterestTable_.extractEntriesForNackInterest(c,d);for(a=0;a<d.length;++a){c=d[a];try{c.getOnNetworkNack()(c.getInterest(),b)}catch(f){console.log("Error in onNetworkNack: "+NdnCommon.getErrorWithStackTrace(f))}}return}if(null!==c)for(3<LOG&&console.log("Interest packet received."),d=[],this.interestFilterTable_.getMatchedFilters(c,
+d),a=0;a<d.length;++a){b=d[a];3<LOG&&console.log("Found interest filter for "+c.getName().toUri());try{b.getOnInterest()(b.getFilter().getPrefix(),c,this,b.getInterestFilterId(),b.getFilter())}catch(g){console.log("Error in onInterest: "+NdnCommon.getErrorWithStackTrace(g))}}else if(null!==d)for(3<LOG&&console.log("Data packet received."),b=[],this.pendingInterestTable_.extractEntriesForExpressedInterest(d,b),a=0;a<b.length;++a){c=b[a];try{c.getOnData()(c.getInterest(),d)}catch(h){console.log("Error in onData: "+
+NdnCommon.getErrorWithStackTrace(h))}}};
+Face.prototype.connectAndExecute=function(a){var b=this.getConnectionInfo();if(null==b)console.log("ERROR: No more connectionInfo from getConnectionInfo"),this.host=this.host=this.connectionInfo=null;else if(b.equals(this.connectionInfo))console.log("ERROR: The host returned by getConnectionInfo is not alive: "+this.connectionInfo.toString());else{this.connectionInfo=b;0<LOG&&console.log("connectAndExecute: trying host from getConnectionInfo: "+this.connectionInfo.toString());this.host=this.connectionInfo.host;
+this.host=this.connectionInfo.port;b=new Interest(new Name("/"));b.setInterestLifetimeMilliseconds(4E3);var c=this,d=setTimeout(function(){0<LOG&&console.log("connectAndExecute: timeout waiting for host "+c.host);c.connectAndExecute(a)},3E3);this.reconnectAndExpressInterest(null,b,function(b,f){clearTimeout(d);0<LOG&&console.log("connectAndExecute: connected to host "+c.host);a()},function(a){},null,WireFormat.getDefaultWireFormat())}};
+Face.prototype.closeByTransport=function(){this.readyStatus=Face.CLOSED;this.onclose()};Face.nonceTemplate_=new Blob(new Buffer(4),!1);
+(function(a,b,c){function d(a,b){return"object"!=typeof b&&(b=b()),Object.keys(b).forEach(function(c){a[c]=b[c]}),a}function e(a){return{from:function(b){return a.prototype=Object.create(b.prototype),a.prototype.constructor=a,{extend:function(c){d(a.prototype,"object"!=typeof c?c(b.prototype):c)}}}}}function f(a,b){return b(a)}function g(a,b){function u(a){this._cfg={version:a,storesSource:null,dbschema:{},tables:{},contentUpgrade:null};this.stores({})}function m(a,b,d,e){var g,h,da,k,ra;if(0===a)Object.keys(F).forEach(function(a){W(b,
+a,F[a].primKey,F[a].indexes)}),g=v._createTransaction(H,R,F),g.idbtrans=b,g.idbtrans.onerror=G(d,["populating database"]),g.on("error").subscribe(d),r.newPSD(function(){r.PSD.trans=g;try{v.on("populate").fire(g)}catch(a){e.onerror=b.onerror=function(a){a.preventDefault()};try{b.abort()}catch(c){}b.db.close();d(a)}});else{if(h=[],da=S.filter(function(b){return b._cfg.version===a})[0],!da)throw new y("Dexie specification of currently installed DB version is missing");F=v._dbSchema=da._cfg.dbschema;
+k=!1;da=S.filter(function(b){return b._cfg.version>a});da.forEach(function(a){var e=F,g=a._cfg.dbschema;sa(e,b);sa(g,b);F=v._dbSchema=g;e=ja(e,g);e.add.forEach(function(a){h.push(function(b,c){W(b,a[0],a[1].primKey,a[1].indexes);c()})});e.change.forEach(function(a){if(a.recreate)throw new y("Not yet support for changing primary key");h.push(function(b,c){var d=b.objectStore(a.name);a.add.forEach(function(a){A(d,a)});a.change.forEach(function(a){d.deleteIndex(a.name);A(d,a)});a.del.forEach(function(a){d.deleteIndex(a)});
+c()})});a._cfg.contentUpgrade&&h.push(function(b,c){var e,h;k=!0;e=v._createTransaction(H,[].slice.call(b.db.objectStoreNames,0),g);e.idbtrans=b;h=0;e._promise=f(e._promise,function(a){return function(b,d,e){function f(a){return function(){a.apply(this,arguments);0==--h&&c()}}return++h,a.call(this,b,function(a,b){arguments[0]=f(a);arguments[1]=f(b);d.apply(this,arguments)},e)}});b.onerror=G(d,["running upgrader function for version",a._cfg.version]);e.on("error").subscribe(d);a._cfg.contentUpgrade(e);
+0===h&&c()});k&&(0<=navigator.userAgent.indexOf("Trident")||0<=navigator.userAgent.indexOf("MSIE"))||h.push(function(a,b){for(var d,e=0;e<a.db.objectStoreNames.length;++e)d=a.db.objectStoreNames[e],null!==g[d]&&g[d]!==c||a.db.deleteObjectStore(d);b()})});ra=function(){try{h.length?h.shift()(b,ra):s(F,b)}catch(a){e.onerror=b.onerror=function(a){a.preventDefault()};try{b.abort()}catch(c){}b.db.close();d(a)}};ra()}}function ja(a,b){var c={del:[],add:[],change:[]},d,e,f,g,h,k,n,u;for(d in a)b[d]||c.del.push(d);
+for(d in b)if(e=a[d],f=b[d],e)if(g={name:d,def:b[d],recreate:!1,del:[],add:[],change:[]},e.primKey.src!==f.primKey.src)g.recreate=!0,c.change.push(g);else{h=e.indexes.reduce(function(a,b){return a[b.name]=b,a},{});f=f.indexes.reduce(function(a,b){return a[b.name]=b,a},{});for(k in h)f[k]||g.del.push(k);for(k in f)n=h[k],u=f[k],n?n.src!==u.src&&g.change.push(u):g.add.push(u);(g.recreate||0<g.del.length||0<g.add.length||0<g.change.length)&&c.change.push(g)}else c.add.push([d,f]);return c}function W(a,
+b,c,d){var e=a.db.createObjectStore(b,c.keyPath?{keyPath:c.keyPath,autoIncrement:c.auto}:{autoIncrement:c.auto});return d.forEach(function(a){A(e,a)}),e}function s(a,b){Object.keys(a).forEach(function(c){b.db.objectStoreNames.contains(c)||W(b,c,a[c].primKey,a[c].indexes)})}function A(a,b){a.createIndex(b.name,b.keyPath,{unique:b.unique,multiEntry:b.multi})}function Ha(a,b){throw new y("Table "+b[0]+" not part of transaction. Original Scope Function Source: "+g.Promise.PSD.trans.scopeFunc.toString());
+}function T(a,b,c,d){this.name=a;this.schema=c;this.hook=N[a]?N[a].hook:K(null,{creating:[q,h],reading:[l,k],updating:[p,h],deleting:[M,h]});this._tpf=b;this._collClass=d||X}function ta(a,b,c,d){T.call(this,a,b,c,d||ua)}function va(a,b,c,d){function e(a,b,c,d){return f._promise(a,c,d)}var f=this,g,h;this.db=v;this.mode=a;this.storeNames=b;this.idbtrans=null;this.on=K(this,["complete","error"],"abort");this._reculock=0;this._blockedFuncs=[];this._psd=null;this.active=!0;this._dbschema=c;d&&(this.parent=
+d);this._tpf=e;this.tables=Object.create(wa);for(d=b.length-1;-1!==d;--d)g=b[d],h=v._tableFactory(a,c[g],e),this.tables[g]=h,this[g]||(this[g]=h)}function Y(a,b,c){this._ctx={table:a,index:":id"===b?null:b,collClass:a._collClass,or:c}}function X(a,b){var c=null,d=null,e;if(b)try{c=b()}catch(f){d=f}e=a._ctx;this._ctx={table:e.table,index:e.index,isPrimKey:!e.index||e.table.schema.primKey.keyPath&&e.index===e.table.schema.primKey.name,range:c,op:"openCursor",dir:"next",unique:"",algorithm:null,filter:null,
+isMatch:null,offset:0,limit:Infinity,error:d,or:e.or}}function ua(){X.apply(this,arguments)}function Ia(a,b){return a._cfg.version-b._cfg.version}function U(a,b,c,d,e,f){c.forEach(function(c){var g=v._tableFactory(d,e[c],b);a.forEach(function(a){a[c]||(f?Object.defineProperty(a,c,{configurable:!0,enumerable:!0,get:function(){var a=r.PSD&&r.PSD.trans;return a&&a.db===v?a.tables[c]:g}}):a[c]=g)})})}function ea(a){a.forEach(function(a){for(var b in a)a[b]instanceof T&&delete a[b]})}function ka(a,b,c,
+d,e,f){var g=r.PSD;f=f||k;a.onerror||(a.onerror=G(e));a.onsuccess=b?I(function(){var g=a.result,h;g?(h=function(){g["continue"]()},b(g,function(a){h=a},d,e)&&c(f(g.value),g,function(a){h=a}),h()):d()},e,g):I(function(){var b=a.result,e;b?(e=function(){b["continue"]()},c(f(b.value),b,function(a){e=a}),e()):d()},e,g)}function fa(a){var b=[];return a.split(",").forEach(function(a){a=a.trim();var c=a.replace("&","").replace("++","").replace("*",""),d=0!==c.indexOf("[")?c:a.substring(a.indexOf("[")+1,
+a.indexOf("]")).split("+");b.push(new Z(c,d||null,-1!==a.indexOf("&"),-1!==a.indexOf("*"),-1!==a.indexOf("++"),Array.isArray(d),-1!==d.indexOf(".")))}),b}function la(a,b){return a<b?-1:a>b?1:0}function Da(a,b){return a<b?1:a>b?-1:0}function Ea(a){return function(b,c){for(var d=0,e;;){if(e=a(b[d],c[d]),0!==e)return e;if(++d,d===b.length||d===c.length)return a(b.length,c.length)}}}function ma(a,b){return a?b?function(){return a.apply(this,arguments)&&b.apply(this,arguments)}:a:b}function Ja(){if(v.verno=
+D.version/10,v._dbSchema=F={},R=[].slice.call(D.objectStoreNames,0),0!==R.length){var a=D.transaction(xa(R),"readonly");R.forEach(function(b){for(var c,d=a.objectStore(b),e=d.keyPath,f=e&&"string"==typeof e&&-1!==e.indexOf("."),g=new Z(e,e||"",!1,!1,!!d.autoIncrement,e&&"string"!=typeof e,f),h=[],k=0;k<d.indexNames.length;++k)c=d.index(d.indexNames[k]),f=(e=c.keyPath)&&"string"==typeof e&&-1!==e.indexOf("."),c=new Z(c.name,e,!!c.unique,!!c.multiEntry,!1,e&&"string"!=typeof e,f),h.push(c);F[b]=new ya(b,
+g,h,{})});U([N],v._transPromiseFactory,Object.keys(F),H,F)}}function sa(a,b){for(var c,d,e,f,g=b.db.objectStoreNames,h=0;h<g.length;++h)for(c=g[h],d=b.objectStore(c),e=0;e<d.indexNames.length;++e){var k=d.indexNames[e],n=d.index(k).keyPath,n="string"==typeof n?n:"["+[].slice.call(n).join("+")+"]";a[c]&&(f=a[c].idxByName[n],f&&(f.name=k))}}var ca=b&&b.addons||g.addons,na=g.dependencies,ga=na.indexedDB,L=na.IDBKeyRange,oa=na.TypeError,y=na.Error,F=this._dbSchema={},S=[],R=[],N={},wa={},D=null,$=!0,
+V=null,ha=!1,H="readwrite",v=this,Q=[],aa=!1,ia=!!Fa();this.version=function(a){if(D)throw new y("Cannot add version when database is open");this.verno=Math.max(this.verno,a);var b=S.filter(function(b){return b._cfg.version===a})[0];return b?b:(b=new u(a),S.push(b),S.sort(Ia),b)};d(u.prototype,{stores:function(a){var b,c;return this._cfg.storesSource=this._cfg.storesSource?d(this._cfg.storesSource,a):a,b={},S.forEach(function(a){d(b,a._cfg.storesSource)}),c=this._cfg.dbschema={},this._parseStoresSpec(b,
+c),F=v._dbSchema=c,ea([N,v,wa]),U([wa],Ha,Object.keys(c),H,c),U([N,v,this._cfg.tables],v._transPromiseFactory,Object.keys(c),H,c,!0),R=Object.keys(c),this},upgrade:function(a){var b=this;return B(function(){a(v._createTransaction(H,Object.keys(b._cfg.dbschema),b._cfg.dbschema))}),this._cfg.contentUpgrade=a,this},_parseStoresSpec:function(a,b){Object.keys(a).forEach(function(c){if(null!==a[c]){var d={},e=fa(a[c]),f=e.shift();if(f.multi)throw new y("Primary key cannot be multi-valued");f.keyPath&&f.auto&&
+J(d,f.keyPath,0);e.forEach(function(a){if(a.auto)throw new y("Only primary key can be marked as autoIncrement (++)");if(!a.keyPath)throw new y("Index must have a name and cannot be an empty string");J(d,a.keyPath,a.compound?a.keyPath.map(function(){return""}):"")});b[c]=new ya(c,f,e,d)}})}});this._allTables=N;this._tableFactory=function(a,b,c){return"readonly"===a?new T(b.name,c,b,X):new ta(b.name,c,b)};this._createTransaction=function(a,b,c,d){return new va(a,b,c,d)};this._transPromiseFactory=function(a,
+b,c){var d,e;return!$||r.PSD&&r.PSD.letThrough?(e=v._createTransaction(a,b,F),e._promise(a,function(a,b){e.error(function(a){v.on("error").fire(a)});c(function(b){e.complete(function(){a(b)})},b,e)})):d=new r(function(e,f){Q.push({resume:function(){var g=v._transPromiseFactory(a,b,c);d.onuncatched=g.onuncatched;g.then(e,f)}})})};this._whenReady=function(a){return!$||r.PSD&&r.PSD.letThrough?new r(a):new r(function(b,c){B(function(){new r(function(){a(b,c)})});Q.push({resume:function(){a(b,c)}})})};
+this.verno=0;this.open=function(){return new r(function(b,c){function d(a){try{e.transaction.abort()}catch(b){}ha=!1;V=a;$=!1;c(V);Q.forEach(function(a){a.resume()});Q=[]}if(D||ha)throw new y("Database already opened or being opened");var e;try{if(V=null,ha=!0,0===S.length&&(aa=!0),!ga)throw new y("indexedDB API not found. If using IE10+, make sure to run your code on a server URL (not locally). If using Safari, make sure to include indexedDB polyfill.");e=aa?ga.open(a):ga.open(a,Math.round(10*v.verno));
+e.onerror=G(d,["opening database",a]);e.onblocked=function(a){v.on("blocked").fire(a)};e.onupgradeneeded=I(function(b){var c,f;aa&&!v._allowEmptyDB?(e.onerror=function(a){a.preventDefault()},e.transaction.abort(),e.result.close(),c=ga.deleteDatabase(a),c.onsuccess=c.onerror=function(){d(new y("Database '"+a+"' doesnt exist"))}):(e.transaction.onerror=G(d),f=b.oldVersion>Math.pow(2,62)?0:b.oldVersion,m(f/10,e.transaction,d,e))},d);e.onsuccess=I(function(){ha=!1;D=e.result;aa?Ja():0<D.objectStoreNames.length&&
+sa(F,D.transaction(xa(D.objectStoreNames),"readonly"));D.onversionchange=v.on("versionchange").fire;ia||za(function(b){if(-1===b.indexOf(a))return b.push(a)});r.newPSD(function(){function a(){$=!1;Q.forEach(function(a){a.resume()});Q=[];b()}r.PSD.letThrough=!0;try{var c=v.on.ready.fire();c&&"function"==typeof c.then?c.then(a,function(a){D.close();D=null;d(a)}):x(a)}catch(e){d(e)}})},d)}catch(f){d(f)}})};this.close=function(){D&&(D.close(),D=null,$=!0,V=null)};this["delete"]=function(){var b=arguments;
+return new r(function(c,d){function e(){v.close();var b=ga.deleteDatabase(a);b.onsuccess=function(){ia||za(function(b){var c=b.indexOf(a);if(0<=c)return b.splice(c,1)});c()};b.onerror=G(d,["deleting",a]);b.onblocked=function(){v.on("blocked").fire()}}if(0<b.length)throw new y("Arguments not allowed in db.delete()");ha?Q.push({resume:e}):e()})};this.backendDB=function(){return D};this.isOpen=function(){return null!==D};this.hasFailed=function(){return null!==V};this.dynamicallyOpened=function(){return aa};
+this.name=a;Object.defineProperty(this,"tables",{get:function(){return Object.keys(N).map(function(a){return N[a]})}});this.on=K(this,"error","populate","blocked",{ready:[O,h],versionchange:[w,h]});this.on.ready.subscribe=f(this.on.ready.subscribe,function(a){return function(b,c){function d(){return c||v.on.ready.unsubscribe(d),b.apply(this,arguments)}a.call(this,d);v.isOpen()&&($?Q.push({resume:d}):d())}});B(function(){v.on("populate").fire(v._createTransaction(H,R,F));v.on("error").fire(new y)});
+this.transaction=function(a,b,c){function d(b,g){var n=null,u,l,E;try{if(h)throw h;n=v._createTransaction(a,k,F,e);u=k.map(function(a){return n.tables[a]});u.push(n);E=0;r.newPSD(function(){r.PSD.trans=n;n.scopeFunc=c;e&&(n.idbtrans=e.idbtrans,n._promise=f(n._promise,function(a){return function(b,c,d){function e(a){return function(b){var c;return r._rootExec(function(){c=a(b);r._tickFinalize(function(){0==--E&&n.active&&(n.active=!1,n.on.complete.fire())})}),c}}return++E,a.call(this,b,function(a,
+b,d){return c(e(a),e(b),d)},d)}}));n.complete(function(){b(l)});n.error(function(a){n.idbtrans&&(n.idbtrans.onerror=Ga);try{n.abort()}catch(b){}e&&(e.active=!1,e.on.error.fire(a));var c=g(a);e||c||v.on.error.fire(a)});r._rootExec(function(){l=c.apply(n,u)})});(!n.idbtrans||e&&0===E)&&n._nop()}catch(m){n&&n.idbtrans&&(n.idbtrans.onerror=Ga),n&&n.abort(),e&&e.on.error.fire(m),x(function(){g(m)||v.on("error").fire(m)})}}var e,g;b=[].slice.call(arguments,1,arguments.length-1);c=arguments[arguments.length-
+1];(e=r.PSD&&r.PSD.trans)&&e.db===v&&-1===a.indexOf("!")||(e=null);g=-1!==a.indexOf("?");a=a.replace("!","").replace("?","");var h=null,k=(Array.isArray(b[0])?b.reduce(function(a,b){return a.concat(b)}):b).map(function(a){return"string"==typeof a?a:(a instanceof T||(h=h||new oa("Invalid type. Arguments following mode must be instances of Table or String")),a.name)});return"r"==a||"readonly"==a?a="readonly":"rw"==a||a==H?a=H:h=new y("Invalid transaction mode: "+a),e&&(h||(e&&"readonly"===e.mode&&a===
+H&&(g?e=null:h=h||new y("Cannot enter a sub-transaction with READWRITE mode when parent transaction is READONLY")),e&&k.forEach(function(a){e.tables.hasOwnProperty(a)||(g?e=null:h=h||new y("Table "+a+" not included in parent transaction. Parent Transaction function: "+e.scopeFunc.toString()))}))),e?e._promise(a,d,"lock"):v._whenReady(d)};this.table=function(a){if(!aa&&!N.hasOwnProperty(a))throw new y("Table does not exist");return N[a]};d(T.prototype,function(){function a(){throw new y("Current Transaction is READONLY");
+}return{_trans:function(a,b,c){return this._tpf(a,[this.name],b,c)},_idbstore:function(a,b,c){var d=this;return this._tpf(a,[this.name],function(a,c,e){b(a,c,e.idbtrans.objectStore(d.name),e)},c)},get:function(a,b){var c=this;return B(function(){b(c.schema.instanceTemplate)}),this._idbstore("readonly",function(b,d,e){var f=e.get(a);f.onerror=G(d,["getting",a,"from",c.name]);f.onsuccess=function(){b(c.hook.reading.fire(f.result))}}).then(b)},where:function(a){return new Y(this,a)},count:function(a){return this.toCollection().count(a)},
+offset:function(a){return this.toCollection().offset(a)},limit:function(a){return this.toCollection().limit(a)},reverse:function(){return this.toCollection().reverse()},filter:function(a){return this.toCollection().and(a)},each:function(a){var b=this;return B(function(){a(b.schema.instanceTemplate)}),this._idbstore("readonly",function(c,d,e){e=e.openCursor();e.onerror=G(d,["calling","Table.each()","on",b.name]);ka(e,null,a,c,d,b.hook.reading.fire)})},toArray:function(a){var b=this;return B(function(){a([b.schema.instanceTemplate])}),
+this._idbstore("readonly",function(a,c,d){var e=[];d=d.openCursor();d.onerror=G(c,["calling","Table.toArray()","on",b.name]);ka(d,null,function(a){e.push(a)},function(){a(e)},c,b.hook.reading.fire)}).then(a)},orderBy:function(a){return new this._collClass(new Y(this,a))},toCollection:function(){return new this._collClass(new Y(this))},mapToClass:function(a,b){var c,d;return this.schema.mappedClass=a,c=Object.create(a.prototype),this.schema.primKey.keyPath&&(J(c,this.schema.primKey.keyPath,this.schema.primKey.auto?
+0:""),Ba(a.prototype,this.schema.primKey.keyPath)),b&&Aa(c,b),this.schema.instanceTemplate=c,d=Object.setPrototypeOf?function(b){return b?(Object.setPrototypeOf(b,a.prototype),b):b}:function(b){var c,d;if(!b)return b;c=Object.create(a.prototype);for(d in b)b.hasOwnProperty(d)&&(c[d]=b[d]);return c},this.schema.readHook&&this.hook.reading.unsubscribe(this.schema.readHook),this.schema.readHook=d,this.hook("reading",d),a},defineClass:function(a){return this.mapToClass(g.defineClass(a),a)},add:a,put:a,
+"delete":a,clear:a,update:a}});e(ta).from(T).extend(function(){return{add:function(a,b){var d=this,e=this.hook.creating.fire;return this._idbstore(H,function(f,g,k,n){var u={},l,E,m;e!==h&&(l=b||(k.keyPath?P(a,k.keyPath):c),E=e.call(u,l,a,n),l===c&&E!==c&&(k.keyPath?J(a,k.keyPath,E):b=E));m=b?k.add(a,b):k.add(a);m.onerror=G(function(a){if(u.onerror)u.onerror(a);return g(a)},["adding",a,"into",d.name]);m.onsuccess=function(b){var c=k.keyPath;if(c&&J(a,c,b.target.result),u.onsuccess)u.onsuccess(b.target.result);
+f(m.result)}})},put:function(a,b){var d=this,e=this.hook.updating.fire;return this.hook.creating.fire!==h||e!==h?this._trans(H,function(e,f,g){var h=b||d.schema.primKey.keyPath&&P(a,d.schema.primKey.keyPath);h===c?g.tables[d.name].add(a).then(e,f):(g._lock(),a=ba(a),g.tables[d.name].where(":id").equals(h).modify(function(){this.value=a}).then(function(c){return 0===c?g.tables[d.name].add(a,b):h})["finally"](function(){g._unlock()}).then(e,f))}):this._idbstore(H,function(c,e,f){var g=b?f.put(a,b):
+f.put(a);g.onerror=G(e,["putting",a,"into",d.name]);g.onsuccess=function(b){var d=f.keyPath;d&&J(a,d,b.target.result);c(g.result)}})},"delete":function(a){return this.hook.deleting.subscribers.length?this.where(":id").equals(a)["delete"]():this._idbstore(H,function(b,c,d){var e=d["delete"](a);e.onerror=G(c,["deleting",a,"from",d.name]);e.onsuccess=function(){b(e.result)}})},clear:function(){return this.hook.deleting.subscribers.length?this.toCollection()["delete"]():this._idbstore(H,function(a,b,
+c){var d=c.clear();d.onerror=G(b,["clearing",c.name]);d.onsuccess=function(){a(d.result)}})},update:function(a,b){if("object"!=typeof b||Array.isArray(b))throw new y("db.update(keyOrObject, modifications). modifications must be an object.");if("object"!=typeof a||Array.isArray(a))return this.where(":id").equals(a).modify(b);Object.keys(b).forEach(function(c){J(a,c,b[c])});var d=P(a,this.schema.primKey.keyPath);return d===c&&r.reject(new y("Object does not contain its primary key")),this.where(":id").equals(d).modify(b)}}});
+d(va.prototype,{_lock:function(){return++this._reculock,1===this._reculock&&r.PSD&&(r.PSD.lockOwnerFor=this),this},_unlock:function(){if(0==--this._reculock)for(r.PSD&&(r.PSD.lockOwnerFor=null);0<this._blockedFuncs.length&&!this._locked();){var a=this._blockedFuncs.shift();try{a()}catch(b){}}return this},_locked:function(){return this._reculock&&(!r.PSD||r.PSD.lockOwnerFor!==this)},_nop:function(a){this.tables[this.storeNames[0]].get(0).then(a)},_promise:function(a,b,c){var d=this;return r.newPSD(function(){var e;
+return d._locked()?e=new r(function(e,f){d._blockedFuncs.push(function(){d._promise(a,b,c).then(e,f)})}):(e=d.active?new r(function(e,f){if(!d.idbtrans&&a){if(!D)throw V?new y("Database not open. Following error in populate, ready or upgrade function made Dexie.open() fail: "+V):new y("Database not open");var h=d.idbtrans=D.transaction(xa(d.storeNames),d.mode);h.onerror=function(a){d.on("error").fire(a&&a.target.error);a.preventDefault();d.abort()};h.onabort=function(a){d.active=!1;d.on("abort").fire(a)};
+h.oncomplete=function(a){d.active=!1;d.on("complete").fire(a)}}c&&d._lock();try{b(e,f,d)}catch(k){g.ignoreTransaction(function(){d.on("error").fire(k)}),d.abort(),f(k)}}):r.reject(Ka(new y("Transaction is inactive. Original Scope Function Source: "+d.scopeFunc.toString()))),d.active&&c&&e["finally"](function(){d._unlock()})),e.onuncatched=function(a){g.ignoreTransaction(function(){d.on("error").fire(a)});d.abort()},e})},complete:function(a){return this.on("complete",a)},error:function(a){return this.on("error",
+a)},abort:function(){if(this.idbtrans&&this.active)try{this.active=!1,this.idbtrans.abort(),this.on.error.fire(new y("Transaction Aborted"))}catch(a){}},table:function(a){if(!this.tables.hasOwnProperty(a))throw new y("Table "+a+" not in transaction");return this.tables[a]}});d(Y.prototype,function(){function a(b,c){try{throw c;}catch(d){b._ctx.error=d}return b}function b(a){return Array.prototype.slice.call(1===a.length&&Array.isArray(a[0])?a[0]:a)}function c(a){return"next"===a?function(a){return a.toUpperCase()}:
+function(a){return a.toLowerCase()}}function d(a){return"next"===a?function(a){return a.toLowerCase()}:function(a){return a.toUpperCase()}}function e(a,b,c,d,f,g){for(var h,k=Math.min(a.length,d.length),n=-1,u=0;u<k;++u){if(h=b[u],h!==d[u])return 0>f(a[u],c[u])?a.substr(0,u)+c[u]+c.substr(u+1):0>f(a[u],d[u])?a.substr(0,u)+d[u]+c.substr(u+1):0<=n?a.substr(0,n)+b[n]+c.substr(n+1):null;0>f(a[u],h)&&(n=u)}return k<d.length&&"next"===g?a+c.substr(a.length):k<a.length&&"prev"===g?a.substr(0,c.length):0>
+n?null:a.substr(0,n)+d[n]+c.substr(n+1)}function f(a,b,g){function h(a){k=c(a);n=d(a);u="next"===a?la:Da;l=k(g);E=n(g);m=a}var k,n,u,l,E,m;h("next");a._ondirectionchange=function(a){h(a)};a._addAlgorithm(function(a,c,d){var f=a.key,g,h;return"string"!=typeof f?!1:(g=n(f),b(g,E)?(c(function(){a["continue"]()}),!0):(h=e(f,g,l,E,u,m),h?c(function(){a["continue"](h)}):c(d),!1))})}return{between:function(a,b,c,d){return(c=!1!==c,d=!0===d,a>b||a===b&&!(!c&&!d||c&&d))?(new this._ctx.collClass(this,function(){return L.only(a)})).limit(0):
+new this._ctx.collClass(this,function(){return L.bound(a,b,!c,!d)})},equals:function(a){return new this._ctx.collClass(this,function(){return L.only(a)})},above:function(a){return new this._ctx.collClass(this,function(){return L.lowerBound(a,!0)})},aboveOrEqual:function(a){return new this._ctx.collClass(this,function(){return L.lowerBound(a)})},below:function(a){return new this._ctx.collClass(this,function(){return L.upperBound(a,!0)})},belowOrEqual:function(a){return new this._ctx.collClass(this,
+function(){return L.upperBound(a)})},startsWith:function(b){return"string"!=typeof b?a(new this._ctx.collClass(this),new oa("String expected")):this.between(b,b+String.fromCharCode(65535),!0,!0)},startsWithIgnoreCase:function(b){if("string"!=typeof b)return a(new this._ctx.collClass(this),new oa("String expected"));if(""===b)return this.startsWith(b);var c=new this._ctx.collClass(this,function(){return L.bound(b.toUpperCase(),b.toLowerCase()+String.fromCharCode(65535))});return f(c,function(a,b){return 0===
+a.indexOf(b)},b),c._ondirectionchange=function(){a(c,new y("reverse() not supported with WhereClause.startsWithIgnoreCase()"))},c},equalsIgnoreCase:function(b){if("string"!=typeof b)return a(new this._ctx.collClass(this),new oa("String expected"));var c=new this._ctx.collClass(this,function(){return L.bound(b.toUpperCase(),b.toLowerCase())});return f(c,function(a,b){return a===b},b),c},anyOf:function(){var a=this._ctx,c=a.table.schema,d=(a=a.index?c.idxByName[a.index]:c.primKey)&&a.compound,e=b(arguments),
+f=d?Ea(la):la,g,h;return(e.sort(f),0===e.length)?(new this._ctx.collClass(this,function(){return L.only("")})).limit(0):(g=new this._ctx.collClass(this,function(){return L.bound(e[0],e[e.length-1])}),g._ondirectionchange=function(a){f="next"===a?la:Da;d&&(f=Ea(f));e.sort(f)},h=0,g._addAlgorithm(function(a,b,c){for(var d=a.key;0<f(d,e[h]);)if(++h,h===e.length)return b(c),!1;return 0===f(d,e[h])?(b(function(){a["continue"]()}),!0):(b(function(){a["continue"](e[h])}),!1)}),g)}}});d(X.prototype,function(){function a(b,
+c){b.filter=ma(b.filter,c)}function b(a,c){a.isMatch=ma(a.isMatch,c)}function c(a,b){if(a.isPrimKey)return b;var d=a.table.schema.idxByName[a.index];if(!d)throw new y("KeyPath "+a.index+" on object store "+b.name+" is not indexed");return a.isPrimKey?b:b.index(d.name)}function d(a,b){return c(a,b)[a.op](a.range||null,a.dir+a.unique)}function e(a,b,c,f,g){a.or?function(){function e(){2==++u&&c()}function h(a,c,d){if(!k||k(c,d,e,f)){var g=c.primaryKey.toString();n.hasOwnProperty(g)||(n[g]=!0,b(a,c,
+d))}}var k=a.filter,n={},u=0;a.or._iterate(h,e,f,g);ka(d(a,g),a.algorithm,h,e,f,a.table.hook.reading.fire)}():ka(d(a,g),ma(a.algorithm,a.filter),b,c,f,a.table.hook.reading.fire)}function f(a){return a.table.schema.instanceTemplate}return{_read:function(a,b){var c=this._ctx;return c.error?c.table._trans(null,function(a,b){b(c.error)}):c.table._idbstore("readonly",a).then(b)},_write:function(a){var b=this._ctx;return b.error?b.table._trans(null,function(a,c){c(b.error)}):b.table._idbstore(H,a,"locked")},
+_addAlgorithm:function(a){var b=this._ctx;b.algorithm=ma(b.algorithm,a)},_iterate:function(a,b,c,d){return e(this._ctx,a,b,c,d)},each:function(a){var b=this._ctx;return B(function(){a(f(b))}),this._read(function(c,d,f){e(b,a,c,d,f)})},count:function(a){var b,d,f;return B(function(){a(0)}),b=this,d=this._ctx,d.filter||d.algorithm||d.or?(f=0,this._read(function(a,b,c){e(d,function(){return++f,!1},function(){a(f)},b,c)},a)):this._read(function(a,e,f){f=c(d,f);f=d.range?f.count(d.range):f.count();f.onerror=
+G(e,["calling","count()","on",b.name]);f.onsuccess=function(b){a(Math.min(b.target.result,Math.max(0,d.limit-d.offset)))}},a)},sortBy:function(a,b){function c(a,b){return b?c(a[h[b]],b-1):a[k]}function d(a,b){var e=c(a,n),f=c(b,n);return e<f?-g:e>f?g:0}var e=this._ctx,g;B(function(){b([f(e)])});var h=a.split(".").reverse(),k=h[0],n=h.length-1;return g="next"===this._ctx.dir?1:-1,this.toArray(function(a){return a.sort(d)}).then(b)},toArray:function(a){var b=this._ctx;return B(function(){a([f(b)])}),
+this._read(function(a,c,d){var f=[];e(b,function(a){f.push(a)},function(){a(f)},c,d)},a)},offset:function(b){var c=this._ctx;return 0>=b?this:(c.offset+=b,c.or||c.algorithm||c.filter?a(c,function(){return 0>--b}):a(c,function(a,c){return 0===b?!0:1===b?(--b,!1):(c(function(){a.advance(b);b=0}),!1)}),this)},limit:function(b){return this._ctx.limit=Math.min(this._ctx.limit,b),a(this._ctx,function(a,c,d){return 0>=--b&&c(d),0<=b}),this},until:function(b,c){var d=this._ctx;return B(function(){b(f(d))}),
+a(this._ctx,function(a,d,e){return b(a.value)?(d(e),c):!0}),this},first:function(a){var b=this;return B(function(){a(f(b._ctx))}),this.limit(1).toArray(function(a){return a[0]}).then(a)},last:function(a){return this.reverse().first(a)},and:function(c){var d=this;return B(function(){c(f(d._ctx))}),a(this._ctx,function(a){return c(a.value)}),b(this._ctx,c),this},or:function(a){return new Y(this._ctx.table,a,this)},reverse:function(){return this._ctx.dir="prev"===this._ctx.dir?"next":"prev",this._ondirectionchange&&
+this._ondirectionchange(this._ctx.dir),this},desc:function(){return this.reverse()},eachKey:function(a){var b=this,c=this._ctx;return B(function(){a(f(b._ctx)[b._ctx.index])}),c.isPrimKey||(c.op="openKeyCursor"),this.each(function(b,c){a(c.key,c)})},eachUniqueKey:function(a){return this._ctx.unique="unique",this.eachKey(a)},keys:function(a){var b,c,d;return B(function(){a([f(c)[b._ctx.index]])}),b=this,c=this._ctx,c.isPrimKey||(c.op="openKeyCursor"),d=[],this.each(function(a,b){d.push(b.key)}).then(function(){return d}).then(a)},
+uniqueKeys:function(a){return this._ctx.unique="unique",this.keys(a)},firstKey:function(a){return this.limit(1).keys(function(a){return a[0]}).then(a)},lastKey:function(a){return this.reverse().firstKey(a)},distinct:function(){var b={};return a(this._ctx,function(a){a=a.primaryKey.toString();var c=b.hasOwnProperty(a);return b[a]=!0,!c}),this}}});e(ua).from(X).extend({modify:function(a){var b=this,c=this._ctx,e=c.table.hook,f=e.updating.fire,g=e.deleting.fire;return B(function(){"function"==typeof a&&
+a.call({value:c.table.schema.instanceTemplate},c.table.schema.instanceTemplate)}),this._write(function(e,k,n,u){function l(a){return a&&(r.push(a),fa.push(W)),k(new pa("Error modifying one or more objects",r,p,fa))}function E(){ja&&p+r.length===q&&(0<r.length?l():e(p))}var m,U,Ca,ea;"function"==typeof a?m=f===h&&g===h?a:function(b){var c=ba(b),d,e;if(!1===a.call(this,b))return!1;this.hasOwnProperty("value")?(d=La(c,this.value),e=f.call(this,d,this.primKey,c,u),e&&(b=this.value,Object.keys(e).forEach(function(a){J(b,
+a,e[a])}))):g.call(this,this.primKey,b,u)}:f===h?(U=Object.keys(a),Ca=U.length,m=function(b){for(var c,d,e=!1,f=0;f<Ca;++f)c=U[f],d=a[c],P(b,c)!==d&&(J(b,c,d),e=!0);return e}):(ea=a,a=qa(ea),m=function(b){var c=!1,e=f.call(this,a,this.primKey,ba(b),u);return e&&d(a,e),Object.keys(a).forEach(function(d){var e=a[d];P(b,d)!==e&&(J(b,d,e),c=!0)}),e&&(a=qa(ea)),c});var q=0,p=0,ja=!1,r=[],fa=[],W=null;b._iterate(function(a,b){var d,e,f;if(W=b.primaryKey,d={primKey:b.primaryKey,value:a},!1!==m.call(d,a))f=
+(e=!d.hasOwnProperty("value"))?b["delete"]():b.update(d.value),++q,f.onerror=G(function(a){if(r.push(a),fa.push(d.primKey),d.onerror)d.onerror(a);return E(),!0},e?["deleting",a,"from",c.table.name]:["modifying",a,"on",c.table.name]),f.onsuccess=function(){if(d.onsuccess)d.onsuccess(d.value);++p;E()};else if(d.onsuccess)d.onsuccess(d.value)},function(){ja=!0;E()},l,n)})},"delete":function(){return this.modify(function(){delete this.value})}});d(this,{Collection:X,Table:T,Transaction:va,Version:u,WhereClause:Y,
+WriteableCollection:ua,WriteableTable:ta});(function(){v.on("versionchange",function(){v.close();v.on("error").fire(new y("Database version changed by other database connection."))})})();ca.forEach(function(a){a(v)})}function h(){}function k(a){return a}function l(a,b){return a===k?b:function(c){return b(a(c))}}function m(a,b){return function(){a.apply(this,arguments);b.apply(this,arguments)}}function q(a,b){return a===h?b:function(){var d=a.apply(this,arguments),e,f,g;return d!==c&&(arguments[0]=
+d),e=this.onsuccess,f=this.onerror,delete this.onsuccess,delete this.onerror,g=b.apply(this,arguments),e&&(this.onsuccess=this.onsuccess?m(e,this.onsuccess):e),f&&(this.onerror=this.onerror?m(f,this.onerror):f),g!==c?g:d}}function p(a,b){return a===h?b:function(){var e=a.apply(this,arguments),f,g,h;return e!==c&&d(arguments[0],e),f=this.onsuccess,g=this.onerror,delete this.onsuccess,delete this.onerror,h=b.apply(this,arguments),f&&(this.onsuccess=this.onsuccess?m(f,this.onsuccess):f),g&&(this.onerror=
+this.onerror?m(g,this.onerror):g),e===c?h===c?c:h:h===c?e:d(e,h)}}function s(a,b){return a===h?b:function(){return!1===a.apply(this,arguments)?!1:b.apply(this,arguments)}}function w(a,b){return a===h?b:function(){return!1===b.apply(this,arguments)?!1:a.apply(this,arguments)}}function M(a,b){return a===h?b:function(){a.apply(this,arguments);b.apply(this,arguments)}}function O(a,b){return a===h?b:function(){var c=a.apply(this,arguments),d,e;return c&&"function"==typeof c.then?(d=this,e=arguments,c.then(function(){return b.apply(d,
+e)})):b.apply(this,arguments)}}function K(b){function c(a,b,f){if(Array.isArray(a))return e(a);if("object"==typeof a)return d(a);b||(b=s);f||(f=h);var n={subscribers:[],fire:f,subscribe:function(a){n.subscribers.push(a);n.fire=b(n.fire,a)},unsubscribe:function(a){n.subscribers=n.subscribers.filter(function(b){return b!==a});n.fire=n.subscribers.reduce(b,f)}};return g[a]=k[a]=n,n}function d(b){Object.keys(b).forEach(function(d){var e=b[d],f;if(Array.isArray(e))c(d,b[d][0],b[d][1]);else if("asap"===
+e)f=c(d,null,function(){var b=arguments;f.subscribers.forEach(function(c){x(function(){c.apply(a,b)})})}),f.subscribe=function(a){-1===f.subscribers.indexOf(a)&&f.subscribers.push(a)},f.unsubscribe=function(a){a=f.subscribers.indexOf(a);-1!==a&&f.subscribers.splice(a,1)};else throw Error("Invalid event config");})}function e(a){function b(){if(d)return!1;d=!0}var d=!1;a.forEach(function(a){c(a).subscribe(b)})}var f=arguments,g={},k=function(a,c){if(c){var d=[].slice.call(arguments,1),e=g[a];return e.subscribe.apply(e,
+d),b}if("string"==typeof a)return g[a]},l,m;k.addEventType=c;l=1;for(m=f.length;l<m;++l)c(f[l]);return k}function x(b){a.setImmediate?setImmediate(b):setTimeout(b,0)}function A(a){a=setTimeout(a,1E3);clearTimeout(a)}function I(a,b,c){return function(){var d=r.PSD;r.PSD=c;try{a.apply(this,arguments)}catch(e){b(e)}finally{r.PSD=d}}}function P(a,b){var d,e,f,g;if(a.hasOwnProperty(b))return a[b];if(!b)return a;if("string"!=typeof b){d=[];e=0;for(f=b.length;e<f;++e)g=P(a,b[e]),d.push(g);return d}return(d=
+b.indexOf("."),-1!==d)?(e=a[b.substr(0,d)],e===c?c:P(e,b.substr(d+1))):c}function J(a,b,d){var e,f,g,h;if(a&&b!==c)if("string"!=typeof b&&"length"in b){if(!("string"!=typeof d&&"length"in d))throw Error("Assertion failed");e=0;for(f=b.length;e<f;++e)J(a,b[e],d[e])}else e=b.indexOf("."),-1!==e?(f=b.substr(0,e),g=b.substr(e+1),""===g?d===c?delete a[f]:a[f]=d:(h=a[f],h||(h=a[f]={}),J(h,g,d))):d===c?delete a[b]:a[b]=d}function Ba(a,b){J(a,b,c)}function qa(a){var b={},c;for(c in a)a.hasOwnProperty(c)&&
+(b[c]=a[c]);return b}function ba(a){var b,c,d;if(!a||"object"!=typeof a)return a;if(Array.isArray(a))for(b=[],c=0,d=a.length;c<d;++c)b.push(ba(a[c]));else if(a instanceof Date)b=new Date,b.setTime(a.getTime());else for(c in b=a.constructor?Object.create(a.constructor.prototype):{},a)a.hasOwnProperty(c)&&(b[c]=ba(a[c]));return b}function La(a,b){var d={},e;for(e in a)a.hasOwnProperty(e)&&(b.hasOwnProperty(e)?a[e]!==b[e]&&JSON.stringify(a[e])!=JSON.stringify(b[e])&&(d[e]=b[e]):d[e]=c);for(e in b)b.hasOwnProperty(e)&&
+!a.hasOwnProperty(e)&&(d[e]=b[e]);return d}function ia(a){if("function"==typeof a)return new a;if(Array.isArray(a))return[ia(a[0])];if(a&&"object"==typeof a){var b={};return Aa(b,a),b}return a}function Aa(a,b){Object.keys(b).forEach(function(c){var d=ia(b[c]);a[c]=d})}function G(a,b){return function(c){var d=c&&c.target.error||Error(),e;return b&&(e=" occurred when "+b.map(function(a){switch(typeof a){case "function":return a();case "string":return a;default:return JSON.stringify(a)}}).join(" "),
+d.name?d.toString=function(){return d.name+e+(d.message?". "+d.message:"")}:d+=e),a(d),c&&(c.stopPropagation&&c.stopPropagation(),c.preventDefault&&c.preventDefault()),!1}}function Ka(a){try{throw a;}catch(b){return b}}function Ga(a){a.preventDefault()}function za(a){var b,c=g.dependencies.localStorage;if(!c)return a([]);try{b=JSON.parse(c.getItem("Dexie.DatabaseNames")||"[]")}catch(d){b=[]}a(b)&&c.setItem("Dexie.DatabaseNames",JSON.stringify(b))}function Z(a,b,c,d,e,f,g){this.name=a;this.keyPath=
+b;this.unique=c;this.multi=d;this.auto=e;this.compound=f;this.dotted=g;a="string"==typeof b?b:b&&"["+[].join.call(b,"+")+"]";this.src=(c?"&":"")+(d?"*":"")+(e?"++":"")+a}function ya(a,b,c,d){this.name=a;this.primKey=b||new Z;this.indexes=c||[new Z];this.instanceTemplate=d;this.mappedClass=null;this.idxByName=c.reduce(function(a,b){return a[b.name]=b,a},{})}function pa(a,b,c,d){this.name="ModifyError";this.failures=b;this.failedKeys=d;this.successCount=c;this.message=b.join("\n")}function xa(a){return 1===
+a.length?a[0]:a}function Fa(){var a=g.dependencies.indexedDB,b=a&&(a.getDatabaseNames||a.webkitGetDatabaseNames);return b&&b.bind(a)}var r=function(){function b(a){x.push([a,p.call(arguments,1)])}function c(){var b=x,d,e,f;x=[];d=0;for(e=b.length;d<e;++d)f=b[d],f[0].apply(a,f[1])}function d(a){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof a)throw new TypeError("not a function");this._value=this._state=null;this._deferreds=[];this._catched=
+!1;var b=this,c=!0;this._PSD=d.PSD;try{q(this,a,function(a){c?s(g,b,a):g(b,a)},function(a){return c?(s(k,b,a),!1):k(b,a)})}finally{c=!1}}function e(a,g){var h,k,l,m,q,p;if(null===a._state)a._deferreds.push(g);else{if(h=a._state?g.onFulfilled:g.onRejected,null===h)return(a._state?g.resolve:g.reject)(a._value);l=w;w=!1;s=b;try{m=d.PSD,d.PSD=a._PSD,k=h(a._value),a._state||k&&"function"==typeof k.then&&!1===k._state||f(a),g.resolve(k)}catch(B){if(q=g.reject(B),!q&&a.onuncatched)try{a.onuncatched(B)}catch(G){}}finally{if(d.PSD=
+m,l){do{for(;0<x.length;)c();if(p=A.pop(),p)try{p()}catch(I){}}while(0<A.length||0<x.length);s=r;w=!0}}}}function f(a){a._catched=!0;a._parent&&f(a._parent)}function g(a,b){var c=d.PSD;d.PSD=a._PSD;try{if(b===a)throw new TypeError("A promise cannot be resolved with itself.");!b||"object"!=typeof b&&"function"!=typeof b||"function"!=typeof b.then?(a._state=!0,a._value=b,l.call(a)):q(a,function(a,c){b.then(a,c)},function(b){g(a,b)},function(b){k(a,b)})}catch(e){k(e)}finally{d.PSD=c}}function k(a,b){var c=
+d.PSD;if(d.PSD=a._PSD,a._state=!1,a._value=b,l.call(a),!a._catched)try{if(a.onuncatched)a.onuncatched(a._value);d.on.error.fire(a._value)}catch(e){}return d.PSD=c,a._catched}function l(){for(var a=0,b=this._deferreds.length;a<b;a++)e(this,this._deferreds[a]);this._deferreds=[]}function m(a,b,c,d){this.onFulfilled="function"==typeof a?a:null;this.onRejected="function"==typeof b?b:null;this.resolve=c;this.reject=d}function q(a,b,c,d){var e=!1;try{b(function(a){e||(e=!0,c(a))},function(b){return e?a._catched:
+(e=!0,d(b))})}catch(f){return e?void 0:d(f)}}var p=[].slice,r="undefined"==typeof setImmediate?function(b){var c=arguments;setTimeout(function(){b.apply(a,p.call(c,1))},0)}:setImmediate,s=r,w=!0,x=[],A=[];return d.on=K(null,"error"),d.all=function(){var a=Array.prototype.slice.call(1===arguments.length&&Array.isArray(arguments[0])?arguments[0]:arguments);return new d(function(b,c){function d(f,g){try{if(g&&("object"==typeof g||"function"==typeof g)){var h=g.then;if("function"==typeof h){h.call(g,
+function(a){d(f,a)},c);return}}a[f]=g;0==--e&&b(a)}catch(k){c(k)}}var e,f;if(0===a.length)return b([]);e=a.length;for(f=0;f<a.length;f++)d(f,a[f])})},d.prototype.then=function(a,b){var c=this,f=new d(function(d,f){null===c._state?e(c,new m(a,b,d,f)):s(e,c,new m(a,b,d,f))});return f._PSD=this._PSD,f.onuncatched=this.onuncatched,f._parent=this,f},d.prototype._then=function(a,b){e(this,new m(a,b,h,h))},d.prototype["catch"]=function(a){if(1===arguments.length)return this.then(null,a);var b=arguments[0],
+c=arguments[1];return"function"==typeof b?this.then(null,function(a){return a instanceof b?c(a):d.reject(a)}):this.then(null,function(a){return a&&a.name===b?c(a):d.reject(a)})},d.prototype["finally"]=function(a){return this.then(function(b){return a(),b},function(b){return a(),d.reject(b)})},d.prototype.onuncatched=null,d.resolve=function(a){var b=new d(function(){});return b._state=!0,b._value=a,b},d.reject=function(a){var b=new d(function(){});return b._state=!1,b._value=a,b},d.race=function(a){return new d(function(b,
+c){a.map(function(a){a.then(b,c)})})},d.PSD=null,d.newPSD=function(a){var b=d.PSD;d.PSD=b?Object.create(b):{};try{return a()}finally{d.PSD=b}},d._rootExec=function(a){var d=w,e;w=!1;s=b;try{a()}finally{if(d){do{for(;0<x.length;)c();if(e=A.pop(),e)try{e()}catch(f){}}while(0<A.length||0<x.length);s=r;w=!0}}},d._tickFinalize=function(a){if(w)throw Error("Not in a virtual tick");A.push(a)},d}(),B=function(){},ca;e(pa).from(Error);g["delete"]=function(a){var b=new g(a);a=b["delete"]();return a.onblocked=
+function(a){b.on("blocked",a);return this},a};g.getDatabaseNames=function(a){return(new r(function(a,b){var c=Fa(),d;c?(d=c(),d.onsuccess=function(b){a([].slice.call(b.target.result,0))},d.onerror=G(b)):za(function(b){return a(b),!1})})).then(a)};g.defineClass=function(a){function b(a){a&&d(this,a)}return Aa(b.prototype,a),b};g.ignoreTransaction=function(a){return r.newPSD(function(){return r.PSD.trans=null,a()})};g.spawn=function(){return a.console&&console.warn("Dexie.spawn() is deprecated. Use Dexie.ignoreTransaction() instead."),
+g.ignoreTransaction.apply(this,arguments)};g.vip=function(a){return r.newPSD(function(){return r.PSD.letThrough=!0,a()})};Object.defineProperty(g,"currentTransaction",{get:function(){return r.PSD&&r.PSD.trans||null}});g.Promise=r;g.derive=e;g.extend=d;g.override=f;g.events=K;g.getByKeyPath=P;g.setByKeyPath=J;g.delByKeyPath=Ba;g.shallowClone=qa;g.deepClone=ba;g.addons=[];g.fakeAutoComplete=B;g.asap=x;g.ModifyError=pa;g.MultiModifyError=pa;g.IndexSpec=Z;g.TableSchema=ya;ca=a.idbModules&&a.idbModules.shimIndexedDB?
+a.idbModules:{};g.dependencies={indexedDB:ca.shimIndexedDB||a.indexedDB||a.mozIndexedDB||a.webkitIndexedDB||a.msIndexedDB,IDBKeyRange:ca.IDBKeyRange||a.IDBKeyRange||a.webkitIDBKeyRange,IDBTransaction:ca.IDBTransaction||a.IDBTransaction||a.webkitIDBTransaction,Error:a.Error||String,SyntaxError:a.SyntaxError||String,TypeError:a.TypeError||String,DOMError:a.DOMError||String,localStorage:null!=("undefined"!=typeof chrome&&null!==chrome?chrome.storage:void 0)?null:a.localStorage};g.version=1.1;b("Dexie",
+g);A(function(){B=A})}).apply(null,"function"==typeof define&&define.amd?[self||window,function(a,b){define(a,function(){return b})}]:"undefined"!=typeof global&&"undefined"!=typeof module&&module.exports?[global,function(a,b){module.exports=b}]:[self||window,function(a,b){(self||window)[a]=b}]);
