Example #1
0
    def addMember(self, memberCertificate):
        """
        Authorize a member identified by memberCertificate to decrypt data under
        the policy.

        :param CertificateV2 memberCertificate: The certificate that identifies
          the member to authorize.
        :return: The published KDK Data packet.
        :rtype: Data
        """
        kdkName = Name(self._nacKey.getIdentityName())
        kdkName.append(EncryptorV2.NAME_COMPONENT_KDK).append(
            # key-id
            self._nacKey.getName().get(-1)).append(
                EncryptorV2.NAME_COMPONENT_ENCRYPTED_BY).append(
                    memberCertificate.getKeyName())

        secretLength = 32
        secret = bytearray(secretLength)
        for i in range(secretLength):
            secret[i] = _systemRandom.randint(0, 0xff)
        # To be compatible with OpenSSL which uses a null-terminated string,
        # replace each 0 with 1. And to be compatible with the Java security
        # library which interprets the secret as a char array converted to UTF8,
        # limit each byte to the ASCII range 1 to 127.
        for i in range(secretLength):
            if secret[i] == 0:
                secret[i] = 1

            secret[i] &= 0x7f

        kdkSafeBag = self._keyChain.exportSafeBag(
            self._nacKey.getDefaultCertificate(),
            Blob(secret, False).toBytes())

        memberKey = PublicKey(memberCertificate.getPublicKey())

        encryptedContent = EncryptedContent()
        encryptedContent.setPayload(kdkSafeBag.wireEncode())
        encryptedContent.setPayloadKey(
            memberKey.encrypt(
                Blob(secret, False).toBytes(), EncryptAlgorithmType.RsaOaep))

        kdkData = Data(kdkName)
        kdkData.setContent(encryptedContent.wireEncodeV2())
        # FreshnessPeriod can serve as a soft access control for revoking access.
        kdkData.getMetaInfo().setFreshnessPeriod(
            AccessManagerV2.DEFAULT_KDK_FRESHNESS_PERIOD_MS)
        self._keyChain.sign(kdkData, SigningInfo(self._identity))

        self._storage.insert(kdkData)

        return kdkData
Example #2
0
    def _makeSelfSignedCertificate(keyName, privateKeyBag, publicKeyEncoding,
                                   password, digestAlgorithm, wireFormat):
        certificate = CertificateV2()

        # Set the name.
        now = Common.getNowMilliseconds()
        certificateName = Name(keyName)
        certificateName.append("self").appendVersion(int(now))
        certificate.setName(certificateName)

        # Set the MetaInfo.
        certificate.getMetaInfo().setType(ContentType.KEY)
        # Set a one-hour freshness period.
        certificate.getMetaInfo().setFreshnessPeriod(3600 * 1000.0)

        # Set the content.
        publicKey = PublicKey(publicKeyEncoding)
        certificate.setContent(publicKey.getKeyDer())

        # Create a temporary in-memory Tpm and import the private key.
        tpm = Tpm("", "", TpmBackEndMemory())
        tpm._importPrivateKey(keyName, privateKeyBag.toBytes(), password)

        # Set the signature info.
        if publicKey.getKeyType() == KeyType.RSA:
            certificate.setSignature(Sha256WithRsaSignature())
        elif publicKey.getKeyType() == KeyType.EC:
            certificate.setSignature(Sha256WithEcdsaSignature())
        else:
            raise ValueError("Unsupported key type")
        signatureInfo = certificate.getSignature()
        KeyLocator.getFromSignature(signatureInfo).setType(
            KeyLocatorType.KEYNAME)
        KeyLocator.getFromSignature(signatureInfo).setKeyName(keyName)

        # Set a 20-year validity period.
        ValidityPeriod.getFromSignature(signatureInfo).setPeriod(
            now, now + 20 * 365 * 24 * 3600 * 1000.0)

        # Encode once to get the signed portion.
        encoding = certificate.wireEncode(wireFormat)
        signatureBytes = tpm.sign(encoding.toSignedBytes(), keyName,
                                  digestAlgorithm)
        signatureInfo.setSignature(signatureBytes)

        # Encode again to include the signature.
        certificate.wireEncode(wireFormat)

        return certificate
