TransWikia.com

Signing CSR using an ECC keypair

Information Security Asked on December 28, 2021

I’m trying to sign a CSR using python-asn1crypto and python-pkcs11. I have an ECC Keypair stored in a Hardware Security Module (HSM).

Here’s a code sample:

key = decode_ec_public_key(encode_ec_public_key(pub))

info = CertificationRequestInfo({
    'version': 0,
    'subject': Name.build(subject),
    'subject_pk_info': {
          'algorithm': {
                 'algorithm': 'ec',
                  'parameters': ECDomainParameters.load(key[Attribute.EC_PARAMS]),
                },
          'public_key': bytes(OctetString.load(key[Attribute.EC_POINT])),
     },
})

# Sign the CSR Info
value = priv.sign(info.dump(), mechanism=Mechanism.ECDSA_SHA1)

csr = CertificationRequest({
    'certification_request_info': info,
    'signature_algorithm': {
        'algorithm': 'sha1_ecdsa',
        'parameters': None,
     },
    'signature': value,
 })

When I verify the csr signature with OpenSSL(openssl req -text -noout -verify -in CSR.csr), I get the following error:

140140027905152:error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag:../crypto/asn1/tasn_dec.c:1130:
140140027905152:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:290:Type=ECDSA_SIG
140140027905152:error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib:../crypto/asn1/a_verify.c:170:

Note that I can see the CSR information using openssl req -in csr.pem -noout -text:

Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: serialNumber = 123456, O = No, CN = Name
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:a5:76:62:fe:ae:33:2f:42:f6:ff:50:69:1d:7d:
                    5e:48:64:6f:84:e0:11:46:a3:6b:91:43:db:f1:ab:
                    76:e9:8f:c8:d5:a4:6f:80:a1:87:06:6d:1d:1d:9e:
                    40:55:a7:5d:84:07:c7:c9:b7:0f:cf:ad:b8:fd:5f:
                    74:d7:5c:7b:1c
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        Attributes:
    Signature Algorithm: ecdsa-with-SHA1
         9c:3c:13:1e:6a:de:6a:89:5b:6f:8b:90:0c:c6:ff:03:9d:e9:
         3f:31:49:67:72:97:f4:4b:cc:50:21:50:db:dd:69:33:61:a7:
         79:b6:19:c3:0f:51:cf:3f:18:4c:98:de:f5:f7:cb:9e:c5:9c:
         a7:b9:90:7d:e7:a5:e7:03:27:a3

I think that I’m not using the proper signature mechanism. python-pkcs11 module provide (via asn1crypto I believe) all these mechanisms:

