Source: security/certificate/identity-certificate.js

/**
 * 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.
 * @returns {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.
 * @returns {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());
};