Example #3
0
    def _makeSelfSignedCertificate(
      keyName, privateKeyBag, publicKeyEncoding, password, digestAlgorithm,
      wireFormat):
        certificate = CertificateV2()

        # Set the name.
        now = Common.getNowMilliseconds()
        certificateName = Name(keyName)
        certificateName.append("self").appendVersion(int(now))
        certificate.setName(certificateName)

        # Set the MetaInfo.
        certificate.getMetaInfo().setType(ContentType.KEY)
        # Set a one-hour freshness period.
        certificate.getMetaInfo().setFreshnessPeriod(3600 * 1000.0)

        # Set the content.
        publicKey = PublicKey(publicKeyEncoding)
        certificate.setContent(publicKey.getKeyDer())

        # Create a temporary in-memory Tpm and import the private key.
        tpm = Tpm("", "", TpmBackEndMemory())
        tpm._importPrivateKey(keyName, privateKeyBag.toBytes(), password)

        # Set the signature info.
        if publicKey.getKeyType() == KeyType.RSA:
            certificate.setSignature(Sha256WithRsaSignature())
        elif publicKey.getKeyType() == KeyType.EC:
            certificate.setSignature(Sha256WithEcdsaSignature())
        else:
            raise ValueError("Unsupported key type")
        signatureInfo = certificate.getSignature()
        KeyLocator.getFromSignature(signatureInfo).setType(KeyLocatorType.KEYNAME)
        KeyLocator.getFromSignature(signatureInfo).setKeyName(keyName)

        # Set a 20-year validity period.
        ValidityPeriod.getFromSignature(signatureInfo).setPeriod(
          now, now + 20 * 365 * 24 * 3600 * 1000.0)

        # Encode once to get the signed portion.
        encoding = certificate.wireEncode(wireFormat)
        signatureBytes = tpm.sign(encoding.toSignedBytes(), keyName,
          digestAlgorithm)
        signatureInfo.setSignature(signatureBytes)

        # Encode again to include the signature.
        certificate.wireEncode(wireFormat)

        return certificate
Example #4
0
    def verifySignature(signature, signedBlob, publicKeyDer):
        """
        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. This is ignored if the signature type does not require a
          public key.
        :return: True if the signature verifies, False if not.
        :rtype: bool
        :raises: SecurityException if the signature type is not recognized or if
          publicKeyDer can't be decoded.
        """
        if (isinstance(signature, Sha256WithRsaSignature)
                or isinstance(signature, Sha256WithEcdsaSignature)):
            if publicKeyDer.isNull():
                return False
            return VerificationHelpers.verifySignature(
                signedBlob.toSignedBytes(), signature.getSignature(),
                PublicKey(publicKeyDer), DigestAlgorithm.SHA256)
        elif isinstance(signature, DigestSha256Signature):
            return VerificationHelpers.verifyDigest(signedBlob.toSignedBytes(),
                                                    signature.getSignature(),
                                                    DigestAlgorithm.SHA256)
        else:
            raise SecurityException(
                "PolicyManager.verify: Signature type is unknown")
Example #5
0
 def __init__(self, other=None):
     """
     Create a new certificate, optionally copying the
     contents of another Data object.
     :param other: (optional) A Data packet to copy the content from
     :type other: Data
     """
     super(Certificate,self).__init__(other)
     self._subjectDescriptionList = []
     self._extensionList = []
     if isinstance(other, Data):
         self.decode()
     else:
         self._notBefore = 1e37
         self._notAfter = -1e37
         self._publicKey = PublicKey()
Example #6
0
    def __init__(self, keyName, arg2, arg3 = None):
        self._defaultCertificate = None

        if isinstance(arg2, PibImpl):
            # PibKeyImpl(keyName, pibImpl)
            pibImpl = arg2

            self._identityName = PibKey.extractIdentityFromKeyName(keyName)
            self._keyName = Name(keyName)
            self._certificates = PibCertificateContainer(keyName, pibImpl)
            self._pibImpl = pibImpl

            if pibImpl == None:
                raise ValueError("The pibImpl is None")

            self._keyEncoding = self._pibImpl.getKeyBits(self._keyName)

            try:
                publicKey = PublicKey(self._keyEncoding)
            except:
                # We don't expect this since we just fetched the encoding.
                raise Pib.Error("Error decoding public key")

            self._keyType = publicKey.getKeyType()
        else:
            # PibKeyImpl(keyName, keyEncoding, pibImpl)
            keyEncoding = arg2
            pibImpl = arg3

            self._identityName = PibKey.extractIdentityFromKeyName(keyName)
            self._keyName = Name(keyName)
            self._keyEncoding = Blob(keyEncoding, True)
            self._certificates = PibCertificateContainer(keyName, pibImpl)
            self._pibImpl = pibImpl

            if pibImpl == None:
                raise ValueError("The pibImpl is None")

            try:
                publicKey = PublicKey(self._keyEncoding)
                self._keyType = publicKey.getKeyType()
            except:
                raise ValueError("Invalid key encoding")

            self._pibImpl.addKey(self._identityName, self._keyName, keyEncoding)
