class CertID(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('hashAlgorithm', rfc2459.AlgorithmIdentifier()), namedtype.NamedType('issuerNameHash', univ.OctetString()), namedtype.NamedType('issuerKeyHash', univ.OctetString()), namedtype.NamedType('serialNumber', rfc2459.CertificateSerialNumber()) )
class TBSCertificate(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.DefaultedNamedType('version', rfc2459.Version('v1', tagSet=rfc2459.Version.tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))), namedtype.NamedType('serialNumber', rfc2459.CertificateSerialNumber()), namedtype.NamedType('signature', AlgorithmIdentifier()), namedtype.NamedType('issuer', rfc2459.Name()), namedtype.NamedType('validity', rfc2459.Validity()), namedtype.NamedType('subject', rfc2459.Name()), namedtype.NamedType('subjectPublicKeyInfo', SubjectPublicKeyInfo()), namedtype.OptionalNamedType('issuerUniqueID', rfc2459.UniqueIdentifier().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), namedtype.OptionalNamedType('subjectUniqueID', rfc2459.UniqueIdentifier().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), namedtype.OptionalNamedType('extensions', rfc2459.Extensions().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))) )
def _build_tbs(csr, days, network): cri = csr.getComponentByName('certificationRequestInfo') subject = cri.getComponentByName('subject') subjectPublicKeyInfo = cri.getComponentByName('subjectPublicKeyInfo') dt_now = datetime.datetime.utcnow() later = datetime.timedelta(days=days) dt_now_str = dt_now.strftime("%y%m%d%H%M%S") + "Z" later_str = (dt_now + later).strftime("%y%m%d%H%M%S") + "Z" notbefore = useful.UTCTime(dt_now_str) notafter = useful.UTCTime(later_str) validity = rfc2459.Validity() validity.setComponentByName('notBefore', notbefore) validity.setComponentByName('notAfter', notafter) tbs = rfc2459.TBSCertificate() tbs.setComponentByName( 'version', rfc2459.Version('v3').subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) rndfile = Random.new() serial = encoding.to_long(256, encoding.byte_to_int, rndfile.read(32))[0] tbs.setComponentByName( 'serialNumber', rfc2459.CertificateSerialNumber(univ.Integer(serial))) tbs.setComponentByName('signature', csr.getComponentByName('signatureAlgorithm')) tbs.setComponentByName('issuer', subject) tbs.setComponentByName('validity', validity) tbs.setComponentByName('subject', subject) tbs.setComponentByName('subjectPublicKeyInfo', subjectPublicKeyInfo) extensionstoadd = "" attributes = cri.getComponentByName('attributes') for attribute in attributes: if (attribute.getComponentByName('type') == utility.OID_PKCShash9ExtensionRequest): value = attribute[1] ## careful with decoder, it returns an implicit type in a tuple extensionstoadd = decoder.decode(value[0])[0] spk = subjectPublicKeyInfo.getComponentByName('subjectPublicKey') ## self siiiigned extensions = _build_extensionsForTbs(extensionstoadd, akipubkeybitstring=spk, skipubkeybitstring=spk) if extensions: tbs.setComponentByName('extensions', extensions) return tbs
def is_cert_id_in_cache(ocsp_issuer, ocsp_subject, use_cache=True): u""" checks if cert_id is in the cache """ logger = getLogger(__name__) cert_id = CertID() cert_id['hashAlgorithm'] = rfc2459.AlgorithmIdentifier( ).setComponentByName('algorithm', ocsp_issuer[u'algorithm']).setComponentByName( 'parameters', ocsp_issuer[u'algorithm_parameter']) cert_id['issuerNameHash'] = univ.OctetString( hexValue=ocsp_issuer[u'name_hash']) cert_id['issuerKeyHash'] = univ.OctetString( hexValue=ocsp_issuer[u'key_hash']) cert_id['serialNumber'] = rfc2459.CertificateSerialNumber( ocsp_subject[u'serial_number']) cert_id_der = der_encoder.encode(cert_id) if logger.getEffectiveLevel() == logging.DEBUG: base64_issuer_name_hash = base64.b64encode( octet_string_to_bytearray(cert_id['issuerNameHash'])) else: base64_issuer_name_hash = None with OCSP_VALIDATION_CACHE_LOCK: if use_cache and cert_id_der in OCSP_VALIDATION_CACHE: current_time = int(time.time()) ts, cache = OCSP_VALIDATION_CACHE[cert_id_der] if ts - CACHE_EXPIRATION <= current_time <= ts + CACHE_EXPIRATION: # cache value is OCSP response logger.debug(u'hit cache: %s', base64_issuer_name_hash) return True, cert_id, cache else: # more than 24 hours difference del OCSP_VALIDATION_CACHE[cert_id_der] logger.debug(u'not hit cache: %s', base64_issuer_name_hash) return False, cert_id, None
def addAuthorityKeyId(self, akiTypes, critical): types = [st.strip() for st in akiTypes.split(',')] noneSpecified = 0 == len(akiTypes.strip()) if critical: raise UnknownAuthorityKeyIdError(critical) hasher = hashlib.sha1() hasher.update(self.issuerKey.toDER()) akiKi = rfc2459.KeyIdentifier().subtype(implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 0), value=hasher.digest()) aki = rfc2459.AuthorityKeyIdentifier() # If the issuerSerialNumber is set, we can add AKI data for Issuer principal and the issuer serial number if None != self.issuerSerialNumber: issuerName = rfc2459.GeneralNames().subtype(implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 1)) generalName = stringToDN( self.issuer, tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) issuerName.setComponentByPosition(0, generalName) csn = rfc2459.CertificateSerialNumber().subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2), value=decoder.decode(self.issuerSerialNumber)[0]) if noneSpecified or 'ki' in types: aki.setComponentByPosition(0, akiKi) if noneSpecified or 'issuer' in types: aki.setComponentByPosition(1, issuerName) if noneSpecified or 'serialNumber' in types: aki.setComponentByPosition(2, csn) else: if noneSpecified or 'ki' in types: aki.setComponentByPosition(0, akiKi) self.addExtension(rfc2459.id_ce_authorityKeyIdentifier, aki, critical)
def encode(cls, pki_key: object, **kwargs): # Algorithm ID alg_oid = cls.ALG_OID if type( cls.ALG_OID) is str else cls.ALG_OID(pki_key) alg_id = rfc2459.AlgorithmIdentifier() alg_id['algorithm'] = ObjectIdentifier(alg_oid) if cls.PARAM_ENCODER: alg_id['parameters'] = Any( encoder.encode(cls.PARAM_ENCODER.encode(pki_key))) # Serial number serial_num = rfc2459.CertificateSerialNumber( kwargs.get('serial_number') or 0) # Validity (time valid) not_before = kwargs.get('not_before') or datetime.now() not_after = kwargs.get('not_after') or not_before.replace( year=not_before.year + 1) validity = rfc2459.Validity() validity['notBefore'] = rfc2459.Time() validity['notBefore']['utcTime'] = UTCTime.fromDateTime(not_before) validity['notAfter'] = rfc2459.Time() validity['notAfter']['utcTime'] = UTCTime.fromDateTime(not_after) # Public key serialization pub_info = rfc2459.SubjectPublicKeyInfo() pub_info['algorithm'] = alg_id pub_info['subjectPublicKey'] = cls.PUB_KEY_ENCODER.encode(pki_key) # Issuer RDN issuer = rfc2459.Name() issuer.setComponentByPosition( 0, parse_rdn(kwargs.get('issuer') or 'CN=ca')) # Subject RDN subject = rfc2459.Name() subject.setComponentByPosition( 0, parse_rdn(kwargs.get('subject') or 'CN=ca')) # Signature algorithm signing_key = kwargs.get('signing_key') or pki_key if not (kwargs.get('signing_alg') or hasattr(signing_key, "X509_SIGNING_DEFAULT")): raise ValueError( "'signing_alg' not specified and 'signing_key' has no default algorithm" ) signing_alg = (kwargs.get('signing_alg') or signing_key.X509_SIGNING_DEFAULT).value signature_alg = rfc2459.AlgorithmIdentifier() signature_alg['algorithm'] = SIGNING_ALG_OIDS[signing_alg.name] if cls.PARAM_ENCODER: signature_alg['parameters'] = Any( encoder.encode(cls.PARAM_ENCODER.encode(pki_key))) # Extensions extensions = rfc2459.Extensions().subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) if kwargs.get('ca') and kwargs.get('ca') == True: # SKI pkey_bytes = Bytes(int(pub_info['subjectPublicKey'])) ski_ext = rfc2459.Extension() ski_ext['extnID'] = ObjectIdentifier([2, 5, 29, 14]) ski_ext['extnValue'] = OctetString( encoder.encode( rfc2459.SubjectKeyIdentifier(SHA1().hash(pkey_bytes)))) # CA basic constraint ca_value = rfc2459.BasicConstraints() ca_value.setComponentByName('cA', True) ca_ext = rfc2459.Extension() ca_ext.setComponentByName('extnID', '2.5.29.19') ca_ext.setComponentByName('critical', True) ca_ext.setComponentByName('extnValue', OctetString(encoder.encode(ca_value))) extensions.setComponentByPosition(0, ski_ext) extensions.setComponentByPosition(1, ca_ext) # Put together the TBSCert tbs_cert = rfc2459.TBSCertificate() tbs_cert['version'] = 2 tbs_cert['serialNumber'] = serial_num tbs_cert['signature'] = signature_alg tbs_cert['issuer'] = issuer tbs_cert['validity'] = validity tbs_cert['subject'] = subject tbs_cert['subjectPublicKeyInfo'] = pub_info tbs_cert['issuerUniqueID'] = kwargs.get('issuer_unique_id') or 10 tbs_cert['subjectUniqueID'] = kwargs.get('subject_unique_id') or 11 if len(extensions): tbs_cert['extensions'] = extensions # Inject or compute the TBSCert signature if kwargs.get('signature_value') is not None: sig_value = Bytes.wrap(kwargs.get('signature_value')).int() else: encoded_tbs = encoder.encode(tbs_cert, asn1Spec=rfc2459.TBSCertificate()) sig_value = signing_alg.sign(signing_key, encoded_tbs) # Build the Cert object cert = rfc2459.Certificate() cert['tbsCertificate'] = tbs_cert cert['signatureAlgorithm'] = signature_alg cert['signatureValue'] = sig_value encoded = encoder.encode(cert, asn1Spec=rfc2459.Certificate()) return X509Certificate.transport_encode(encoded, **kwargs)
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) request = Request() certid = CertID() request['reqCert'] = certid certid['hashAlgorithm'] = rfc2459.AlgorithmIdentifier()\ .setComponentByName('algorithm', rfc2437.id_sha1)\ # .setComponentByName('parameters', univ.Any(hexValue='0500')) # certid['issuerNameHash'] = univ.OctetString(hexValue='01cb3044531fa8618a68d3c60596ab0555866b09') certid['issuerNameHash'] = univ.OctetString( hexValue='54e857e287d993fb6c0001fa3739b6e35c0e2c21') # certid['issuerKeyHash'] = univ.OctetString(hexValue='31c3791bbaf553d717e0897a2d176c0ab32b9d33') certid['issuerKeyHash'] = univ.OctetString( hexValue='1819c3646d8a358624911ee83dd5a78e509d555d') certid['serialNumber'] = rfc2459.CertificateSerialNumber(10000616) encoder.encode(certid['serialNumber']) req['tbsRequest']['requestList'] = univ.SequenceOf( componentType=Request()).setComponentByPosition(0, request) # reqExts = rfc2459.Extensions().subtype( # explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)) # reqExt = rfc2459.Extension() # reqExt['extnID'] = univ.ObjectIdentifier('1.3.6.1.5.5.7.48.1.2') # reqExt['critical'] = univ.Boolean('False') # reqExt['extnValue'] = univ.Any(hexValue='04120410236e5193af7958f49edcc756ed6c6dd3') # reqExts[0] = reqExt # req['tbsRequest']['requestExtensions'] = reqExts print(req.prettyPrint()) print(encoder.encode(req)) else:
def is_cert_id_in_cache(ocsp_issuer, ocsp_subject, use_cache=True): u""" checks if cert_id is in the cache """ global SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED global SF_OCSP_RESPONSE_CACHE_SERVER_URL global OCSP_VALIDATION_CACHE_UPDATED logger = getLogger(__name__) cert_id = CertID() cert_id['hashAlgorithm'] = rfc2459.AlgorithmIdentifier( ).setComponentByName('algorithm', ocsp_issuer[u'algorithm']).setComponentByName( 'parameters', ocsp_issuer[u'algorithm_parameter']) cert_id['issuerNameHash'] = univ.OctetString( hexValue=ocsp_issuer[u'name_hash']) cert_id['issuerKeyHash'] = univ.OctetString( hexValue=ocsp_issuer[u'key_hash']) cert_id['serialNumber'] = rfc2459.CertificateSerialNumber( ocsp_subject[u'serial_number']) if logger.getEffectiveLevel() == logging.DEBUG: base64_name_hash = b64encode( octet_string_to_bytearray(cert_id['issuerNameHash'])) else: base64_name_hash = None with OCSP_VALIDATION_CACHE_LOCK: current_time = int(time.time()) for idx in range(2): hkey = _decode_cert_id_key(cert_id) if use_cache and hkey in OCSP_VALIDATION_CACHE: ts, cache = OCSP_VALIDATION_CACHE[hkey] if ts - CACHE_EXPIRATION <= current_time <= ts + CACHE_EXPIRATION: # cache value is OCSP response logger.debug( u'hit cache. issuer name: %s, is ' u'subject root: %s', ocsp_issuer['name'], ocsp_issuer[u'is_root_ca']) return True, cert_id, cache else: # more than 24 hours difference del OCSP_VALIDATION_CACHE[hkey] OCSP_VALIDATION_CACHE_UPDATED = True if idx == 1: # No second attempt to download the OCSP response cache. break # download OCSP response cache once if SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED: downloaded_cache = download_ocsp_response_cache( SF_OCSP_RESPONSE_CACHE_SERVER_URL) logger.debug('downloaded OCSP response cache file from %s', SF_OCSP_RESPONSE_CACHE_SERVER_URL) for hkey, (ts, cache) in downloaded_cache.items(): if ts - CACHE_EXPIRATION <= current_time <= ts + CACHE_EXPIRATION: OCSP_VALIDATION_CACHE[hkey] = ts, cache OCSP_VALIDATION_CACHE_UPDATED = True else: logger.debug("OCSP response cache service is not enabled. Set " "the environment variable " "SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED=true to " "enable it.") if logger.getEffectiveLevel() == logging.DEBUG: logger.debug( u'not hit cache. issuer name hash: %s, issuer name: %s, is subject ' u'root: %s, issuer name hash algorithm: %s, ' u'issuer key hash: %s, subject serial number: %s', base64_name_hash, ocsp_issuer['name'], ocsp_issuer[u'is_root_ca'], cert_id['hashAlgorithm'], b64encode(octet_string_to_bytearray(cert_id['issuerKeyHash'])), cert_id['serialNumber']) return False, cert_id, None
def build_payload(): # initializations tbsReq = TBSRequest() certid = CertID() request = Request() requestList = univ.SequenceOf(componentType=Request()) req = OCSPRequest() reqExts = rfc2459.Extensions().subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)) reqExt = rfc2459.Extension() signature = Signature() certs = univ.SequenceOf(componentType=rfc2459.Certificate()).subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0) ) cert = rfc2459.Certificate() name = rfc2459.GeneralName() # assignments certid['hashAlgorithm'] = rfc2459.AlgorithmIdentifier()\ .setComponentByName('algorithm', ALGORITHM)\ .setComponentByName('parameters', univ.Any(hexValue=ALGO_PARAMS_HEX)) certid['issuerNameHash'] = univ.OctetString(hexValue=ISSUER_NAME_HASH) certid['issuerKeyHash'] = univ.OctetString(hexValue=ISSUER_KEY_HASH) certid['serialNumber'] = rfc2459.CertificateSerialNumber(SERIAL_NUMBER) request['reqCert'] = certid # optional field #request['singleRequestExtension'] = reqExt reqExt['extnID'] = univ.ObjectIdentifier('1.3.6.1.5.5.7.48.1.2') reqExt['critical'] = univ.Boolean('False') reqExt['extnValue'] = univ.Any(hexValue='04120410236e5193af7958f49edcc756ed6c6dd3') reqExts[0] = reqExt requestList[0] = request # optional # TODO: fill name? #tbsReq['requestorName'] = name tbsReq['requestList'] = requestList # optional tbsReq['requestExtensions'] = reqExts tbsReq['version'] = Version(0).subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) # optional # TODO fill cert? signature['signatureAlgorithm'] = rfc2459.AlgorithmIdentifier()\ .setComponentByName('algorithm', rfc2437.sha1WithRSAEncryption) signature['signature'] = univ.BitString("'010101010101'B") certs[0] = cert signature['certs'] = certs req['tbsRequest'] = tbsReq # optional signature #req['optionalSignature'] = signature return req