Source code for pyndn.security.signing_info

# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2017-2019 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/ndn-cxx/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.

"""
This module defines the SigningInfo class which 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.
"""

from pyndn.name import Name
from pyndn.security.security_types import DigestAlgorithm
from pyndn.validity_period import ValidityPeriod
from pyndn.security.pib.pib_identity import PibIdentity
from pyndn.security.pib.pib_key import PibKey

[docs]class SigningInfo(object): """ The SigningInfo constructor has multiple forms: SigningInfo() - Create a default SigningInfo with SigningInfo.SignerType.NULL (which will cause KeyChain.sign to use the default identity) and an empty Name. SigningInfo(signingInfo) - Create a SigningInfo as a copy of the given signingInfo (taking a pointer to the given signingInfo PibIdentity and PibKey without copying). 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 SigningInfo signingInfo: The SigningInfo to copy. :param signerType: The type of signer. :type signerType: 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 str 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()). :raises ValueError: If the signingString format is invalid. """ def __init__(self, arg1 = None, arg2 = None): self._validityPeriod = ValidityPeriod() if arg1 is None: self.reset(SigningInfo.SignerType.NULL) self._digestAlgorithm = DigestAlgorithm.SHA256 elif isinstance(arg1, SigningInfo): # The copy constructor. signingInfo = arg1 self._type = signingInfo._type self._name = Name(signingInfo._name) self._identity = signingInfo._identity self._key = signingInfo._key self._digestAlgorithm = signingInfo._digestAlgorithm self._validityPeriod = ValidityPeriod(signingInfo._validityPeriod) elif type(arg1) is int: signerType = arg1 self.reset(signerType) if not (arg2 is None): self._name = Name(arg2) self._digestAlgorithm = DigestAlgorithm.SHA256 elif isinstance(arg1, PibIdentity): self._digestAlgorithm = DigestAlgorithm.SHA256 self.setPibIdentity(arg1) elif isinstance(arg1, PibKey): self._digestAlgorithm = DigestAlgorithm.SHA256 self.setPibKey(arg1) elif type(arg1) is str: signingString = arg1 self.reset(SigningInfo.SignerType.NULL) self._digestAlgorithm = DigestAlgorithm.SHA256 if signingString == "": return try: iColon = signingString.index(':') except: raise ValueError( "Invalid signing string cannot represent SigningInfo") scheme = signingString[0 : iColon] nameArg = signingString[iColon + 1:] if scheme == "id": if nameArg == SigningInfo.getDigestSha256Identity().toUri(): self.setSha256Signing() else: self.setSigningIdentity(Name(nameArg)) elif scheme == "key": self.setSigningKeyName(Name(nameArg)) elif scheme == "cert": self.setSigningCertificateName(Name(nameArg)) else: raise ValueError("Invalid signing string scheme") else: raise ValueError("SigningInfo: Unrecognized type")
[docs] class SignerType(object): # No signer is specified. Use default settings or follow the trust schema. NULL = 0 # The signer is an identity. Use its default key and default certificate. ID = 1 # The signer is a key. Use its default certificate. KEY = 2 # The signer is a certificate. Use it directly. CERT = 3 # Use a SHA-256 digest. No signer needs to be specified. SHA256 = 4
[docs] def setSigningIdentity(self, identityName): """ 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: This SigningInfo. :rtype: SigningInfo """ self.reset(SigningInfo.SignerType.ID) self._name = Name(identityName) return self
[docs] def setSigningKeyName(self, keyName): """ 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: This SigningInfo. :rtype: SigningInfo """ self.reset(SigningInfo.SignerType.KEY) self._name = Name(keyName) return self
[docs] def setSigningCertificateName(self, certificateName): """ 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: This SigningInfo. :rtype: SigningInfo """ self.reset(SigningInfo.SignerType.CERT) self._name = Name(certificateName) return self
[docs] def setSha256Signing(self): """ Set this to type SignerType.SHA256, and set the digest algorithm to DigestAlgorithm.SHA256. :return: This SigningInfo. :rtype: SigningInfo """ self.reset(SigningInfo.SignerType.SHA256) self._digestAlgorithm = DigestAlgorithm.SHA256 return self
[docs] def setPibIdentity(self, identity): """ 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 None. If this is None then use the default identity, otherwise use identity.getName(). :return: This SigningInfo. :rtype: SigningInfo """ self.reset(SigningInfo.SignerType.ID) if identity != None: self._name = identity.getName() self._identity = identity return self
[docs] def setPibKey(self, key): """ 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 None. If this is None then use the default key for the identity, otherwise use key.getName(). :return: This SigningInfo. :rtype: SigningInfo """ self.reset(SigningInfo.SignerType.KEY) if key != None: self._name = key.getName() self._key = key return self
[docs] def getSignerType(self): """ Get the type of the signer. :return:The type of the signer :rtype: int from the SigningInfo.SignerType enum """ return self._type
[docs] def getSignerName(self): """ Get the name of signer. :return: The name of signer. The interpretation differs based on the signerType. :rtype: Name """ return self._name
[docs] def getPibIdentity(self): """ Get the PibIdentity of the signer. :return: The PibIdentity handler of the signer, or None if getSignerName() should be used to find the identity. :rtype: PibIdentity :raises ValueError: If the signer type is not SignerType.ID. """ if self._type != SigningInfo.SignerType.ID: raise ValueError( "getPibIdentity: The signer type is not SignerType.ID") return self._identity
[docs] def getPibKey(self): """ Get the PibKey of the signer. :return: The PibKey handler of the signer, or None if getSignerName() should be used to find the key. :rtype: PibKey :raise ValueError: If the signer type is not SignerType.KEY. """ if self._type != SigningInfo.SignerType.KEY: raise ValueError( "getPibKey: The signer type is not SignerType.KEY") return self._key
[docs] def setDigestAlgorithm(self, digestAlgorithm): """ Set the digest algorithm for public key operations. :param digestAlgorithm: The digest algorithm. :type digestAlgorithm: int from the DigestAlgorithm enum :return: This SigningInfo. :rtype: SigningInfo """ self._digestAlgorithm = digestAlgorithm return self
[docs] def getDigestAlgorithm(self): """ Get the digest algorithm for public key operations. :return: The digest algorithm. :rtype: int from the DigestAlgorithm enum """ return self._digestAlgorithm
[docs] def setValidityPeriod(self, validityPeriod): """ 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: This SigningInfo. :rtype: SigningInfo """ self._validityPeriod = ValidityPeriod(validityPeriod) return self
[docs] def getValidityPeriod(self): """ 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: The validity period. :rtype: ValidityPeriod """ return self._validityPeriod
def __str__(self): """ Get the string representation of this SigningInfo. :return: The string representation. :rtype: str """ if self._type == SigningInfo.SignerType.NULL: return "" elif self._type == SigningInfo.SignerType.ID: return "id:" + self.getSignerName().toUri() elif self._type == SigningInfo.SignerType.KEY: return "key:" + self.getSignerName().toUri() elif self._type == SigningInfo.SignerType.CERT: return "cert:" + self.getSignerName().toUri() elif self._type == SigningInfo.SignerType.SHA256: return "id:" + SigningInfo.getDigestSha256Identity().toUri() else: # We don't expect this to happen. raise ValueError("Unknown signer type")
[docs] @staticmethod def getDigestSha256Identity(): """ Get the localhost identity which indicates that the signature is generated using SHA-256. :return: A new Name of the SHA-256 identity. :rtype: Name """ return Name("/localhost/identity/digest-sha256")
[docs] def reset(self, signerType): """ Check and set the signerType, and set others to default values. This does NOT reset the digest algorithm. :param signerType: The type of signer. :type signerType: int from the SigningInfo.SignerType enum """ if (not (signerType == SigningInfo.SignerType.NULL or signerType == SigningInfo.SignerType.ID or signerType == SigningInfo.SignerType.KEY or signerType == SigningInfo.SignerType.CERT or signerType == SigningInfo.SignerType.SHA256)): raise ValueError("SigningInfo: The signerType is not valid") self._type = signerType self._name = Name() self._identity = None self._key = None self._validityPeriod = ValidityPeriod()