Example #7
0
    def decode(self):
        """
        Populates the fields by decoding DER data from the Content.
        """
        root = DerNode.parse(self.getContent())

        # we need to ensure that there are:
        #   validity (notBefore, notAfter)
        #   subject list
        #   public key
        #   (optional) extension list

        rootChildren = root.getChildren()
        # 1st: validity info
        validityChildren = DerNode.getSequence(rootChildren, 0).getChildren()
        self._notBefore = validityChildren[0].toVal()
        self._notAfter = validityChildren[1].toVal()

        # 2nd: subjectList
        subjectChildren = DerNode.getSequence(rootChildren, 1).getChildren()
        for sd in subjectChildren:
            descriptionChildren = sd.getChildren()
            oidStr = descriptionChildren[0].toVal()
            value = descriptionChildren[1].toVal()

            subjectDesc = CertificateSubjectDescription(oidStr, value)
            self.addSubjectDescription(subjectDesc)

        # 3rd: public key
        publicKeyInfo = rootChildren[2].encode()
        self._publicKey = PublicKey(publicKeyInfo)

        if len(rootChildren) > 3:
            extensionChildren = DerNode.getSequence(rootChildren,
                                                    3).getChildren()
            for extInfo in extensionChildren:
                children = extInfo.getChildren()
                oidStr = children[0].toVal()
                isCritical = children[1].toVal()
                value = children[2].toVal()
                extension = CertificateExtension(oidStr, isCritical, value)
                self.addExtension(extension)
 def getPublicKey(self, keyName):
     """
     Get the public key with the specified name.
     
     :param Name keyName: The name of the key.
     :return: The public key.
     :rtype: PublicKey
     """
     return PublicKey.fromDer(
       self._identityStorage.getKeyType(keyName),
       self._identityStorage.getKey(keyName))
Example #9
0
    def encrypt(keyBits, plainData, params):
        """
        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: The encrypted data.
        :rtype: Blob
        """
        return PublicKey(keyBits).encrypt(plainData, params.getAlgorithmType())
Example #10
0
    def _makeAndPublishCkData(self, onError):
        """
        Make a CK Data packet for _ckName encrypted by the KEK in _kekData and
        insert it in the _storage.

        :param onError: On failure, this calls onError(errorCode, message) where
          errorCode is from EncryptError.ErrorCode, and message is an error
          string.
        :type onError: function object
        :return: True on success, else False.
        :rtype: bool
        """
        try:
            kek = PublicKey(self._kekData.getContent())

            content = EncryptedContent()
            content.setPayload(
                kek.encrypt(Blob(self._ckBits, False),
                            EncryptAlgorithmType.RsaOaep))

            ckData = Data(
                Name(self._ckName).append(
                    EncryptorV2.NAME_COMPONENT_ENCRYPTED_BY).append(
                        self._kekData.getName()))
            ckData.setContent(content.wireEncodeV2())
            # FreshnessPeriod can serve as a soft access control for revoking access.
            ckData.getMetaInfo().setFreshnessPeriod(
                EncryptorV2.DEFAULT_CK_FRESHNESS_PERIOD_MS)
            self._keyChain.sign(ckData, self._ckDataSigningInfo)
            self._storage.insert(ckData)

            logging.getLogger(__name__).info("Publishing CK data: " +
                                             ckData.getName().toUri())
            return True
        except Exception as ex:
            onError(
                EncryptError.ErrorCode.EncryptionFailure,
                "Failed to encrypt generated CK with KEK " +
                self._kekData.getName().toUri())
            return False
Example #11
0
    def setPublicKeyForKeyName(self, keyName, keyType, publicKeyDer):
        """
        Set the public key for the keyName.

        :param Name keyName: The key name.
        :param keyType: The KeyType, such as KeyType.RSA.
        :type keyType: an int from KeyType
        :param publicKeyDer: The public key DER byte array.
        :type publicKeyDer: str, or an array type with int elements which is
          converted to str
        """
        self._publicKeyStore[keyName.toUri()] = PublicKey(
            Blob(publicKeyDer, True))
    def setPublicKeyForKeyName(self, keyName, keyType, publicKeyDer):
        """
        Set the public key for the keyName.

        :param Name keyName: The key name.
        :param keyType: The KeyType, such as KeyType.RSA.
        :type keyType: an int from KeyType
        :param publicKeyDer: The public key DER byte array.
        :type publicKeyDer: str, or an array type with int elements which is
          converted to str
        """
        self._publicKeyStore[keyName.toUri()] = PublicKey.fromDer(
          keyType, Blob(publicKeyDer, True))
