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