/**
* Copyright (C) 2017-2018 Regents of the University of California.
* @author: Jeff Thompson <[email protected]>
* @author: From ndn-cxx security https://github.com/named-data/ndn-cxx/blob/master/src/security/signing-info.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 Name = require('../name.js').Name; /** @ignore */
var PibIdentity = require('./pib/pib-identity.js').PibIdentity; /** @ignore */
var PibKey = require('./pib/pib-key.js').PibKey; /** @ignore */
var DigestAlgorithm = require('./security-types.js').DigestAlgorithm; /** @ignore */
var ValidityPeriod = require('./validity-period.js').ValidityPeriod;
/**
* SigningInfo holds the signing parameters passed to the KeyChain. A
* SigningInfo is invalid if the specified identity/key/certificate does not
* exist, or the PibIdentity or PibKey instance is not valid.
*
* The SigningInfo constructor has multiple forms:
* SigningInfo() - Create a default SigningInfo with
* SigningInfo.SignerType.NULL and an empty Name.
* SigningInfo(signerType, signerName) - Create a SigningInfo with the
* signerType and optional signer Name.
* Signinginfo(identity) - Create a SigningInfo of type
* SigningInfo.SignerType.ID according to the given PibIdentity, where the
* digest algorithm is set to DigestAlgorithm.SHA256.
* SigningInfo(key) - Create a SigningInfo of type SigningInfo.SignerType.KEY
* according to the given PibKey, where the digest algorithm is set to
* DigestAlgorithm.SHA256.
* SigningInfo(signingString) - Create a SigningInfo from its string
* representation, where the digest algorithm is set to DigestAlgorithm.SHA256.
* @param {number} signerType The type of signer as an int from the
* SigningInfo.SignerType enum.
* @param {Name} signerName The name of signer. The interpretation of the
* signerName differs based on the signerType. This copies the Name.
* @param {PibIdentity} identity An existing PibIdentity which is not copied.
* @param {PibKey} key An existing PibKey which is not copied.
* @param {string} signingString The representative signing string for the
* signing method, as follows:
* Default signing: "" (the empty string).
* Signing with the default certificate of the default key for the identity
* with the specified name:
* `id:/my-identity`.
* Signing with the default certificate of the key with the specified name:
* `key:/my-identity/ksk-1`.
* Signing with the certificate with the specified name:
* `cert:/my-identity/KEY/ksk-1/ID-CERT/%FD%01`.
* Signing with sha256 digest: `id:/localhost/identity/digest-sha256` (the
* value returned by getDigestSha256Identity()).
* @throws Error If the signingString format is invalid.
* @constructor
*/
var SigningInfo = function SigningInfo(arg1, arg2)
{
this.validityPeriod_ = new ValidityPeriod();
if (arg1 == undefined) {
this.reset(SigningInfo.SignerType.NULL);
this.digestAlgorithm_ = DigestAlgorithm.SHA256;
}
else if (typeof arg1 === 'number') {
var signerType = arg1;
this.reset(signerType);
if (arg2 != undefined)
this.name_ = new Name(arg2);
this.digestAlgorithm_ = DigestAlgorithm.SHA256;
}
else if (arg1 instanceof PibIdentity) {
this.digestAlgorithm_ = DigestAlgorithm.SHA256;
this.setPibIdentity(arg1);
}
else if (arg1 instanceof PibKey) {
this.digestAlgorithm_ = DigestAlgorithm.SHA256;
this.setPibKey(arg1);
}
else if (typeof arg1 === 'string') {
signingString = arg1;
this.reset(SigningInfo.SignerType.NULL);
this.digestAlgorithm_ = DigestAlgorithm.SHA256;
if (signingString == "")
return;
var iColon = signingString.indexOf(':');
if (iColon < 0)
throw new Error("Invalid signing string cannot represent SigningInfo");
var scheme = signingString.substring(0, iColon);
var nameArg = signingString.substring(iColon + 1);
if (scheme == "id") {
if (nameArg == SigningInfo.getDigestSha256Identity().toUri())
this.setSha256Signing();
else
this.setSigningIdentity(new Name(nameArg));
}
else if (scheme == "key")
this.setSigningKeyName(new Name(nameArg));
else if (scheme == "cert")
this.setSigningCertificateName(new Name(nameArg));
else
throw new Error("Invalid signing string scheme");
}
else
throw new Error("SigningInfo: Unrecognized type");
};
exports.SigningInfo = SigningInfo;
SigningInfo.SignerType = function SigningInfoSignerType() {};
/** No signer is specified. Use default settings or follow the trust schema. */
SigningInfo.SignerType.NULL = 0;
/** The signer is an identity. Use its default key and default certificate. */
SigningInfo.SignerType.ID = 1;
/** The signer is a key. Use its default certificate. */
SigningInfo.SignerType.KEY = 2;
/** The signer is a certificate. Use it directly. */
SigningInfo.SignerType.CERT = 3;
/** Use a SHA-256 digest. No signer needs to be specified. */
SigningInfo.SignerType.SHA256 = 4;
/**
* Set this to type SignerType.ID and an identity with name identityName. This
* does not change the digest algorithm.
* @param {Name} identityName The name of the identity. This copies the Name.
* @return {SigningInfo} This SigningInfo.
*/
SigningInfo.prototype.setSigningIdentity = function(identityName)
{
this.reset(SigningInfo.SignerType.ID);
this.name_ = new Name(identityName);
return this;
};
/**
* Set this to type SignerType.KEY and a key with name keyName. This does not
* change the digest algorithm.
* @param {Name} keyName The name of the key. This copies the Name.
* @return {SigningInfo} This SigningInfo.
*/
SigningInfo.prototype.setSigningKeyName = function(keyName)
{
this.reset(SigningInfo.SignerType.KEY);
this.name_ = new Name(keyName);
return this;
};
/**
* Set this to type SignerType.CERT and a certificate with name certificateName.
* This does not change the digest algorithm.
* @param {Name} certificateName The name of the certificate. This copies the
* Name.
* @return {SigningInfo} This SigningInfo.
*/
SigningInfo.prototype.setSigningCertificateName = function(certificateName)
{
this.reset(SigningInfo.SignerType.CERT);
this.name_ = new Name(certificateName);
return this;
};
/**
* Set this to type SignerType.SHA256, and set the digest algorithm to
* DigestAlgorithm.SHA256.
* @return {SigningInfo} This SigningInfo.
*/
SigningInfo.prototype.setSha256Signing = function()
{
this.reset(SigningInfo.SignerType.SHA256);
this.digestAlgorithm_ = DigestAlgorithm.SHA256;
return this;
};
/**
* Set this to type SignerType.ID according to the given PibIdentity. This does
* not change the digest algorithm.
* @param {PibIdentity} identity An existing PibIdentity which is not copied, or
* null. If this is null then use the default identity, otherwise use
* identity.getName().
* @return {SigningInfo} This SigningInfo.
*/
SigningInfo.prototype.setPibIdentity = function(identity)
{
this.reset(SigningInfo.SignerType.ID);
if (identity != null)
this.name_ = identity.getName();
this.identity_ = identity;
return this;
};
/**
* Set this to type SignerType.KEY according to the given PibKey. This does not
* change the digest algorithm.
* @param {PibKey} key An existing PibKey which is not copied, or null. If this
* is null then use the default key for the identity, otherwise use
* key.getName().
* @return {SigningInfo} This SigningInfo.
*/
SigningInfo.prototype.setPibKey = function(key)
{
this.reset(SigningInfo.SignerType.KEY);
if (key != null)
this.name_ = key.getName();
this.key_ = key;
return this;
};
/**
* Get the type of the signer.
* @return {number} The type of the signer, as an int from the
* SigningInfo.SignerType enum.
*/
SigningInfo.prototype.getSignerType = function() { return this.type_; };
/**
* Get the name of signer.
* @return {Name} The name of signer. The interpretation differs based on the
* signerType.
*/
SigningInfo.prototype.getSignerName = function() { return this.name_; };
/**
* Get the PibIdentity of the signer.
* @return {PibIdentity} The PibIdentity handler of the signer, or null if
* getSignerName() should be used to find the identity.
* @throws Error if the signer type is not SignerType.ID.
*/
SigningInfo.prototype.getPibIdentity = function()
{
if (this.type_ != SigningInfo.SignerType.ID)
throw new Error("getPibIdentity: The signer type is not SignerType.ID");
return this.identity_;
};
/**
* Get the PibKey of the signer.
* @return {PibKey} The PibKey handler of the signer, or null if
* getSignerName() should be used to find the key.
* @throws Error if the signer type is not SignerType.KEY.
*/
SigningInfo.prototype.getPibKey = function()
{
if (this.type_ != SigningInfo.SignerType.KEY)
throw new Error("getPibKey: The signer type is not SignerType.KEY");
return this.key_;
};
/**
* Set the digest algorithm for public key operations.
* @param {number} digestAlgorithm The digest algorithm, as an int from the
* DigestAlgorithm enum.
* @return {SigningInfo} This SigningInfo.
*/
SigningInfo.prototype.setDigestAlgorithm = function(digestAlgorithm)
{
this.digestAlgorithm_ = digestAlgorithm;
return this;
};
/**
* Get the digest algorithm for public key operations.
* @return {number} The digest algorithm, as an int from the DigestAlgorithm
* enum.
*/
SigningInfo.prototype.getDigestAlgorithm = function()
{
return this.digestAlgorithm_;
};
/**
* Set the validity period for the signature info.
* Note that the equivalent ndn-cxx method uses a semi-prepared SignatureInfo,
* but this method only uses the ValidityPeriod from the SignatureInfo.
* @param {ValidityPeriod} validityPeriod The validity period, which is copied.
* @return {SigningInfo} This SigningInfo.
*/
SigningInfo.prototype.setValidityPeriod = function(validityPeriod)
{
this.validityPeriod_ = new ValidityPeriod(validityPeriod);
return this;
};
/**
* Get the validity period for the signature info.
* Note that the equivalent ndn-cxx method uses a semi-prepared SignatureInfo,
* but this method only uses the ValidityPeriod from the SignatureInfo.
* @return {ValidityPeriod} The validity period.
*/
SigningInfo.prototype.getValidityPeriod = function()
{
return this.validityPeriod_;
};
/**
* Get the string representation of this SigningInfo.
* @return {string} The string representation.
*/
SigningInfo.prototype.toString = function()
{
if (this.type_ == SigningInfo.SignerType.NULL)
return "";
else if (this.type_ == SigningInfo.SignerType.ID)
return "id:" + this.getSignerName().toUri();
else if (this.type_ == SigningInfo.SignerType.KEY)
return "key:" + this.getSignerName().toUri();
else if (this.type_ == SigningInfo.SignerType.CERT)
return "cert:" + this.getSignerName().toUri();
else if (this.type_ == SigningInfo.SignerType.SHA256)
return "id:" + SigningInfo.getDigestSha256Identity().toUri();
else
// We don't expect this to happen.
throw new Error("Unknown signer type");
};
/**
* Get the localhost identity which indicates that the signature is generated
* using SHA-256.
* @return {Name} A new Name of the SHA-256 identity.
*/
SigningInfo.getDigestSha256Identity = function()
{
return new Name("/localhost/identity/digest-sha256");
};
/**
* Check and set the signerType, and set others to default values. This does NOT
* reset the digest algorithm.
* @param {number} signerType The type of signer as an int from the
* SigningInfo.SignerType enum.
*/
SigningInfo.prototype.reset = function(signerType)
{
if (!(signerType == SigningInfo.SignerType.NULL ||
signerType == SigningInfo.SignerType.ID ||
signerType == SigningInfo.SignerType.KEY ||
signerType == SigningInfo.SignerType.CERT ||
signerType == SigningInfo.SignerType.SHA256))
throw new Error("SigningInfo: The signerType is not valid");
this.type_ = signerType;
this.name_ = new Name();
this.identity_ = null;
this.key_ = null;
this.validityPeriod_ = new ValidityPeriod();
};