['ACTI', 'ACTI_KEY_GEN', 'AES_CBC', 'AES_CBC_ENCRYPT_DATA', 'AES_CBC_PAD', 'AES_CCM', 'AES_CFB1', 'AES_CFB128', 'AES_CFB64', 'AES_CFB8', 'AES_CMAC', 'AES_CMAC_GENERAL', 'AES_CTR', 'AES_CTS', 'AES_ECB', 'AES_ECB_ENCRYPT_DATA', 'AES_GCM', 'AES_GMAC', 'AES_KEY_GEN', 'AES_KEY_WRAP', 'AES_KEY_WRAP_PAD', 'AES_MAC', 'AES_MAC_GENERAL', 'AES_OFB', 'AES_XCBC_MAC', 'AES_XCBC_MAC_96', 'BLOWFISH_CBC', 'BLOWFISH_CBC_PAD', 'BLOWFISH_KEY_GEN', 'CMS_SIG', 'CONCATENATE_BASE_AND_DATA', 'CONCATENATE_BASE_AND_KEY', 'CONCATENATE_DATA_AND_BASE', 'DES2_KEY_GEN', 'DES3_CBC', 'DES3_CBC_ENCRYPT_DATA', 'DES3_CBC_PAD', 'DES3_CMAC', 'DES3_CMAC_GENERAL', 'DES3_ECB', 'DES3_ECB_ENCRYPT_DATA', 'DES3_KEY_GEN', 'DES3_MAC', 'DES3_MAC_GENERAL', 'DES_CBC_ENCRYPT_DATA', 'DES_ECB_ENCRYPT_DATA', 'DH_PKCS_DERIVE', 'DH_PKCS_KEY_PAIR_GEN', 'DH_PKCS_PARAMETER_GEN', 'DSA', 'DSA_KEY_PAIR_GEN', 'DSA_PARAMETER_GEN', 'DSA_SHA1', 'DSA_SHA224', 'DSA_SHA256', 'DSA_SHA384', 'DSA_SHA512', 'ECDH1_COFACTOR_DERIVE', 'ECDH1_DERIVE', 'ECDSA', 'ECDSA_SHA1', 'ECDSA_SHA224', 'ECDSA_SHA256', 'ECDSA_SHA384', 'ECDSA_SHA512', 'ECMQV_DERIVE', 'EC_EDWARDS_KEY_PAIR_GEN', 'EC_KEY_PAIR_GEN', 'EDDSA', 'EXTRACT_KEY_FROM_KEY', 'GENERIC_SECRET_KEY_GEN', 'GOST28147', 'GOST28147_ECB', 'GOST28147_KEY_GEN', 'GOST28147_KEY_WRAP', 'GOST28147_MAC', 'GOSTR3410', 'GOSTR3410_DERIVE', 'GOSTR3410_KEY_PAIR_GEN', 'GOSTR3410_KEY_WRAP', 'GOSTR3410_WITH_GOSTR3411', 'GOSTR3411', 'GOSTR3411_HMAC', 'HOTP', 'HOTP_KEY_GEN', 'KIP_DERIVE', 'KIP_MAC', 'KIP_WRAP', 'MD2_RSA_PKCS', 'MD5_RSA_PKCS', 'PKCS5_PBKD2', 'RSA_9796', 'RSA_PKCS', 'RSA_PKCS_KEY_PAIR_GEN', 'RSA_PKCS_OAEP', 'RSA_PKCS_OAEP_TPM_1_1', 'RSA_PKCS_PSS', 'RSA_PKCS_TPM_1_1', 'RSA_X9_31', 'RSA_X9_31_KEY_PAIR_GEN', 'RSA_X_509', 'SECURID', 'SECURID_KEY_GEN', 'SEED_CBC', 'SEED_CBC_ENCRYPT_DATA', 'SEED_CBC_PAD', 'SEED_ECB', 'SEED_ECB_ENCRYPT_DATA', 'SEED_KEY_GEN', 'SEED_MAC', 'SEED_MAC_GENERAL', 'SHA1_KEY_DERIVATION', 'SHA1_RSA_PKCS', 'SHA1_RSA_PKCS_PSS', 'SHA1_RSA_X9_31', 'SHA224', 'SHA224_HMAC', 'SHA224_HMAC_GENERAL', 'SHA224_KEY_DERIVATION', 'SHA224_RSA_PKCS', 'SHA224_RSA_PKCS_PSS', 'SHA256', 'SHA256_HMAC', 'SHA256_HMAC_GENERAL', 'SHA256_KEY_DERIVATION', 'SHA256_RSA_PKCS', 'SHA256_RSA_PKCS_PSS', 'SHA384', 'SHA384_HMAC', 'SHA384_HMAC_GENERAL', 'SHA384_KEY_DERIVATION', 'SHA384_RSA_PKCS', 'SHA384_RSA_PKCS_PSS', 'SHA512', 'SHA512_HMAC', 'SHA512_HMAC_GENERAL', 'SHA512_KEY_DERIVATION', 'SHA512_RSA_PKCS', 'SHA512_RSA_PKCS_PSS', 'SHA_1', 'SHA_1_HMAC', 'SHA_1_HMAC_GENERAL', 'SSL3_KEY_AND_MAC_DERIVE', 'SSL3_MASTER_KEY_DERIVE', 'SSL3_MASTER_KEY_DERIVE_DH', 'SSL3_MD5_MAC', 'SSL3_PRE_MASTER_KEY_GEN', 'SSL3_SHA1_MAC', 'TLS_KEY_AND_MAC_DERIVE', 'TLS_MASTER_KEY_DERIVE', 'TLS_MASTER_KEY_DERIVE_DH', 'TLS_PRE_MASTER_KEY_GEN', 'TLS_PRF', 'TWOFISH_CBC', 'TWOFISH_CBC_PAD', 'TWOFISH_KEY_GEN', 'WTLS_CLIENT_KEY_AND_MAC_DERIVE', 'WTLS_MASTER_KEY_DERIVE', 'WTLS_MASTER_KEY_DERIVE_DH_ECC', 'WTLS_PRE_MASTER_KEY_GEN', 'WTLS_PRF', 'WTLS_SERVER_KEY_AND_MAC_DERIVE', 'X9_42_DH_DERIVE', 'X9_42_DH_HYBRID_DERIVE', 'X9_42_DH_KEY_PAIR_GEN', 'X9_42_DH_PARAMETER_GEN', 'X9_42_MQV_DERIVE', 'XOR_BASE_AND_DATA', '_ARIA_CBC', '_ARIA_CBC_ENCRYPT_DATA', '_ARIA_CBC_PAD', '_ARIA_ECB', '_ARIA_ECB_ENCRYPT_DATA', '_ARIA_KEY_GEN', '_ARIA_MAC', '_ARIA_MAC_GENERAL', '_BATON_CBC128', '_BATON_COUNTER', '_BATON_ECB128', '_BATON_ECB96', '_BATON_KEY_GEN', '_BATON_SHUFFLE', '_BATON_WRAP', '_CAMELLIA_CBC', '_CAMELLIA_CBC_ENCRYPT_DATA', '_CAMELLIA_CBC_PAD', '_CAMELLIA_CTR', '_CAMELLIA_ECB', '_CAMELLIA_ECB_ENCRYPT_DATA', '_CAMELLIA_KEY_GEN', '_CAMELLIA_MAC', '_CAMELLIA_MAC_GENERAL', '_CAST3_CBC', '_CAST3_CBC_PAD', '_CAST3_ECB', '_CAST3_KEY_GEN', '_CAST3_MAC', '_CAST3_MAC_GENERAL', '_CAST5_CBC', '_CAST5_CBC_PAD', '_CAST5_ECB', '_CAST5_KEY_GEN', '_CAST5_MAC', '_CAST5_MAC_GENERAL', '_CAST_CBC', '_CAST_CBC_PAD', '_CAST_ECB', '_CAST_KEY_GEN', '_CAST_MAC', '_CAST_MAC_GENERAL', '_CDMF_CBC', '_CDMF_CBC_PAD', '_CDMF_ECB', '_CDMF_KEY_GEN', '_CDMF_MAC', '_CDMF_MAC_GENERAL', '_DES_CBC', '_DES_CBC_PAD', '_DES_CFB64', '_DES_CFB8', '_DES_ECB', '_DES_KEY_GEN', '_DES_MAC', '_DES_MAC_GENERAL', '_DES_OFB64', '_DES_OFB8', '_FASTHASH', '_FORTEZZA_TIMESTAMP', '_IDEA_CBC', '_IDEA_CBC_PAD', '_IDEA_ECB', '_IDEA_KEY_GEN', '_IDEA_MAC', '_IDEA_MAC_GENERAL', '_JUNIPER_CBC128', '_JUNIPER_COUNTER', '_JUNIPER_ECB128', '_JUNIPER_KEY_GEN', '_JUNIPER_SHUFFLE', '_JUNIPER_WRAP', '_KEA_KEY_DERIVE', '_KEA_KEY_PAIR_GEN', '_KEY_WRAP_LYNKS', '_KEY_WRAP_SET_OAEP', '_MD2', '_MD2_HMAC', '_MD2_HMAC_GENERAL', '_MD2_KEY_DERIVATION', '_MD5', '_MD5_HMAC', '_MD5_HMAC_GENERAL', '_MD5_KEY_DERIVATION', '_PBA_SHA1_WITH_SHA1_HMAC', '_PBE_MD2_DES_CBC', '_PBE_MD5_CAST3_CBC', '_PBE_MD5_CAST5_CBC', '_PBE_MD5_CAST_CBC', '_PBE_MD5_DES_CBC', '_PBE_SHA1_CAST5_CBC', '_PBE_SHA1_DES2_EDE_CBC', '_PBE_SHA1_DES3_EDE_CBC', '_PBE_SHA1_RC2_128_CBC', '_PBE_SHA1_RC2_40_CBC', '_PBE_SHA1_RC4_128', '_PBE_SHA1_RC4_40', '_RC2_CBC', '_RC2_CBC_PAD', '_RC2_ECB', '_RC2_KEY_GEN', '_RC2_MAC', '_RC2_MAC_GENERAL', '_RC4', '_RC4_KEY_GEN', '_RC5_CBC', '_RC5_CBC_PAD', '_RC5_ECB', '_RC5_KEY_GEN', '_RC5_MAC', '_RC5_MAC_GENERAL', '_RIPEMD128', '_RIPEMD128_HMAC', '_RIPEMD128_HMAC_GENERAL', '_RIPEMD128_RSA_PKCS', '_RIPEMD160', '_RIPEMD160_HMAC', '_RIPEMD160_HMAC_GENERAL', '_RIPEMD160_RSA_PKCS', '_SKIPJACK_CBC64', '_SKIPJACK_CFB16', '_SKIPJACK_CFB32', '_SKIPJACK_CFB64', '_SKIPJACK_CFB8', '_SKIPJACK_ECB64', '_SKIPJACK_KEY_GEN', '_SKIPJACK_OFB64', '_SKIPJACK_PRIVATE_WRAP', '_SKIPJACK_RELAYX', '_SKIPJACK_WRAP', '_VENDOR_DEFINED', '__class__', '__doc__', '__members__', '__module__']