Example #13
0
    def _makeAndPublishCkData(self, onError):
        """
        Make a CK Data packet for _ckName encrypted by the KEK in _kekData and
        insert it in the _storage.

        :param onError: On failure, this calls onError(errorCode, message) where
          errorCode is from EncryptError.ErrorCode, and message is an error
          string.
        :type onError: function object
        :return: True on success, else False.
        :rtype: bool
        """
        try:
            kek = PublicKey(self._kekData.getContent())

            content = EncryptedContent()
            content.setPayload(kek.encrypt
              (Blob(self._ckBits, False), EncryptAlgorithmType.RsaOaep))

            ckData = Data(
              Name(self._ckName).append(EncryptorV2.NAME_COMPONENT_ENCRYPTED_BY)
               .append(self._kekData.getName()))
            ckData.setContent(content.wireEncodeV2())
            # FreshnessPeriod can serve as a soft access control for revoking access.
            ckData.getMetaInfo().setFreshnessPeriod(
              EncryptorV2.DEFAULT_CK_FRESHNESS_PERIOD_MS)
            self._keyChain.sign(ckData, self._ckDataSigningInfo)
            self._storage.insert(ckData)

            logging.getLogger(__name__).info("Publishing CK data: " +
              ckData.getName().toUri())
            return True
        except Exception as ex:
            onError(EncryptError.ErrorCode.EncryptionFailure,
              "Failed to encrypt generated CK with KEK " +
              self._kekData.getName().toUri())
            return False
Example #14
0
 def __init__(self, other=None):
     """
     Create a new certificate, optionally copying the
     contents of another Data object.
     :param other: (optional) A Data packet to copy the content from
     :type other: Data
     """
     super(Certificate,self).__init__(other)
     self._subjectDescriptionList = []
     self._extensionList = []
     if isinstance(other, Data):
         self.decode()
     else:
         self._notBefore = 1e37
         self._notAfter = -1e37
         self._publicKey = PublicKey()
Example #15
0
    def getPublicKey(self, keyName):
        """
        Get the public key with the keyName.

        :param Name keyName: The name of public key.
        :return: The public key.
        :rtype: PublicKey
        """
        keyURI = keyName.toUri()

        if not self.doesKeyExist(keyName, KeyClass.PUBLIC):
            raise SecurityException("Public key doesn't exist")

        base64Content = None
        with open(self.nameTransform(keyURI, ".pub")) as keyFile:
            base64Content = keyFile.read()
        der = base64.b64decode(base64Content)

        return PublicKey(Blob(der, False))
Example #16
0
    def decode(self):
        """
        Populates the fields by decoding DER data from the Content.
        """
        root = DerNode.parse(self.getContent())

        # we need to ensure that there are:
        #   validity (notBefore, notAfter)
        #   subject list
        #   public key
        #   (optional) extension list

        rootChildren = root.getChildren()
        # 1st: validity info
        validityChildren = DerNode.getSequence(rootChildren, 0).getChildren()
        self._notBefore = validityChildren[0].toVal()
        self._notAfter = validityChildren[1].toVal()

        # 2nd: subjectList
        subjectChildren = DerNode.getSequence(rootChildren, 1).getChildren()
        for sd in subjectChildren:
            descriptionChildren = sd.getChildren()
            oidStr = descriptionChildren[0].toVal()
            value = descriptionChildren[1].toVal()

            subjectDesc = CertificateSubjectDescription(oidStr, value)
            self.addSubjectDescription(subjectDesc)

        # 3rd: public key
        publicKeyInfo = rootChildren[2].encode()
        self._publicKey = PublicKey(publicKeyInfo)

        if len(rootChildren) > 3:
            extensionChildren = DerNode.getSequence(rootChildren, 3).getChildren()
            for extInfo in extensionChildren:
                children = extInfo.getChildren()
                oidStr = children[0].toVal()
                isCritical = children[1].toVal()
                value = children[2].toVal()
                extension = CertificateExtension(oidStr, isCritical, value)
                self.addExtension(extension)
    def generateKeyPair(self, keyName, params):
        """
        Generate a pair of asymmetric keys.

        :param Name keyName: The name of the key pair.
        :param KeyParams params: The parameters of the key.
        """
        privateKey = None
        try:
            privateKey = TpmPrivateKey.generatePrivateKey(params)
        except Exception as ex:
            raise SecurityException("Error in generatePrivateKey: " + str(ex))

        publicKeyDer = None
        try:
            publicKeyDer = privateKey.derivePublicKey()
        except Exception as ex:
            raise SecurityException("Error in derivePublicKey: " + str(ex))

        self._privateKeyStore[keyName.toUri()] = privateKey
        self._publicKeyStore[keyName.toUri()] = PublicKey(publicKeyDer)
    def getPublicKey(self, keyName):
        """
        Get the public key with the keyName.

        :param Name keyName: The name of public key.
        :return: The public key.
        :rtype: PublicKey
        """
        keyURI = keyName.toUri()

        if not self.doesKeyExist(keyName, KeyClass.PUBLIC):
            raise SecurityException(
              "Public key doesn't exist")

        base64Content = None
        with open(self.nameTransform(keyURI, ".pub")) as keyFile:
            base64Content = keyFile.read()
        der = base64.b64decode(base64Content)
        if not type(der) is str:
            der = "".join(map(chr, der))

        return PublicKey.fromDer(KeyType.RSA, Blob(der, False))
