def recipient_info(self, cert, session_key, oaep): public_key = cert.public_key() cert = signer.cert2asn(cert) tbs_cert = cert['tbs_certificate'] # TODO: use subject_key_identifier when available if oaep: encrypted_key = public_key.encrypt( session_key, padding.OAEP(mgf=padding.MGF1(hashes.SHA512()), algorithm=hashes.SHA512(), label=None)) kea = cms.KeyEncryptionAlgorithm({ 'algorithm': cms.KeyEncryptionAlgorithmId('rsaes_oaep'), 'parameters': algos.RSAESOAEPParams({ 'hash_algorithm': algos.DigestAlgorithm({'algorithm': 'sha512'}), 'mask_gen_algorithm': algos.MaskGenAlgorithm({ 'algorithm': algos.MaskGenAlgorithmId('mgf1'), 'parameters': { 'algorithm': algos.DigestAlgorithmId('sha512'), } }), 'p_source_algorithm': algos.PSourceAlgorithm({ 'algorithm': algos.PSourceAlgorithmId('p_specified'), 'parameters': b'', }) }) }) else: kea = {'algorithm': 'rsa'} encrypted_key = public_key.encrypt(session_key, padding.PKCS1v15()) result = cms.RecipientInfo(name='ktri', value={ 'version': 'v0', 'rid': cms.RecipientIdentifier( name='issuer_and_serial_number', value={ 'issuer': tbs_cert['issuer'], 'serial_number': tbs_cert['serial_number'] }), 'key_encryption_algorithm': kea, 'encrypted_key': core.OctetString(encrypted_key) }) return result
def sign_authpack_native(data, privkey, certificate, wrap_signed=False): """ Creating PKCS7 blob which contains the following things: 1. 'data' blob which is an ASN1 encoded "AuthPack" structure 2. the certificate used to sign the data blob 3. the singed 'signed_attrs' structure (ASN1) which points to the "data" structure (in point 1) """ da = {'algorithm': algos.DigestAlgorithmId('1.3.14.3.2.26')} si = {} si['version'] = 'v1' si['sid'] = cms.IssuerAndSerialNumber({ 'issuer': certificate.issuer, 'serial_number': certificate.serial_number, }) si['digest_algorithm'] = algos.DigestAlgorithm(da) si['signed_attrs'] = [ cms.CMSAttribute({ 'type': 'content_type', 'values': ['1.3.6.1.5.2.3.1'] }), # indicates that the encap_content_info's authdata struct (marked with OID '1.3.6.1.5.2.3.1' is signed ) cms.CMSAttribute({ 'type': 'message_digest', 'values': [hashlib.sha1(data).digest()] }), ### hash of the data, the data itself will not be signed, but this block of data will be. ] si['signature_algorithm'] = algos.SignedDigestAlgorithm( {'algorithm': '1.2.840.113549.1.1.1'}) si['signature'] = rsa_pkcs1v15_sign( privkey, cms.CMSAttributes(si['signed_attrs']).dump(), "sha1") ec = {} ec['content_type'] = '1.3.6.1.5.2.3.1' ec['content'] = data sd = {} sd['version'] = 'v3' sd['digest_algorithms'] = [algos.DigestAlgorithm(da)] # must have only one sd['encap_content_info'] = cms.EncapsulatedContentInfo(ec) sd['certificates'] = [certificate] sd['signer_infos'] = cms.SignerInfos([cms.SignerInfo(si)]) if wrap_signed is True: ci = {} ci['content_type'] = '1.2.840.113549.1.7.2' # signed data OID ci['content'] = cms.SignedData(sd) return cms.ContentInfo(ci).dump() return cms.SignedData(sd).dump()
async def format_csc_signing_req(self, tbs_hashes: List[str], digest_algorithm: str) -> dict: """ Populate the request data for a CSC signing request :param tbs_hashes: Base64-encoded hashes that require signing. :param digest_algorithm: The digest algorithm to use. :return: A dict that, when encoded as a JSON object, be used as the request body for a call to ``signatures/signHash``. """ mechanism = self.get_signature_mechanism(digest_algorithm) session_info = self.auth_manager.csc_session_info # SAD can be bound to specific hashes, but the authorization # process typically takes more wall clock time (esp. when # authorization requires a human user to perform an action). # Putting get_activation_data in a separate coroutine # allows API users to choose whether they want to provide # the credentials at init time, or just-in-time tied to specific # hashes. # The latter might not scale as easily within this architecture; # if you want both optimal security _and_ optimal performance, # you'll have to use this signer in the interrupted signing workflow. auth_info: CSCAuthorizationInfo \ = await self.auth_manager.authorize_signature(tbs_hashes) req_data = { 'credentialID': session_info.credential_id, 'SAD': auth_info.sad, 'hashAlgo': algos.DigestAlgorithmId(digest_algorithm).dotted, 'signAlgo': mechanism['algorithm'].dotted, 'hash': tbs_hashes } if mechanism['parameters'].native is not None: params_der = mechanism['parameters'].dump() req_data['signAlgoParams'] = \ base64.b64encode(params_der).decode('ascii') if self.client_data is not None: req_data['clientData'] = self.client_data return req_data
def build_as_req_negoEx(user_cert, cert_pass, remoteComputer, diffieHellmanExchange): pfx = open(user_cert, 'rb').read() privkeyinfo, certificate, extra_certs = parse_pkcs12( pfx, password=cert_pass.encode()) privkey = load_private_key(privkeyinfo) issuer = certificate.issuer.native['common_name'] cname = "AzureAD\\" + issuer + "\\" + [ i for i in certificate.subject.native['common_name'] if i.startswith('S-1') ][0] now = datetime.datetime.now(datetime.timezone.utc) req_body = build_req_body_NegoEx(remoteComputer, cname, now) padata = BuildPkinit_pa(req_body, now, diffieHellmanExchange, privkey, certificate) payload = PA_PK_AS_REQ() payload['signedAuthPack'] = padata pa_data = { 'padata-type': PaDataType.PK_AS_REQ.value, 'padata-value': payload.dump() } asreq = { 'pvno': 5, 'msg-type': 10, 'padata': [pa_data], 'req-body': req_body } req = { 'kerberos-v5': algos.DigestAlgorithmId('1.3.6.1.5.2.7'), 'null': core.Null(), 'Kerberos': AS_REQ(asreq) } req = SPNEGO_PKINIT_REP(req) return issuer, req.dump().hex()
def sign(datau, key, cert, othercerts, hashalgo, attrs=True, signed_value=None, hsm=None, pss=False, timestampurl=None, timestampcredentials=None, timestamp_req_options=None): if signed_value is None: signed_value = getattr(hashlib, hashalgo)(datau).digest() signed_time = datetime.now(tz=util.timezone.utc) if hsm is not None: keyid, cert = hsm.certificate() cert = cert2asn(cert, False) else: cert = cert2asn(cert) certificates = [] certificates.append(cert) for i in range(len(othercerts)): certificates.append(cert2asn(othercerts[i])) hashalgo = unicode(hashalgo) if sys.version[0] < '3' else hashalgo signer = { 'version': 'v1', 'sid': cms.SignerIdentifier({ 'issuer_and_serial_number': cms.IssuerAndSerialNumber({ 'issuer': cert.issuer, 'serial_number': cert.serial_number, }), }), 'digest_algorithm': algos.DigestAlgorithm({'algorithm': hashalgo}), 'signature': signed_value, } if not pss: signer['signature_algorithm'] = algos.SignedDigestAlgorithm( {'algorithm': 'rsassa_pkcs1v15'}) else: if isinstance(key, keys.PrivateKeyInfo): salt_length = key.byte_size - hashes.SHA512.digest_size - 2 salt_length = hashes.SHA512.digest_size else: salt_length = padding.calculate_max_pss_salt_length( key, hashes.SHA512) signer['signature_algorithm'] = algos.SignedDigestAlgorithm({ 'algorithm': 'rsassa_pss', 'parameters': algos.RSASSAPSSParams({ 'hash_algorithm': algos.DigestAlgorithm({'algorithm': 'sha512'}), 'mask_gen_algorithm': algos.MaskGenAlgorithm({ 'algorithm': algos.MaskGenAlgorithmId('mgf1'), 'parameters': { 'algorithm': algos.DigestAlgorithmId('sha512'), } }), 'salt_length': algos.Integer(salt_length), 'trailer_field': algos.TrailerField(1) }) }) if attrs: if attrs is True: signer['signed_attrs'] = [ cms.CMSAttribute({ 'type': cms.CMSAttributeType('content_type'), 'values': ('data', ), }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('message_digest'), 'values': (signed_value, ), }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('signing_time'), 'values': (cms.Time({'utc_time': core.UTCTime(signed_time)}), ) }), ] else: signer['signed_attrs'] = attrs config = { 'version': 'v1', 'digest_algorithms': cms.DigestAlgorithms((algos.DigestAlgorithm({'algorithm': hashalgo}), )), 'encap_content_info': { 'content_type': 'data', }, 'certificates': certificates, # 'crls': [], 'signer_infos': [ signer, ], } datas = cms.ContentInfo({ 'content_type': cms.ContentType('signed_data'), 'content': cms.SignedData(config), }) if attrs: tosign = datas['content']['signer_infos'][0]['signed_attrs'].dump() tosign = b'\x31' + tosign[1:] else: tosign = datau if hsm is not None: signed_value_signature = hsm.sign(keyid, tosign, hashalgo) elif isinstance(key, keys.PrivateKeyInfo): key = asymmetric.load_private_key(key) if pss: signed_value_signature = asymmetric.rsa_pss_sign( key, tosign, 'sha512') else: signed_value_signature = asymmetric.rsa_pkcs1v15_sign( key, tosign, hashalgo.lower()) else: if pss: hasher = hashes.Hash(hashes.SHA512(), backend=backends.default_backend()) hasher.update(tosign) digest = hasher.finalize() signed_value_signature = key.sign( digest, padding.PSS(mgf=padding.MGF1(hashes.SHA512()), salt_length=salt_length), utils.Prehashed(hashes.SHA512())) else: signed_value_signature = key.sign( tosign, padding.PKCS1v15(), getattr(hashes, hashalgo.upper())()) if timestampurl is not None: datas['content']['signer_infos'][0]['unsigned_attrs'] = timestamp( signed_value_signature, hashalgo, timestampurl, timestampcredentials, timestamp_req_options, ) # signed_value_signature = core.OctetString(signed_value_signature) datas['content']['signer_infos'][0]['signature'] = signed_value_signature #open('signed-content-info', 'wb').write(datas.dump()) return datas.dump()
def sign(datau, key, cert, othercerts, hashalgo, attrs=True, signed_value=None, hsm=None, pss=False, timestampurl=None, timestampcredentials=None): if signed_value is None: signed_value = getattr(hashlib, hashalgo)(datau).digest() signed_time = datetime.now(tz=util.timezone.utc) if hsm is not None: keyid, cert = hsm.certificate() cert = cert2asn(cert, False) else: cert = cert2asn(cert) certificates = [] certificates.append(cert) for i in range(len(othercerts)): certificates.append(cert2asn(othercerts[i])) hashalgo = unicode(hashalgo) if sys.version[0] < '3' else hashalgo signer = { 'version': 'v1', 'sid': cms.SignerIdentifier({ 'issuer_and_serial_number': cms.IssuerAndSerialNumber({ 'issuer': cert.issuer, 'serial_number': cert.serial_number, }), }), 'digest_algorithm': algos.DigestAlgorithm({'algorithm': hashalgo}), 'signature': signed_value, } if not pss: signer['signature_algorithm'] = algos.SignedDigestAlgorithm( {'algorithm': 'rsassa_pkcs1v15'}) else: if isinstance(key, keys.PrivateKeyInfo): salt_length = key.byte_size - hashes.SHA512.digest_size - 2 salt_length = hashes.SHA512.digest_size else: salt_length = padding.calculate_max_pss_salt_length( key, hashes.SHA512) signer['signature_algorithm'] = algos.SignedDigestAlgorithm({ 'algorithm': 'rsassa_pss', 'parameters': algos.RSASSAPSSParams({ 'hash_algorithm': algos.DigestAlgorithm({'algorithm': 'sha512'}), 'mask_gen_algorithm': algos.MaskGenAlgorithm({ 'algorithm': algos.MaskGenAlgorithmId('mgf1'), 'parameters': { 'algorithm': algos.DigestAlgorithmId('sha512'), } }), 'salt_length': algos.Integer(salt_length), 'trailer_field': algos.TrailerField(1) }) }) if attrs: if attrs is True: signer['signed_attrs'] = [ cms.CMSAttribute({ 'type': cms.CMSAttributeType('content_type'), 'values': ('data', ), }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('message_digest'), 'values': (signed_value, ), }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('signing_time'), 'values': (cms.Time({'utc_time': core.UTCTime(signed_time)}), ) }), ] else: signer['signed_attrs'] = attrs config = { 'version': 'v1', 'digest_algorithms': cms.DigestAlgorithms((algos.DigestAlgorithm({'algorithm': hashalgo}), )), 'encap_content_info': { 'content_type': 'data', }, 'certificates': certificates, # 'crls': [], 'signer_infos': [ signer, ], } datas = cms.ContentInfo({ 'content_type': cms.ContentType('signed_data'), 'content': cms.SignedData(config), }) if attrs: tosign = datas['content']['signer_infos'][0]['signed_attrs'].dump() tosign = b'\x31' + tosign[1:] else: tosign = datau if hsm is not None: signed_value_signature = hsm.sign(keyid, tosign, hashalgo) elif isinstance(key, keys.PrivateKeyInfo): key = asymmetric.load_private_key(key) if pss: signed_value_signature = asymmetric.rsa_pss_sign( key, tosign, 'sha512') else: signed_value_signature = asymmetric.rsa_pkcs1v15_sign( key, tosign, hashalgo.lower()) else: if pss: hasher = hashes.Hash(hashes.SHA512(), backend=backends.default_backend()) hasher.update(tosign) digest = hasher.finalize() signed_value_signature = key.sign( digest, padding.PSS(mgf=padding.MGF1(hashes.SHA512()), salt_length=salt_length), utils.Prehashed(hashes.SHA512())) else: signed_value_signature = key.sign( tosign, padding.PKCS1v15(), getattr(hashes, hashalgo.upper())()) if timestampurl is not None: signed_value = getattr(hashlib, hashalgo)(signed_value_signature).digest() tspreq = tsp.TimeStampReq({ "version": 1, "message_imprint": tsp.MessageImprint({ "hash_algorithm": algos.DigestAlgorithm({'algorithm': hashalgo}), "hashed_message": signed_value, }), #'req_policy', ObjectIdentifier, {'optional': True}), "nonce": int(time.time() * 1000), "cert_req": True, #'extensions': tsp.Extensions() }) tspreq = tspreq.dump() tspheaders = {"Content-Type": "application/timestamp-query"} if timestampcredentials is not None: username = timestampcredentials.get("username", None) password = timestampcredentials.get("password", None) if username and password: auth_header_value = b64encode( bytes(username + ':' + password, "utf-8")).decode("ascii") tspheaders["Authorization"] = f"Basic {auth_header_value}" tspresp = requests.post(timestampurl, data=tspreq, headers=tspheaders) if tspresp.headers.get('Content-Type', None) == 'application/timestamp-reply': tspresp = tsp.TimeStampResp.load(tspresp.content) if tspresp['status']['status'].native == 'granted': attrs = [ cms.CMSAttribute({ 'type': cms.CMSAttributeType('signature_time_stamp_token'), 'values': cms.SetOfContentInfo([ cms.ContentInfo({ 'content_type': cms.ContentType('signed_data'), 'content': tspresp["time_stamp_token"]["content"], }) ]) }) ] datas['content']['signer_infos'][0]['unsigned_attrs'] = attrs else: raise ValueError("TimeStampResponse status is not granted") else: raise ValueError("TimeStampResponse has invalid content type") # signed_value_signature = core.OctetString(signed_value_signature) datas['content']['signer_infos'][0]['signature'] = signed_value_signature #open('signed-content-info', 'wb').write(datas.dump()) return datas.dump()
def sign_message(data_to_sign, digest_alg, sign_key, use_signed_attributes=True): """Function signs the data and returns the generated ASN.1 :param data_to_sign: A byte string of the data to be signed. :param digest_alg: The digest algorithm to be used for generating the signature. :param sign_key: The key to be used for generating the signature. :param use_signed_attributes: Optional attribute to indicate weather the CMS signature attributes should be included in the signature or not. :return: A CMS ASN.1 byte string of the signed data. """ if use_signed_attributes: digest_func = hashlib.new(digest_alg) digest_func.update(data_to_sign) message_digest = digest_func.digest() class SmimeCapability(core.Sequence): _fields = [('0', core.Any, { 'optional': True }), ('1', core.Any, { 'optional': True }), ('2', core.Any, { 'optional': True }), ('3', core.Any, { 'optional': True }), ('4', core.Any, { 'optional': True })] class SmimeCapabilities(core.Sequence): _fields = [ ('0', SmimeCapability), ('1', SmimeCapability, { 'optional': True }), ('2', SmimeCapability, { 'optional': True }), ('3', SmimeCapability, { 'optional': True }), ('4', SmimeCapability, { 'optional': True }), ('5', SmimeCapability, { 'optional': True }), ] smime_cap = OrderedDict([ ('0', OrderedDict([('0', core.ObjectIdentifier('1.2.840.113549.3.7')) ])), ('1', OrderedDict([('0', core.ObjectIdentifier('1.2.840.113549.3.2')), ('1', core.Integer(128))])), ('2', OrderedDict([('0', core.ObjectIdentifier('1.2.840.113549.3.4')), ('1', core.Integer(128))])), ]) signed_attributes = cms.CMSAttributes([ cms.CMSAttribute({ 'type': cms.CMSAttributeType('content_type'), 'values': cms.SetOfContentType([cms.ContentType('data')]) }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('signing_time'), 'values': cms.SetOfTime( [cms.Time({'utc_time': core.UTCTime(datetime.now())})]) }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('message_digest'), 'values': cms.SetOfOctetString([core.OctetString(message_digest)]) }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('1.2.840.113549.1.9.15'), 'values': cms.SetOfAny([core.Any(SmimeCapabilities(smime_cap))]) }), ]) signature = asymmetric.rsa_pkcs1v15_sign(sign_key[0], signed_attributes.dump(), digest_alg) else: signed_attributes = None signature = asymmetric.rsa_pkcs1v15_sign(sign_key[0], data_to_sign, digest_alg) return cms.ContentInfo({ 'content_type': cms.ContentType('signed_data'), 'content': cms.SignedData({ 'version': cms.CMSVersion('v1'), 'digest_algorithms': cms.DigestAlgorithms([ algos.DigestAlgorithm( {'algorithm': algos.DigestAlgorithmId(digest_alg)}) ]), 'encap_content_info': cms.ContentInfo({'content_type': cms.ContentType('data')}), 'certificates': cms.CertificateSet( [cms.CertificateChoices({'certificate': sign_key[1].asn1})]), 'signer_infos': cms.SignerInfos([ cms.SignerInfo({ 'version': cms.CMSVersion('v1'), 'sid': cms.SignerIdentifier({ 'issuer_and_serial_number': cms.IssuerAndSerialNumber({ 'issuer': sign_key[1].asn1['tbs_certificate']['issuer'], 'serial_number': sign_key[1].asn1['tbs_certificate'] ['serial_number'] }) }), 'digest_algorithm': algos.DigestAlgorithm( {'algorithm': algos.DigestAlgorithmId(digest_alg)}), 'signed_attrs': signed_attributes, 'signature_algorithm': algos.SignedDigestAlgorithm({ 'algorithm': algos.SignedDigestAlgorithmId('rsassa_pkcs1v15') }), 'signature': core.OctetString(signature) }) ]) }) }).dump()
def sign_message( data_to_sign, digest_alg, sign_key, sign_alg="rsassa_pkcs1v15", use_signed_attributes=True, ): """Function signs the data and returns the generated ASN.1 :param data_to_sign: A byte string of the data to be signed. :param digest_alg: The digest algorithm to be used for generating the signature. :param sign_key: The key to be used for generating the signature. :param sign_alg: The algorithm to be used for signing the message. :param use_signed_attributes: Optional attribute to indicate weather the CMS signature attributes should be included in the signature or not. :return: A CMS ASN.1 byte string of the signed data. """ if use_signed_attributes: digest_func = hashlib.new(digest_alg) digest_func.update(data_to_sign) message_digest = digest_func.digest() class SmimeCapability(core.Sequence): _fields = [ ("0", core.Any, { "optional": True }), ("1", core.Any, { "optional": True }), ("2", core.Any, { "optional": True }), ("3", core.Any, { "optional": True }), ("4", core.Any, { "optional": True }), ] class SmimeCapabilities(core.Sequence): _fields = [ ("0", SmimeCapability), ("1", SmimeCapability, { "optional": True }), ("2", SmimeCapability, { "optional": True }), ("3", SmimeCapability, { "optional": True }), ("4", SmimeCapability, { "optional": True }), ("5", SmimeCapability, { "optional": True }), ] smime_cap = OrderedDict([ ( "0", OrderedDict([ ("0", core.ObjectIdentifier("2.16.840.1.101.3.4.1.42")) ]), ), ( "1", OrderedDict([ ("0", core.ObjectIdentifier("2.16.840.1.101.3.4.1.2")) ]), ), ( "2", OrderedDict([("0", core.ObjectIdentifier("1.2.840.113549.3.7")) ]), ), ( "3", OrderedDict([ ("0", core.ObjectIdentifier("1.2.840.113549.3.2")), ("1", core.Integer(128)), ]), ), ( "4", OrderedDict([ ("0", core.ObjectIdentifier("1.2.840.113549.3.4")), ("1", core.Integer(128)), ]), ), ]) signed_attributes = cms.CMSAttributes([ cms.CMSAttribute({ "type": cms.CMSAttributeType("content_type"), "values": cms.SetOfContentType([cms.ContentType("data")]), }), cms.CMSAttribute({ "type": cms.CMSAttributeType("signing_time"), "values": cms.SetOfTime([ cms.Time({ "utc_time": core.UTCTime( datetime.utcnow().replace(tzinfo=timezone.utc)) }) ]), }), cms.CMSAttribute({ "type": cms.CMSAttributeType("message_digest"), "values": cms.SetOfOctetString([core.OctetString(message_digest)]), }), cms.CMSAttribute({ "type": cms.CMSAttributeType("1.2.840.113549.1.9.15"), "values": cms.SetOfAny([core.Any(SmimeCapabilities(smime_cap))]), }), ]) else: signed_attributes = None # Generate the signature data_to_sign = signed_attributes.dump( ) if signed_attributes else data_to_sign if sign_alg == "rsassa_pkcs1v15": signature = asymmetric.rsa_pkcs1v15_sign(sign_key[0], data_to_sign, digest_alg) elif sign_alg == "rsassa_pss": signature = asymmetric.rsa_pss_sign(sign_key[0], data_to_sign, digest_alg) else: raise AS2Exception("Unsupported Signature Algorithm") return cms.ContentInfo({ "content_type": cms.ContentType("signed_data"), "content": cms.SignedData({ "version": cms.CMSVersion("v1"), "digest_algorithms": cms.DigestAlgorithms([ algos.DigestAlgorithm( {"algorithm": algos.DigestAlgorithmId(digest_alg)}) ]), "encap_content_info": cms.ContentInfo({"content_type": cms.ContentType("data")}), "certificates": cms.CertificateSet( [cms.CertificateChoices({"certificate": sign_key[1].asn1})]), "signer_infos": cms.SignerInfos([ cms.SignerInfo({ "version": cms.CMSVersion("v1"), "sid": cms.SignerIdentifier({ "issuer_and_serial_number": cms.IssuerAndSerialNumber({ "issuer": sign_key[1].asn1["tbs_certificate"]["issuer"], "serial_number": sign_key[1].asn1["tbs_certificate"] ["serial_number"], }) }), "digest_algorithm": algos.DigestAlgorithm( {"algorithm": algos.DigestAlgorithmId(digest_alg)}), "signed_attrs": signed_attributes, "signature_algorithm": algos.SignedDigestAlgorithm( {"algorithm": algos.SignedDigestAlgorithmId(sign_alg)}), "signature": core.OctetString(signature), }) ]), }), }).dump()
def _sign(self, datau, key, cert, othercerts, hashalgo, attrs=True, signed_value=None, hsm=None, pss=False, timestampurl=None): if signed_value is None: signed_value = getattr(hashlib, hashalgo)(datau).digest() signed_time = datetime.now(tz=util.timezone.utc) if hsm is not None: keyid, cert = hsm.certificate() cert = cert2asn(cert, False) othercerts = [] else: cert = cert2asn(cert) certificates = [] certificates.append(cert) for i in range(len(othercerts)): certificates.append(cert2asn(othercerts[i])) signer = { 'version': 'v1', 'sid': cms.SignerIdentifier({ 'issuer_and_serial_number': cms.IssuerAndSerialNumber({ 'issuer': cert.issuer, 'serial_number': cert.serial_number, }), }), 'digest_algorithm': algos.DigestAlgorithm({'algorithm': hashalgo}), 'signature': signed_value, } if not pss: signer['signature_algorithm'] = algos.SignedDigestAlgorithm( {'algorithm': 'rsassa_pkcs1v15'}) else: salt_length = padding.calculate_max_pss_salt_length( key, hashes.SHA512) signer['signature_algorithm'] = algos.SignedDigestAlgorithm({ 'algorithm': 'rsassa_pss', 'parameters': algos.RSASSAPSSParams({ 'hash_algorithm': algos.DigestAlgorithm({'algorithm': 'sha512'}), 'mask_gen_algorithm': algos.MaskGenAlgorithm({ 'algorithm': algos.MaskGenAlgorithmId('mgf1'), 'parameters': { 'algorithm': algos.DigestAlgorithmId('sha512'), } }), 'salt_length': algos.Integer(salt_length), 'trailer_field': algos.TrailerField(1) }) }) if attrs: if attrs is True: signer['signed_attrs'] = [ cms.CMSAttribute({ 'type': cms.CMSAttributeType('content_type'), 'values': ('data', ), }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('message_digest'), 'values': (signed_value, ), }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('signing_time'), 'values': (cms.Time({'utc_time': core.UTCTime(signed_time)}), ) }), ] else: signer['signed_attrs'] = attrs config = { 'version': 'v1', 'digest_algorithms': cms.DigestAlgorithms( (algos.DigestAlgorithm({'algorithm': hashalgo}), )), 'encap_content_info': { 'content_type': 'data', }, 'certificates': certificates, # 'crls': [], 'signer_infos': [ signer, ], } datas = cms.ContentInfo({ 'content_type': cms.ContentType('signed_data'), 'content': cms.SignedData(config), }) if attrs: tosign = datas['content']['signer_infos'][0]['signed_attrs'].dump() tosign = b'\x31' + tosign[1:] else: tosign = datau if hsm is not None: signed_value_signature = hsm.sign(keyid, tosign, hashalgo) else: if pss: hasher = hashes.Hash(hashes.SHA512(), backend=backends.default_backend()) hasher.update(tosign) digest = hasher.finalize() signed_value_signature = key.sign( digest, padding.PSS(mgf=padding.MGF1(hashes.SHA512()), salt_length=salt_length), utils.Prehashed(hashes.SHA512())) else: signed_value_signature = key.sign( tosign, padding.PKCS1v15(), getattr(hashes, hashalgo.upper())()) if timestampurl is not None: signed_value = getattr(hashlib, hashalgo)(signed_value_signature).digest() tspreq = tsp.TimeStampReq({ "version": 1, "message_imprint": tsp.MessageImprint({ "hash_algorithm": algos.DigestAlgorithm({'algorithm': hashalgo}), "hashed_message": signed_value, }), "nonce": int(time.time() * 1000), "cert_req": True, }) tspreq = tspreq.dump() tspheaders = {"Content-Type": "application/timestamp-query"} tspresp = requests.post(timestampurl, data=tspreq, headers=tspheaders) if tspresp.headers.get('Content-Type', None) == 'application/timestamp-reply': tspresp = tsp.TimeStampResp.load(tspresp.content) if tspresp['status']['status'].native == 'granted': attrs = [ cms.CMSAttribute({ 'type': cms.CMSAttributeType('signature_time_stamp_token'), 'values': cms.SetOfContentInfo([ cms.ContentInfo({ 'content_type': cms.ContentType('signed_data'), 'content': tspresp["time_stamp_token"]["content"], }) ]) }) ] datas['content']['signer_infos'][0][ 'unsigned_attrs'] = attrs # signed_value_signature = core.OctetString(signed_value_signature) datas['content']['signer_infos'][0][ 'signature'] = signed_value_signature return datas.dump()
async def signatures_sign_hash(self, request: web.Request): params = await request.json() try: cred_id = str(params['credentialID']) sad = params['SAD'] except KeyError: raise web.HTTPBadRequest() csc_auth_obj = CSCAuthorization.verify_sad( sad, secret=self.service_params.sad_secret, credential_id=cred_id) pki_arch, cert_spec = self._parse_credential_id(cred_id) try: priv_key_info = pki_arch.key_set.get_private_key( cert_spec.subject_key) except ConfigurationError as e: raise web.HTTPBadRequest() try: hash_list = [base64.b64decode(x) for x in params['hash']] sign_algo_id = algos.SignedDigestAlgorithmId(params['signAlgo']) except (KeyError, ValueError): raise web.HTTPBadRequest() if csc_auth_obj.hashes is not None: if not set(hash_list).issubset(csc_auth_obj.hashes): raise web.HTTPBadRequest() else: if not len(hash_list) <= csc_auth_obj.num_signatures: raise web.HTTPBadRequest() sign_algo_params = params.get('signAlgoParams', None) if sign_algo_params is not None: if sign_algo_id.native != 'rsassa_pss': raise web.HTTPNotImplemented() try: sign_algo_params = algos.RSASSAPSSParams.load( base64.b64decode(sign_algo_params)) except ValueError: raise web.HTTPBadRequest() try: sign_algo = algos.SignedDigestAlgorithm({ 'algorithm': sign_algo_id, 'parameters': sign_algo_params }) except ValueError: raise web.HTTPBadRequest() hash_algo_oid = params.get('hashAlgo', None) try: hash_algo = sign_algo.hash_algo except ValueError: if hash_algo_oid is None: raise web.HTTPBadRequest() hash_algo = algos.DigestAlgorithmId(hash_algo_oid).native def _sign_hash(x): signed = generic_sign_prehashed(priv_key_info, x, sign_algo, digest_algorithm=hash_algo) return base64.b64encode(signed).decode('ascii') result = list(map(_sign_hash, hash_list)) return web.json_response({'signatures': result})
def sign(datau, key, cert, othercerts, hashalgo, attrs=True, signed_value=None, hsm=None, pss=False, timestampurl=None, timestampcredentials=None, timestamp_req_options=None, ocspurl=None, ocspissuer=None): if signed_value is None: signed_value = getattr(hashlib, hashalgo)(datau).digest() signed_time = datetime.now(tz=util.timezone.utc) if hsm is not None: keyid, cert = hsm.certificate() cert = cert2asn(cert, False) else: cert = cert2asn(cert) certificates = [] certificates.append(cert) for i in range(len(othercerts)): certificates.append(cert2asn(othercerts[i])) hashalgo = unicode(hashalgo) if sys.version[0] < '3' else hashalgo signer = { 'version': 'v1', 'sid': cms.SignerIdentifier({ 'issuer_and_serial_number': cms.IssuerAndSerialNumber({ 'issuer': cert.issuer, 'serial_number': cert.serial_number, }), }), 'digest_algorithm': algos.DigestAlgorithm({'algorithm': hashalgo}), 'signature': signed_value, } if not pss: signer['signature_algorithm'] = algos.SignedDigestAlgorithm( {'algorithm': 'rsassa_pkcs1v15'}) else: if isinstance(key, keys.PrivateKeyInfo): salt_length = key.byte_size - hashes.SHA512.digest_size - 2 salt_length = hashes.SHA512.digest_size else: salt_length = padding.calculate_max_pss_salt_length( key, hashes.SHA512) signer['signature_algorithm'] = algos.SignedDigestAlgorithm({ 'algorithm': 'rsassa_pss', 'parameters': algos.RSASSAPSSParams({ 'hash_algorithm': algos.DigestAlgorithm({'algorithm': 'sha512'}), 'mask_gen_algorithm': algos.MaskGenAlgorithm({ 'algorithm': algos.MaskGenAlgorithmId('mgf1'), 'parameters': { 'algorithm': algos.DigestAlgorithmId('sha512'), } }), 'salt_length': algos.Integer(salt_length), 'trailer_field': algos.TrailerField(1) }) }) if attrs: if attrs is True: signer['signed_attrs'] = [ cms.CMSAttribute({ 'type': cms.CMSAttributeType('content_type'), 'values': ('data', ), }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('message_digest'), 'values': (signed_value, ), }), cms.CMSAttribute({ 'type': cms.CMSAttributeType('signing_time'), 'values': (cms.Time({'utc_time': core.UTCTime(signed_time)}), ) }), ] else: if isinstance(attrs, types.FunctionType): attrs = attrs(signed_value) signer['signed_attrs'] = attrs config = { 'version': 'v1', 'digest_algorithms': cms.DigestAlgorithms((algos.DigestAlgorithm({'algorithm': hashalgo}), )), 'encap_content_info': { 'content_type': 'data', }, 'certificates': certificates, 'signer_infos': [ signer, ], } if ocspurl and ocspissuer: from cryptography.hazmat.backends.openssl.backend import backend from cryptography.x509 import ocsp as cocsp from cryptography import x509 as cx509 ocspuser = cert.dump() ocspuser = cx509.load_der_x509_certificate(ocspuser, backend=backend) builder = cocsp.OCSPRequestBuilder() builder = builder.add_certificate(ocspuser, ocspissuer, hashes.SHA1()) req = builder.build() data = req.public_bytes(serialization.Encoding.DER) response = requests.post( ocspurl, headers={'Content-Type': 'application/ocsp-request'}, data=data, ) data = ocsp.OCSPResponse.load(response.content) other = cms.RevocationInfoChoice({ 'other': cms.OtherRevocationInfoFormat({ 'other_rev_info_format': 'ocsp_response', 'other_rev_info': data }) }) config['crls'] = cms.RevocationInfoChoices([other]) datas = cms.ContentInfo({ 'content_type': cms.ContentType('signed_data'), 'content': cms.SignedData(config), }) if attrs: tosign = datas['content']['signer_infos'][0]['signed_attrs'].dump() tosign = b'\x31' + tosign[1:] else: tosign = datau if hsm is not None: signed_value_signature = hsm.sign(keyid, tosign, hashalgo) elif isinstance(key, keys.PrivateKeyInfo): key = asymmetric.load_private_key(key) if pss: signed_value_signature = asymmetric.rsa_pss_sign( key, tosign, 'sha512') else: signed_value_signature = asymmetric.rsa_pkcs1v15_sign( key, tosign, hashalgo.lower()) else: if pss: hasher = hashes.Hash(hashes.SHA512(), backend=backends.default_backend()) hasher.update(tosign) digest = hasher.finalize() signed_value_signature = key.sign( digest, padding.PSS(mgf=padding.MGF1(hashes.SHA512()), salt_length=salt_length), utils.Prehashed(hashes.SHA512())) else: signed_value_signature = key.sign( tosign, padding.PKCS1v15(), getattr(hashes, hashalgo.upper())()) if timestampurl is not None: datas['content']['signer_infos'][0]['unsigned_attrs'] = timestamp( signed_value_signature, hashalgo, timestampurl, timestampcredentials, timestamp_req_options, ) # signed_value_signature = core.OctetString(signed_value_signature) datas['content']['signer_infos'][0]['signature'] = signed_value_signature #open('signed-content-info', 'wb').write(datas.dump()) return datas.dump()