0

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

No name
  • 93
  • 7

2 Answers2

1

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

dave_thompson_085
  • 9,759
  • 1
  • 24
  • 28
0

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,
            })
No name
  • 93
  • 7