Example #19
0
    def __init__(self, keyName, arg2, arg3=None):
        self._defaultCertificate = None

        if isinstance(arg2, PibImpl):
            # PibKeyImpl(keyName, pibImpl)
            pibImpl = arg2

            self._identityName = PibKey.extractIdentityFromKeyName(keyName)
            self._keyName = Name(keyName)
            self._certificates = PibCertificateContainer(keyName, pibImpl)
            self._pibImpl = pibImpl

            if pibImpl == None:
                raise ValueError("The pibImpl is None")

            self._keyEncoding = self._pibImpl.getKeyBits(self._keyName)

            try:
                publicKey = PublicKey(self._keyEncoding)
            except:
                # We don't expect this since we just fetched the encoding.
                raise Pib.Error("Error decoding public key")

            self._keyType = publicKey.getKeyType()
        else:
            # PibKeyImpl(keyName, keyEncoding, pibImpl)
            keyEncoding = arg2
            pibImpl = arg3

            self._identityName = PibKey.extractIdentityFromKeyName(keyName)
            self._keyName = Name(keyName)
            self._keyEncoding = Blob(keyEncoding, True)
            self._certificates = PibCertificateContainer(keyName, pibImpl)
            self._pibImpl = pibImpl

            if pibImpl == None:
                raise ValueError("The pibImpl is None")

            try:
                publicKey = PublicKey(self._keyEncoding)
                self._keyType = publicKey.getKeyType()
            except:
                raise ValueError("Invalid key encoding")

            self._pibImpl.addKey(self._identityName, self._keyName,
                                 keyEncoding)
Example #20
0
class Certificate(Data):
    epochStart = datetime(1970,1,1)
    def __init__(self, other=None):
        """
        Create a new certificate, optionally copying the
        contents of another Data object.
        :param other: (optional) A Data packet to copy the content from
        :type other: Data
        """
        super(Certificate,self).__init__(other)
        self._subjectDescriptionList = []
        self._extensionList = []
        if isinstance(other, Data):
            self.decode()
        else:
            self._notBefore = 1e37
            self._notAfter = -1e37
            self._publicKey = PublicKey()

    def isTooEarly(self):
        """
        Check if the certificate start date is in the future
        :return: True if the certificate cannot be used yet
        :rtype: boolean
        """

        secondsSince1970 = (datetime.now() - self.epochStart).total_seconds
        if secondsSince1970 < self.getNotBefore()/1000:
            return True
        return False

    def isTooLate(self):
        """
        Check if the certificate end date is in the past
        :return: True if the certificate has expired
        :rtype: boolean
        """
        secondsSince1970 = (datetime.now() - self.epochStart).total_seconds
        if secondsSince1970 > self.getNotAfter()/1000:
            return True
        return False

    def isInValidityPeriod(self, time):
        return self.getSignature().getValidityPeriod().isValid(time)

    def __str__(self):
        s = "Certificate name:\n"
        s += "  "+self.getName().toUri()+"\n"
        s += "Validity:\n"

        dateFormat = "%Y%m%dT%H%M%S"
        notBeforeStr = datetime.utcfromtimestamp(self.getNotBefore()/1000).strftime(dateFormat)
        notAfterStr = datetime.utcfromtimestamp(self.getNotAfter()/1000).strftime(dateFormat)

        s += "  NotBefore: " + notBeforeStr+"\n"
        s += "  NotAfter: " + notAfterStr + "\n"
        for sd in self._subjectDescriptionList:
            s += "Subject Description:\n"
            s += "  " + str(sd.getOid()) + ": " + sd.getValue().toRawStr() + "\n"

        s += "Public key bits:\n"
        keyDer = self.getPublicKeyDer()
        encodedKey = base64.b64encode(keyDer.toBytes())
        for idx in range(0, len(encodedKey), 64):
            # Use Blob to convert to a str.
            s += Blob(encodedKey[idx:idx+64], False).toRawStr() + "\n"


        if len(self._extensionList) > 0:
            s += "Extensions:\n"
            for ext in self._extensionList:
                s += "  OID: "+ext.getOid()+"\n"
                s += "  Is critical: " + ('Y' if ext.isCritical() else 'N') + "\n"

                s += "  Value: " + str(ext.getValue()).encode('hex') + "\n"

        return s


    def addSubjectDescription(self, descr):
        """
        Add a subject description field to the certificate.
        :param descr: The CertificateSubjectDescription object to add
        """
        self._subjectDescriptionList.append(descr)

    def addExtension(self, ext):
        """
        Add an extension field to the certificate.
        :param ext: Th CertificateExtension object to add
        """
        self._extensionList.append(ext)

    def toDer(self):
        """
        Encode the certificate fields in DER format.
        :return: The DER encoded contents of the certificate.
        :rtype: DerNode
        """
        root = DerSequence()
        validity = DerSequence()
        notBefore = DerGeneralizedTime(self.getNotBefore())
        notAfter = DerGeneralizedTime(self.getNotAfter())

        validity.addChild(notBefore)
        validity.addChild(notAfter)

        root.addChild(validity)

        subjectList = DerSequence()
        for sd in self._subjectDescriptionList:
            child = sd.toDer()
            subjectList.addChild(child)

        root.addChild(subjectList)
        root.addChild(self._publicKey.toDer())

        if (len(self._extensionList) > 0):
            extnList = DerSequence()
            for ext in self._extensionList:
                child = ext.toDer()
                extnList.addChild(child)
            root.addChild(extnList)

        return root

    def encode(self):
        """
            Encode the contents of the certificate in DER format and set the
            Content and MetaInfo fields.
        """
        root = self.toDer()
        outVal = root.encode()
        self.setContent(Blob(outVal))
        self.getMetaInfo().setType(ContentType.KEY)

    def decode(self):
        """
        Populates the fields by decoding DER data from the Content.
        """
        root = DerNode.parse(self.getContent())

        # we need to ensure that there are:
        #   validity (notBefore, notAfter)
        #   subject list
        #   public key
        #   (optional) extension list

        rootChildren = root.getChildren()
        # 1st: validity info
        validityChildren = DerNode.getSequence(rootChildren, 0).getChildren()
        self._notBefore = validityChildren[0].toVal()
        self._notAfter = validityChildren[1].toVal()

        # 2nd: subjectList
        subjectChildren = DerNode.getSequence(rootChildren, 1).getChildren()
        for sd in subjectChildren:
            descriptionChildren = sd.getChildren()
            oidStr = descriptionChildren[0].toVal()
            value = descriptionChildren[1].toVal()

            subjectDesc = CertificateSubjectDescription(oidStr, value)
            self.addSubjectDescription(subjectDesc)

        # 3rd: public key
        publicKeyInfo = rootChildren[2].encode()
        self._publicKey = PublicKey(publicKeyInfo)

        if len(rootChildren) > 3:
            extensionChildren = DerNode.getSequence(rootChildren, 3).getChildren()
            for extInfo in extensionChildren:
                children = extInfo.getChildren()
                oidStr = children[0].toVal()
                isCritical = children[1].toVal()
                value = children[2].toVal()
                extension = CertificateExtension(oidStr, isCritical, value)
                self.addExtension(extension)

    def wireDecode(self, buf, wireFormat = None):
        """
        Make sure the fields are populated after decoding
        """
        Data.wireDecode(self, buf, wireFormat)
        self.decode()

    def getNotBefore(self):
        """
        Returns the earliest date the certificate is valid at.
        :return: Timestamp as milliseconds since 1970.
        :rtype: float
        """
        return self._notBefore

    def getNotAfter(self):
        """
        Returns the latest date the certificate is valid at.
        :return: Timestamp as milliseconds since 1970.
        :rtype: float
        """
        return self._notAfter

    def getPublicKeyInfo(self):
        """
        :return: The PublicKey object stored in the certificate.
        :rtype: PublicKey
        """
        return self._publicKey

    def getPublicKeyDer(self):
        """
        Get the public key DER encoding.
        :return: The DER encoding Blob.
        :rtype: Blob
        :throws: RuntimeError if the public key is not set.
        """
        if self._publicKey.getKeyDer().isNull():
            raise RuntimeError("The public key is not set")

        return self._publicKey.getKeyDer()

    def setNotBefore(self, notBefore):
        self._notBefore = notBefore

    def setNotAfter(self, notAfter):
        self._notAfter = notAfter

    def setPublicKeyInfo(self, publicKey):
        """
        Assign a new public key to the certificate.
        :param publicKey: The new public key
        :type publicKey: PublicKey
        """
        self._publicKey = publicKey

    def getSubjectDescriptions(self):
        """
        :return: The subject description fields of the certificate.
        :rtype: list of CertificateSubjectDescription
        """
        return self._subjectDescriptionList

    def getExtensionList(self):
        """
        :return: The extension fields of the certificate.
        :rtype: list of CertificateExtension
        """
        return self._extensionList

    def getExtensions(self):
        """
        :deprecated: Use getExtensionList.
        """
        return self.getExtensionList()
Example #21
0
    def verifySignature(buffer,
                        signature,
                        publicKey,
                        digestAlgorithm=DigestAlgorithm.SHA256):
        """
        Verify the buffer against the signature using the public key.

        :param buffer: The input buffer to verify.
        :type buffer: Blob or an object which is the same as the bytes() operator
        :param signature: The signature bytes.
        :type signature: Blob or an object which is the same as the bytes()
          operator
        :param publicKey: The object containing the public key, or the public
          key DER which is used to make the PublicKey object.
        :type publicKey: PublicKey or Blob or  an object which is the same as
          the bytes() operator
        :param digestAlgorithm: (optional) The digest algorithm. If omitted, use
          DigestAlgorithm.SHA256.
        :type digestAlgorithm: int from DigestAlgorithm
        :return: True if verification succeeds, False if verification fails.
        :rtype: bool
        :raises: ValueError for an invalid public key type or digestAlgorithm.
        """
        if digestAlgorithm == None:
            digestAlgorithm = DigestAlgorithm.SHA256

        if isinstance(buffer, Blob):
            buffer = buffer.toBytes()
        if isinstance(signature, Blob):
            signature = signature.toBytes()
        if not isinstance(publicKey, PublicKey):
            # Turn publicKey into a PublicKey object.
            if not isinstance(publicKey, Blob):
                publicKey = Blob(publicKey)
            publicKey = PublicKey(publicKey)

        if digestAlgorithm == DigestAlgorithm.SHA256:
            if publicKey.getKeyType() == KeyType.RSA:
                # Get the public key.
                try:
                    cryptoPublicKey = load_der_public_key(
                        publicKey.getKeyDer().toBytes(),
                        backend=default_backend())
                except:
                    return False

                try:
                    cryptoPublicKey.verify(signature, buffer,
                                           padding.PKCS1v15(), hashes.SHA256())
                    return True
                except:
                    return False
            elif publicKey.getKeyType() == KeyType.EC:
                # Get the public key.
                try:
                    cryptoPublicKey = load_der_public_key(
                        publicKey.getKeyDer().toBytes(),
                        backend=default_backend())
                except:
                    return False

                try:
                    cryptoPublicKey.verify(signature, buffer,
                                           ec.ECDSA(hashes.SHA256()))
                    return True
                except:
                    return False
            else:
                raise ValueError("verifySignature: Invalid key type")
        else:
            raise ValueError("verifySignature: Invalid digest algorithm")