But I’m not sure which one I should use (I’ve used ECDSA_SHA1 to generate the CSR above).

2 Answers

The signature format was not correct, I've added the following:

from asn1crypto.algos import DSASignature

signature = priv.sign(info.dump(),
                            mechanism=Mechanism.ECDSA_SHA1)

value = DSASignature.from_p1363(signature).dump()
csr = CertificationRequest({
                'certification_request_info': info,
                'signature_algorithm': {
                    'algorithm': 'sha1_ecdsa',
                    'parameters': None,
                },
                'signature': value,
            })

Answered by No name on December 28, 2021

PKCS11 (and also P1363) formats ECDSA signature by concatenating the two numbers r,s encoded as fixed-size unsigned; for P-256 that size is 32 octets giving signature of 64 octets.

PKCS10, like X.509/PKIX, formats ECDSA signature as an ASN.1 SEQUENCE of two INTEGERs; each INTEGER in ASN.1 DER is variable-size signed (technically two's complement, but since ECDSA r,s are never negative that part doesn't matter). I'm not familiar with python-asn1crypto nor did you give a link, but I'd expect something with that name to be able to cope with this case. Look for ECDSA-Sig or ECDSA-Sig-Value or similar; see e.g. https://www.rfc-editor.org/rfc/rfc3279#section-2.2.3

Meta: I'm sure I've seen the core of this (maybe without python) several times and answered at least one or two of them, but search isn't finding any decent dupe(s).

Answered by dave_thompson_085 on December 28, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP