Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
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()
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
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()
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
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()
Ejemplo n.º 8
0
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()
Ejemplo n.º 9
0
    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()
Ejemplo n.º 10
0
    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})
Ejemplo n.º 11
0
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()