Example #22
0
class Certificate(Data):
    epochStart = datetime(1970,1,1)
    def __init__(self, other=None):
        """
        Create a new certificate, optionally copying the
        contents of another Data object.
        :param other: (optional) A Data packet to copy the content from
        :type other: Data
        """
        super(Certificate,self).__init__(other)
        self._subjectDescriptionList = []
        self._extensionList = []
        if isinstance(other, Data):
            self.decode()
        else:
            self._notBefore = 1e37
            self._notAfter = -1e37
            self._publicKey = PublicKey()

    def isTooEarly(self):
        """
        Check if the certificate start date is in the future
        :return: True if the certificate cannot be used yet
        :rtype: boolean
        """

        secondsSince1970 = (datetime.now() - self.epochStart).total_seconds
        if secondsSince1970 < self.getNotBefore()/1000:
            return True
        return False

    def isTooLate(self):
        """
        Check if the certificate end date is in the past
        :return: True if the certificate has expired
        :rtype: boolean
        """
        secondsSince1970 = (datetime.now() - self.epochStart).total_seconds
        if secondsSince1970 > self.getNotAfter()/1000:
            return True
        return False

    def isInValidityPeriod(self, time):
        return self.getSignature().getValidityPeriod().isValid(time)

    def __str__(self):
        s = "Certificate name:\n"
        s += "  "+self.getName().toUri()+"\n"
        s += "Validity:\n"

        dateFormat = "%Y%m%dT%H%M%S"
        notBeforeStr = Common.datetimeFromTimestamp(self.getNotBefore()).strftime(dateFormat)
        notAfterStr = Common.datetimeFromTimestamp(self.getNotAfter()).strftime(dateFormat)

        s += "  NotBefore: " + notBeforeStr+"\n"
        s += "  NotAfter: " + notAfterStr + "\n"
        for sd in self._subjectDescriptionList:
            s += "Subject Description:\n"
            s += "  " + str(sd.getOid()) + ": " + sd.getValue().toRawStr() + "\n"

        s += "Public key bits:\n"
        s += Common.base64Encode(self.getPublicKeyDer().toBytes(), True)

        if len(self._extensionList) > 0:
            s += "Extensions:\n"
            for ext in self._extensionList:
                s += "  OID: "+ext.getOid()+"\n"
                s += "  Is critical: " + ('Y' if ext.isCritical() else 'N') + "\n"

                s += "  Value: " + str(ext.getValue()).encode('hex') + "\n"

        return s

    def addSubjectDescription(self, descr):
        """
        Add a subject description field to the certificate.
        :param descr: The CertificateSubjectDescription object to add
        """
        self._subjectDescriptionList.append(descr)

    def addExtension(self, ext):
        """
        Add an extension field to the certificate.
        :param ext: Th CertificateExtension object to add
        """
        self._extensionList.append(ext)

    def toDer(self):
        """
        Encode the certificate fields in DER format.
        :return: The DER encoded contents of the certificate.
        :rtype: DerNode
        """
        root = DerSequence()
        validity = DerSequence()
        notBefore = DerGeneralizedTime(self.getNotBefore())
        notAfter = DerGeneralizedTime(self.getNotAfter())

        validity.addChild(notBefore)
        validity.addChild(notAfter)

        root.addChild(validity)

        subjectList = DerSequence()
        for sd in self._subjectDescriptionList:
            child = sd.toDer()
            subjectList.addChild(child)

        root.addChild(subjectList)
        root.addChild(self._publicKey.toDer())

        if (len(self._extensionList) > 0):
            extnList = DerSequence()
            for ext in self._extensionList:
                child = ext.toDer()
                extnList.addChild(child)
            root.addChild(extnList)

        return root

    def encode(self):
        """
            Encode the contents of the certificate in DER format and set the
            Content and MetaInfo fields.
        """
        root = self.toDer()
        outVal = root.encode()
        self.setContent(Blob(outVal))
        self.getMetaInfo().setType(ContentType.KEY)

    def decode(self):
        """
        Populates the fields by decoding DER data from the Content.
        """
        root = DerNode.parse(self.getContent())

        # we need to ensure that there are:
        #   validity (notBefore, notAfter)
        #   subject list
        #   public key
        #   (optional) extension list

        rootChildren = root.getChildren()
        # 1st: validity info
        validityChildren = DerNode.getSequence(rootChildren, 0).getChildren()
        self._notBefore = validityChildren[0].toVal()
        self._notAfter = validityChildren[1].toVal()

        # 2nd: subjectList
        subjectChildren = DerNode.getSequence(rootChildren, 1).getChildren()
        for sd in subjectChildren:
            descriptionChildren = sd.getChildren()
            oidStr = descriptionChildren[0].toVal()
            value = descriptionChildren[1].toVal()

            subjectDesc = CertificateSubjectDescription(oidStr, value)
            self.addSubjectDescription(subjectDesc)

        # 3rd: public key
        publicKeyInfo = rootChildren[2].encode()
        self._publicKey = PublicKey(publicKeyInfo)

        if len(rootChildren) > 3:
            extensionChildren = DerNode.getSequence(rootChildren, 3).getChildren()
            for extInfo in extensionChildren:
                children = extInfo.getChildren()
                oidStr = children[0].toVal()
                isCritical = children[1].toVal()
                value = children[2].toVal()
                extension = CertificateExtension(oidStr, isCritical, value)
                self.addExtension(extension)

    def wireDecode(self, buf, wireFormat = None):
        """
        Make sure the fields are populated after decoding
        """
        Data.wireDecode(self, buf, wireFormat)
        self.decode()

    def getNotBefore(self):
        """
        Returns the earliest date the certificate is valid at.
        :return: Timestamp as milliseconds since 1970.
        :rtype: float
        """
        return self._notBefore

    def getNotAfter(self):
        """
        Returns the latest date the certificate is valid at.
        :return: Timestamp as milliseconds since 1970.
        :rtype: float
        """
        return self._notAfter

    def getPublicKeyInfo(self):
        """
        :return: The PublicKey object stored in the certificate.
        :rtype: PublicKey
        """
        return self._publicKey

    def getPublicKeyDer(self):
        """
        Get the public key DER encoding.
        :return: The DER encoding Blob.
        :rtype: Blob
        :throws: RuntimeError if the public key is not set.
        """
        if self._publicKey.getKeyDer().isNull():
            raise RuntimeError("The public key is not set")

        return self._publicKey.getKeyDer()

    def setNotBefore(self, notBefore):
        self._notBefore = notBefore

    def setNotAfter(self, notAfter):
        self._notAfter = notAfter

    def setPublicKeyInfo(self, publicKey):
        """
        Assign a new public key to the certificate.
        :param publicKey: The new public key
        :type publicKey: PublicKey
        """
        self._publicKey = publicKey

    def getSubjectDescriptions(self):
        """
        :return: The subject description fields of the certificate.
        :rtype: list of CertificateSubjectDescription
        """
        return self._subjectDescriptionList

    def getExtensionList(self):
        """
        :return: The extension fields of the certificate.
        :rtype: list of CertificateExtension
        """
        return self._extensionList

    def getExtensions(self):
        """
        :deprecated: Use getExtensionList.
        """
        return self.getExtensionList()