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
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
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
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")
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 __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)
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))
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())
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
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))
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
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))
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))
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)
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()
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")
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()