smallstep/certificates

Problem with enrollment on cisco router

Opened this issue · 11 comments

I tried to make a lab with an IpSec VPN between 2 Cisco 2800 routers (old, with only SHA1 hash) with a scep auto enrollment. I have to use an Ubuntu server for the CA so i decided to use smallstep CA to provide a scep server. I've managed to get the CA certificate with the Cisco command 'crypto pki authenticate trustpoint_name' but when i tried to enroll the trustpoint, it failed with this message on the CA console :
ERRO[0136] duration="891.927µs" duration-ns=891927 error="scep get request failed: failed parsing SCEP request: pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported" fields.time="2024-12-10T17:15:46+01:00" method=GET name=ca path="/scep/myscep/pkiclient.exe?operation=PKIOperation&message=MIIJIQYJKoZIhvcNAQcCoIIJEjCCCQ4CAQExDjAMBggqhkiG9w0CBQUAMIIEUQYJ%0AKoZIhvcNAQcBoIIEQgSCBD4wggQ6BgkqhkiG9w0BBw.............D%0A" protocol=HTTP/1.0 referer= remote-address=10.0.0.1 request-id=a619b201-9f6f-421b-a2a4-bc4387dfa81d size=145 status=500 user-agent= user-id=

I tried with an sscep client on computer and it worked.

My cisco pki configuration :
crypto pki trustpoint ubo

enrollment url http://10.0.0.3:8080/scep/myscep

password 7 071F205F5D1E161713

subject-name CN=testubo

revocation-check none

My ca.json configuration :
{
"root": "/root/.step/certs/root_ca.crt",
"federatedRoots": null,
"crt": "/root/.step/certs/intermediate_ca.crt",
"key": "/root/.step/secrets/intermediate_ca_key",
"address": "127.0.0.1:2016",
"insecureAddress": ":8080",
"dnsNames": [
"127.0.0.1"
],
"logger": {
"format": "text"
},
"db": {
"type": "badgerv2",
"dataSource": "/root/.step/db",
"badgerFileLoadingMode": ""
},
"authority": {
"provisioners": [
{
"type": "JWK",
"name": "hadri",
"key": {
"use": "sig",
"kty": "EC",
"kid": "ZKDSXDysfztANIZueMO_096snANaOuEUtWl9cgai5fE",
"crv": "P-256",
"alg": "ES256",
"x": "tn9PZeoUKL2vXKwFLXWd8LZch77-zOMrm93nQJFTlCg",
"y": "T0PH8G9lyD8oWtK18bsPuZmPiPjQY87dSUH7i8rvJcg"
},
"encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjYwMDAwMCwicDJzIjoiaUFfZWkwVGlydmxOaTM3OXBCMlJKdyJ9.lsY8nFtzYh307PTpGs5C5pwhPGcDg1ZxVFz55ARZ3XkkHZ7pR-QpJw.9G2TSpkmvOCtr9a6.ra_JlginsSciJ6DDvCGS-uF74jWsKGXV5qGoXocVI7Ky9aqrX0_WI0cz2X7aBZt0Fvj6Wv_hfzyKjPPC3vgONx_2dZENWpoP0dGUyHyajzSILQGVnGINtLVnFFFv-REAgN0eCTqt1QyFUCULVbT3v59h1g2phGYf59iVOBeCmVGmU9wHW_BRvKHUA6xOA8uH2HqCKYyriFFs3rq0GieN-4zKXmYKWsEoLK5Dw7KfuYDFSP8HIcrnfnhmopk-MsLLzpTHuyT_GZ2tSlqG-5C0pgbahKqzfVNOXc3Avmpjk6vStfM8hSo_skJUtFWWzVlQVUaWD-OboRsy4_EIj8E.AkgSCuulaRt9-myVvr5kVg"
},
{
"type": "SCEP",
"name": "myscep",
"minimumPublicKeyLength": 1024,
"encryptionAlgorithmIdentifier": 2,
"challenge":"pipi",
"forceCN": true,
"options": {
"x509": {},
"ssh": {}
},
"claims": {
"enableSSHCA": true,
"disableRenewal": false,
"allowRenewalAfterExpiry": false,
"disableSmallstepExtensions": false
}
}
],
"template": {},
"backdate": "1m0s"
},
"tls": {
"cipherSuites": [
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
],
"minVersion": 1.2,
"maxVersion": 1.3,
"renegotiation": false
},
"commonName": "Step Online CA"
}

The error from the router :
Dec 10 17:16:26.619: CRYPTO_PKI: unlocked trustpoint ubo, refcount is e

Dec 10 17:16:26.623: CRYPTO_PKI: locked trustpoint ubo, refcount is 1

Dec 10 17:16:26.627: CRYPTO_PKI: unlocked trustpoint ubo , refcount is

Dec 10 17:16:26.627: CRYPTO_PKI: received msg of 367 bytes

Dec 10 17:16:26.627: CRYPTO PKI: HTTP header:

HTTP/1.0 500 Internal Server Error

Content-Type: text/plain; charset=utf-8

X-Content-Type-Options: nosniff

X-Request-Id: a619b201-9f6f-421b-a2a4-bc4387dfa81d

Date: Tue, 10 Dec 2024 16:15:46 GMT

Content-Length: 145

Dec 10 17:16:26.627: CRYPTO PKI: Received pki message (PKCS7) for trustpoint ubo: 145 bytes

73 63 65 70 20 67 65 74 20 72 65 71 75 65 73 74

20 66 61 69 60 65 64 3A 20 66 61 69 60 65 64 20

70 61 72 73

75 65 73 74

69 68 67 20 53 43 45 50 20 72 65 71

3A 20 70 68 63 73 37 3A 28 63 61 6E

6E 6F 74 20 64 65 63 72 79 70 74 20 64 61 74 61

3A 20 6F 6E 6C 79 20 52 53 41 20 20 44 45 53 20

20 44 45 53 20 45 44 45 33 20 20 41 45 53 20 32

35 36 20 43 42 43 20 61 6E 64 20 41 45 53 2D 31

32 38 20 47 43 40 20 73 75 70 70 6F 72 74 65.64

BA

Dec 10 17:16:26.631: CRYPTO PKI: make trustedCerts list for ubo

Dec 10 17:16:26.631: CRYPTO_PKI: subject="cn=intermediate CA" serial number 51 DA IF 95 EA 29 C5 C8 A8 49 24 35 60 OF 20 FE

Dec 18 17:16:26.635: E/cert-c/source/p7contnt.c(167): Error #703h

Dec 10 17:16:26.635: pkcs7 verify data returned status 0x703

Dec 10 17:16:26.635: CRYPTO PKI: status 1795: failed to verify

Dec 10 17:16:26.635: CRYPTO PKI: status 1795: failed to process the inner content

Dec 10 17:16:26.635: %PKI-6-CERTFAIL: Certificate enrollment failed.

Dec 10 17:16:26:635: CRYPTO_PKI: All enrollment requests completed for trustpoint ubo.

Dec 18 17:16:26.635: CRYPTO PKI: All enrollment requests completed for trustpoint ubo.

Dec 10 17:16:26.635: CRYPTO PKI: All enrollment requests completed for trustpoint ubo.

Dec 10 17:16:26.639: CRYPTO_PKI: All enrollment requests completed for trustpoint ubo.

Thanks by advance.

Are you using an RSA intermediate CA? If you don't know, can you show the output of step certificate inspect /root/.step/certs/intermediate_ca.crt? If sscep worked I think the answer is yes, but I just want to verify.

Can you try if you can get the contents of the request (the whole message=... part) and share it? It sounds like the message may be encrypted using an algorithm that our server doesn't currently support.

Are you using an RSA intermediate CA? If you don't know, can you show the output of step certificate inspect /root/.step/certs/intermediate_ca.crt? If sscep worked I think the answer is yes, but I just want to verify.

Can you try if you can get the contents of the request (the whole message=... part) and share it? It sounds like the message may be encrypted using an algorithm that our server doesn't currently support.

Hello, yes im using an RSA intermediate CA, here the output of the command :
root@pipi-VirtualBox:/home/pipi# step certificate inspect /root/.step/certs/intermediate_ca.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 108800029005902698219868613108430733566 (0x51da1f95ea29c5c8a8492435600f00fe)
Signature Algorithm: SHA1-RSA
Issuer: CN=Root_CA
Validity
Not Before: Dec 9 15:35:42 2024 UTC
Not After : Dec 10 03:35:39 2034 UTC
Subject: CN=intermediate_CA
Subject Public Key Info:
Public Key Algorithm: RSA
Public-Key: (2048 bit)
Modulus:
b9:1a:e1:ce:5c:ac:f3:fb:67:e4:7f:71:4f:05:79:
f0:0e:bb:26:dd:f2:03:de:16:13:8d:45:05:9d:83:
5f:1b:8d:03:44:b6:42:f1:da:df:96:23:e7:a9:35:
fb:16:fc:86:9d:d6:15:58:62:7f:1f:2f:3a:c6:a7:
38:f8:51:90:34:cd:06:3c:3f:84:d7:b1:3b:96:a5:
36:7d:c9:e1:c6:7c:10:ad:ae:55:cc:11:dc:6b:19:
87:86:07:49:26:9f:c5:16:ef:53:f3:5c:f4:ee:65:
d6:3f:cb:f5:49:2a:44:7a:4d:11:7d:ed:d1:af:8d:
06:87:a9:c4:f1:db:c2:0a:48:e7:c9:bb:33:43:43:
9a:6c:06:a9:41:2e:05:bf:3d:f5:39:be:02:e7:fc:
a5:21:c2:c6:5e:05:2f:f8:02:38:c9:fb:f4:f9:d9:
62:c7:cd:dc:44:93:0e:17:cb:1e:a2:67:39:b0:f8:
4a:07:5e:39:7e:f8:89:fc:9a:25:3d:3f:e9:3c:70:
d2:9a:7c:75:df:d9:d4:2e:a8:c4:3c:92:be:13:5d:
80:18:c5:3c:35:de:68:3b:4d:01:30:5b:f0:9a:b3:
90:61:22:8c:a0:f5:c7:03:44:eb:85:b9:1e:bd:a7:
df:4c:01:47:12:43:c0:59:28:66:15:b5:1a:99:fd:
31
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Subject Key Identifier:
17:B8:6A:91:58:22:84:2D:DB:08:1B:F2:D2:65:7F:7C:A9:88:47:37
X509v3 Authority Key Identifier:
keyid:6F:EE:15:FD:38:14:5C:2B:E7:13:F5:F3:BD:71:DF:8B:5F:DF:62:2C
Signature Algorithm: SHA1-RSA
8a:2c:ee:37:ee:e5:bf:2d:94:9e:0e:a5:a9:b8:6f:ff:ec:92:
f3:1c:4a:68:44:17:95:18:1b:fb:b4:4b:b8:54:dd:0e:19:1a:
57:a0:e7:3c:cb:ba:e2:5b:12:c7:da:af:39:f4:6a:8a:0f:bf:
01:99:e5:18:44:a9:ad:2a:9c:4d:82:35:56:cc:95:41:0b:96:
62:18:1d:6d:2f:81:d5:4f:07:ef:d4:9c:08:4d:7d:67:dd:0f:
59:6b:a3:ea:95:89:50:9d:cd:a1:61:66:5d:ce:14:bb:81:e1:
40:fe:d1:38:a2:8a:71:15:f4:31:33:25:aa:49:cb:2c:50:62:
2e:56:4c:f5:3d:8f:b5:b3:f9:70:66:29:88:28:6f:3c:e3:24:
67:7e:df:5d:c0:79:49:dd:82:a3:cc:fc:da:2b:9f:e9:6b:23:
aa:4d:80:8c:e8:43:55:01:56:5e:b4:c4:6c:64:de:a0:ca:79:
ca:44:37:1d:99:33:cb:ce:38:24:b0:f6:f5:9f:d2:92:1f:0c:
7d:59:27:30:85:d3:fa:e5:3d:53:ce:be:89:1a:1b:92:dd:e7:
c6:57:24:8f:f8:b2:41:38:a5:dd:65:93:68:1e:d3:61:72:c9:
3e:f9:58:74:4b:3d:d1:ad:d0:a2:24:c0:f4:41:65:49:14:18:
34:2a:1d:86

and here the full content error message :
ERRO[0136] duration="891.927µs" duration-ns=891927 error="scep get request failed: failed parsing SCEP request: pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported" fields.time="2024-12-10T17:15:46+01:00" method=GET name=ca path="/scep/myscep/pkiclient.exe?operation=PKIOperation&message=MIIJIQYJKoZIhvcNAQcCoIIJEjCCCQ4CAQExDjAMBggqhkiG9w0CBQUAMIIEUQYJ%0AKoZIhvcNAQcBoIIEQgSCBD4wggQ6BgkqhkiG9w0BBwOgggQrMIIEJwIBADGCAUIw%0AggE%2BAgEAMCYwEjEQMA4GA1UEAwwHUm9vdF9DQQIQUdofleopxcioSSQ1YA8A%2FjAN%0ABgkqhkiG9w0BAQEFAASCAQAMSD%2FfLntfEyYGC7TiPaRE3t%2BBWKEh37tbgYWqnxmo%0ABNNClnUTZU9YY%2FEcTXDExK5Vvr%2FrjN9XTmvTZnqCpf3LSCOZ7PRwoVSobmyXTcPf%0A95Sx9uY8rMo%2B8WVK59QN8pIFyP1rlbNTmcFJ%2FgV7KYiXQm4z7CwT2xLv8EZUDvVP%0Aa6KKQ8TZzBlR1Lt9tcF5DCyQS02lD1QBPel1406seaZ5EC2IsQX8AQhAJku7nptI%0ARkBLDc2q0019iLTi7skltrL8PsD%2BW73OYgJx00c7G9CtSaFIiFHcTJd1nB%2Bx%2FeO%2F%0A6ePxjbAleK71zjN0fRoVRa%2BfymA1c3yLT2QR2Odoog1xMIIC2gYJKoZIhvcNAQcB%0AMBEGBSsOAwIHBAjeZdhhCcAAmICCArhL7mKrmkaK2bMquFj4vm%2FjCwXgpzwb4AY1%0AVKxMJfx4jkaWWmbZgPHFp56eJJ2qHj5BNLgkfh8968EOkignKDNnZta8PZgAmLNd%0Ai%2BpclZk1u5os4YaeenkBWfv0LV4k%2FwtTG0UxjhririYiiD%2BstFXCMf9OjTlufbSo%0Ad8uXeDMFRBWlmhAR7S6xzq3hRlSRWIakmaBbHUI6NFUJpQsNwJZLU1kHyR3Uuzmg%0A4H5lrn3XR%2BYIlPxdMj4YmlBuukeveLeg%2FFEhs03P359nQsxj7JDc4SUWt1Fo3%2BVb%0A3ea4%2FLIY09zTRSjwEKbewZk8QxvImQwhEITsCLpESDEn8U%2FaZBnJxhIc0Ba0ATfQ%0AeqFKtz18Mr6WLn94Giluy8J2RMuUMZW61MXe2qzv1Bzb6mkacWn1W%2BdlzPFVXEE7%0A3qoB5GhkQyyl2PYxscI5drEI07EiIzwAzMyoCbrfYaMY6vkYAj%2FcPCxEGLrAyh9y%0AUW1l%2FoiewNyG5HBs1wETEMeiu0eP5HYwSFaQtbj%2BWs3jlW%2Bi%2B2fsee%2FjetP48p7q%0AKTQFeXyi4AJy6lhsblSyOLbaq9Rw9WIgvA3sfqRSbtjNecc8oY7i2ZC6NW99DD3f%0A3AFq%2FXcbWA89zrjzvpK3PnUQIQ2KG8wxI63hnHhvXZnquxWFbJ3grKn4kVgaiDnm%0ATEBzWKst5ti2pRm2oQI13IIpuvQA4k2yUisWkhNFrDka2LiXNFVbcDGITjdJP0Tu%0AgGgadjvYp%2BuA5CUYZSvUpmee1dw4mui5WhFzTwFajgMURrYjuUXD8WXvPlU3M5hO%0AL7P0%2FzBwZFxlaHQiVJDCe5Xj7m4ORTf7wToV1ZFSwo5qQoZKk04JKSzYr28ynraj%0A10mdhCFHfDBhBugOvOUjD08OImDRCQ9Zc%2FgWtymxZCQBp9S2Jgk8TX9uq9sDkhmg%0AggKuMIICqjCCAZICAQcwDQYJKoZIhvcNAQEEBQAwGzEZMBcGCSqGSIb3DQEJAhYK%0AdWJvLnViby5mcjAeFw0yNDEyMTAxNzE2MjNaFw0zNDEyMDgxNzE2MjNaMBsxGTAX%0ABgkqhkiG9w0BCQIWCnViby51Ym8uZnIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw%0AggEKAoIBAQCxaFsKwajboZsbMFvZs7hrw94VKoD2YSN5GLY8pNWTGNSz3SrAG3FY%0AEGwBA%2F%2FgTL11eXYldXnCLaUds6lWEoTkiN5qpzs37O7N%2FYOG6BKCghnULlXMCTY0%0AY92l61%2BOK6lX6afL62OkK1oI%2Bq0YqbGGfKEhXnXkRGYhUr0p8j4MJU5RAC2gfphy%0Azwo1Kcxn9WwdeTCIoyr3Lditj6skPLqHEHdb3wpwHP62qinnHmVWPNcsk9lnFtfd%0Ak0e%2B1sScL%2BW%2FPl6qaOZylFlK3mEgX8O1%2Bi7X8gii2zK%2B%2Bw8M%2Bf93hroDuTDSLeQv%0AGcTZ%2F8P1jtcunvmK9ALt2OjFbU%2F%2BC%2BiPAgMBAAEwDQYJKoZIhvcNAQEEBQADggEB%0AAJatOOxLJ%2B1Fm4tHrdQ%2BPgC2KXaccKg9e4qfPVzvBqK5GAuwhp3Y5YnuujWdDRjb%0Asp2MU4mEWv%2BUFTp8D97SfLwl9rgYW0fo2ROUbu5G4JNbIZOdfZIkb2ImlQjlh%2FpX%0AVdU%2FDIsCWkIVv8%2BQPat2hR17%2FJS9zBUi2KmtnyFE7d5P3P5jTK8fAZO69JXohXys%0AtqKZLLj4U5Yu3L8U70fkanQTjXYcbGg5rs3cWBt5s8TCmdVH43AUp9hwh8XPdgao%0AtVIV%2FCu5j69iPGMLxeQrHBbqNTt0rYJg%2Ffgmty4JzIe5E5lDBRqNdp6RHIJrAr8e%0AHCpKXI%2FuX%2F9VWxFA3UuZ%2Bz4xggHwMIIB7AIBATAgMBsxGTAXBgkqhkiG9w0BCQIW%0ACnViby51Ym8uZnICAQcwDAYIKoZIhvcNAgUFAKCBozASBgpghkgBhvhFAQkCMQQT%0AAjE5MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHwYJKoZIhvcNAQkEMRIEEJ%2Fq%0A6RNwhjHhHXhDzf9oliMwIAYKYIZIAYb4RQEJBTESBBCZHQtFs6Ln2R8l9%2FvbUMrr%0AMDAGCmCGSAGG%2BEUBCQcxIhMgRTk2RjhGMjM4N0U5RTdDQjREOEQwQjdFQUQwNjJC%0AQTgwDQYJKoZIhvcNAQEBBQAEggEAfxFMk1QD0uYeZXSnkrEiZbueT27pBVgkoZPn%0A%2BPdHjNXkRm%2FW2mOBomkW1q5Z%2FvN44NMZifbaT9TzYiZCLMk4vRmfxMTkEJ%2F9S7SI%0Agh1z3ja2dWGs6%2BOFqLpFYjuD0nE%2BEtZD4Kfz0c71%2FXqC9m9gxkG5BVyOv17jtXx7%0AonuMsCRUwJ7nZ4oGC%2FmFT3o3tDcEY0PfMqiuHH%2B4jSbBImZO5IKYQkv2XFxd2yDt%0An1azc29Zwl2TW5bSImIY2MOMv7XAg08aad%2FkWi%2B1vMA4XX2IDIh%2BS2MIcCnThQl6%0ArLRbpCxPcd09MKFa27LDLeAV9LKg%2BywskW%2BmPxu8806zb3%2B4pA%3D%3D%0A" protocol=HTTP/1.0 referer= remote-address=10.0.0.1 request-id=a619b201-9f6f-421b-a2a4-bc4387dfa81d size=145 status=500 user-agent= user-id=

According to the request parsed, it seems DES-CBC is used as the encryption algorithm. Its OID seems to be in the list of supported algorithms, but somehow it fails to be seen as a supported algorithm.

I'll try to see if I can debug using pkcs7 directly.

Also see the below:

https://lapo.it/asn1js/#MIIJIQYJKoZIhvcNAQcCoIIJEjCCCQ4CAQExDjAMBggqhkiG9w0CBQUAMIIEUQYJKoZIhvcNAQcBoIIEQgSCBD4wggQ6BgkqhkiG9w0BBwOgggQrMIIEJwIBADGCAUIwggE-AgEAMCYwEjEQMA4GA1UEAwwHUm9vdF9DQQIQUdofleopxcioSSQ1YA8A_jANBgkqhkiG9w0BAQEFAASCAQAMSD_fLntfEyYGC7TiPaRE3t-BWKEh37tbgYWqnxmoBNNClnUTZU9YY_EcTXDExK5Vvr_rjN9XTmvTZnqCpf3LSCOZ7PRwoVSobmyXTcPf95Sx9uY8rMo-8WVK59QN8pIFyP1rlbNTmcFJ_gV7KYiXQm4z7CwT2xLv8EZUDvVPa6KKQ8TZzBlR1Lt9tcF5DCyQS02lD1QBPel1406seaZ5EC2IsQX8AQhAJku7nptIRkBLDc2q0019iLTi7skltrL8PsD-W73OYgJx00c7G9CtSaFIiFHcTJd1nB-x_eO_6ePxjbAleK71zjN0fRoVRa-fymA1c3yLT2QR2Odoog1xMIIC2gYJKoZIhvcNAQcBMBEGBSsOAwIHBAjeZdhhCcAAmICCArhL7mKrmkaK2bMquFj4vm_jCwXgpzwb4AY1VKxMJfx4jkaWWmbZgPHFp56eJJ2qHj5BNLgkfh8968EOkignKDNnZta8PZgAmLNdi-pclZk1u5os4YaeenkBWfv0LV4k_wtTG0UxjhririYiiD-stFXCMf9OjTlufbSod8uXeDMFRBWlmhAR7S6xzq3hRlSRWIakmaBbHUI6NFUJpQsNwJZLU1kHyR3Uuzmg4H5lrn3XR-YIlPxdMj4YmlBuukeveLeg_FEhs03P359nQsxj7JDc4SUWt1Fo3-Vb3ea4_LIY09zTRSjwEKbewZk8QxvImQwhEITsCLpESDEn8U_aZBnJxhIc0Ba0ATfQeqFKtz18Mr6WLn94Giluy8J2RMuUMZW61MXe2qzv1Bzb6mkacWn1W-dlzPFVXEE73qoB5GhkQyyl2PYxscI5drEI07EiIzwAzMyoCbrfYaMY6vkYAj_cPCxEGLrAyh9yUW1l_oiewNyG5HBs1wETEMeiu0eP5HYwSFaQtbj-Ws3jlW-i-2fsee_jetP48p7qKTQFeXyi4AJy6lhsblSyOLbaq9Rw9WIgvA3sfqRSbtjNecc8oY7i2ZC6NW99DD3f3AFq_XcbWA89zrjzvpK3PnUQIQ2KG8wxI63hnHhvXZnquxWFbJ3grKn4kVgaiDnmTEBzWKst5ti2pRm2oQI13IIpuvQA4k2yUisWkhNFrDka2LiXNFVbcDGITjdJP0TugGgadjvYp-uA5CUYZSvUpmee1dw4mui5WhFzTwFajgMURrYjuUXD8WXvPlU3M5hOL7P0_zBwZFxlaHQiVJDCe5Xj7m4ORTf7wToV1ZFSwo5qQoZKk04JKSzYr28ynraj10mdhCFHfDBhBugOvOUjD08OImDRCQ9Zc_gWtymxZCQBp9S2Jgk8TX9uq9sDkhmgggKuMIICqjCCAZICAQcwDQYJKoZIhvcNAQEEBQAwGzEZMBcGCSqGSIb3DQEJAhYKdWJvLnViby5mcjAeFw0yNDEyMTAxNzE2MjNaFw0zNDEyMDgxNzE2MjNaMBsxGTAXBgkqhkiG9w0BCQIWCnViby51Ym8uZnIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxaFsKwajboZsbMFvZs7hrw94VKoD2YSN5GLY8pNWTGNSz3SrAG3FYEGwBA__gTL11eXYldXnCLaUds6lWEoTkiN5qpzs37O7N_YOG6BKCghnULlXMCTY0Y92l61-OK6lX6afL62OkK1oI-q0YqbGGfKEhXnXkRGYhUr0p8j4MJU5RAC2gfphyzwo1Kcxn9WwdeTCIoyr3Lditj6skPLqHEHdb3wpwHP62qinnHmVWPNcsk9lnFtfdk0e-1sScL-W_Pl6qaOZylFlK3mEgX8O1-i7X8gii2zK--w8M-f93hroDuTDSLeQvGcTZ_8P1jtcunvmK9ALt2OjFbU_-C-iPAgMBAAEwDQYJKoZIhvcNAQEEBQADggEBAJatOOxLJ-1Fm4tHrdQ-PgC2KXaccKg9e4qfPVzvBqK5GAuwhp3Y5YnuujWdDRjbsp2MU4mEWv-UFTp8D97SfLwl9rgYW0fo2ROUbu5G4JNbIZOdfZIkb2ImlQjlh_pXVdU_DIsCWkIVv8-QPat2hR17_JS9zBUi2KmtnyFE7d5P3P5jTK8fAZO69JXohXystqKZLLj4U5Yu3L8U70fkanQTjXYcbGg5rs3cWBt5s8TCmdVH43AUp9hwh8XPdgaotVIV_Cu5j69iPGMLxeQrHBbqNTt0rYJg_fgmty4JzIe5E5lDBRqNdp6RHIJrAr8eHCpKXI_uX_9VWxFA3UuZ-z4xggHwMIIB7AIBATAgMBsxGTAXBgkqhkiG9w0BCQIWCnViby51Ym8uZnICAQcwDAYIKoZIhvcNAgUFAKCBozASBgpghkgBhvhFAQkCMQQTAjE5MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHwYJKoZIhvcNAQkEMRIEEJ_q6RNwhjHhHXhDzf9oliMwIAYKYIZIAYb4RQEJBTESBBCZHQtFs6Ln2R8l9_vbUMrrMDAGCmCGSAGG-EUBCQcxIhMgRTk2RjhGMjM4N0U5RTdDQjREOEQwQjdFQUQwNjJCQTgwDQYJKoZIhvcNAQEBBQAEggEAfxFMk1QD0uYeZXSnkrEiZbueT27pBVgkoZPn-PdHjNXkRm_W2mOBomkW1q5Z_vN44NMZifbaT9TzYiZCLMk4vRmfxMTkEJ_9S7SIgh1z3ja2dWGs6-OFqLpFYjuD0nE-EtZD4Kfz0c71_XqC9m9gxkG5BVyOv17jtXx7onuMsCRUwJ7nZ4oGC_mFT3o3tDcEY0PfMqiuHH-4jSbBImZO5IKYQkv2XFxd2yDtn1azc29Zwl2TW5bSImIY2MOMv7XAg08aad_kWi-1vMA4XX2IDIh-S2MIcCnThQl6rLRbpCxPcd09MKFa27LDLeAV9LKg-ywskW-mPxu8806zb3-4pA

Got it: apparently the error is also returned when MD5 is used as the digest algorithm. This seems to be true for your request: algorithm OBJECT IDENTIFIER 1.2.840.113549.2.5 md5. MD5 is not supported in our pkcs7 library, and it's unlikely we'll add it (without additional guardrails). Is there an option to use a different hashing algorithm in your SCEP client?

It's a bit unfortunate that this error is returned in this case. It seems to be leftover from before we forked the repository at https://github.com/smallstep/pkcs7. I might fix that sometime soon.

Thanks for the fast answer, my client is a old cisco router so i cant change the hashing and encryption algorithm, do you know when it can be patch.
Im asking because Im currently woking on a project where i need this kind of solution with an deadline.
Thanks again

Thanks for the fast answer, my client is a old cisco router so i cant change the hashing and encryption algorithm, do you know when it can be patch. Im asking because Im currently woking on a project where i need this kind of solution with an deadline. Thanks again

It's unlikely that we'll add support for MD5 in pkcs7, so unfortunately that part won't be fixed soon. I can see an option in which the supported algorithms could be made more dynamic, but that would be a larger scope, and thus take longer (if we'd do it at all). If you really need MD5 quick, I'd suggest you to fork https://github.com/smallstep/pkcs7, add it there, and build your own step-ca binary (at least for now).

Thanks, I would like to try the option u mentioned, i never used go, im newbie in coding, im more in network part, do you have some tips on the part of the file i have to modify or things like that ?
Thanks n'y advance

@Drig69 general guidelines for working step-ca can be found here: https://github.com/smallstep/certificates/blob/master/CONTRIBUTING.md. Some parts do not apply, as the changes you're going to make are not intended to be added to the official step-ca, though.

You'll also need to check out https://github.com/smallstep/pkcs7, and set a replace in the go.mod file (or another method to change which exact dependency is used when building step-ca) pointing to your local copy of pkcs7 in the certificates repo. It'll look something like this in the certificates go.mod file:

replace github.com/smallstep/pkcs7 => /path/to/local/pkcs7

The exact changes you need are a bit too much to spell out completely, but you'll have to start with adding support for md5 in this type switch: https://github.com/smallstep/pkcs7/blob/fbab67b7673f9b78780d48d2f5757dac5da5509e/pkcs7.go#L94-L108. You should work your way up from there.

After patching the pkcs7 library, try compiling and running step-ca again.

Drig69 commented

I tried to do it with a git clone, and did what u said and when i tried to compile with make bootstrap && make i have the following error :
root@pipi-VirtualBox:/home/pipi/Téléchargements/certificates-master# make bootstrap && make
./.version.sh: 4: Bad substitution
golangci/golangci-lint info checking GitHub for tag 'latest'
golangci/golangci-lint info found version: 1.62.2 for v1.62.2/linux/amd64
golangci/golangci-lint info installed /root/go/bin/golangci-lint
./.version.sh: 4: Bad substitution
ca/tls.go:135:2: SA1019: tr.DialTLS has been deprecated since Go 1.14: Use DialTLSContext instead, which allows the transport to cancel dials as soon as they are no longer needed. If both are set, DialTLSContext takes priority. (staticcheck)
tr.DialTLS = c.buildDialTLS(tlsCtx)
^
ca/tls.go:182:2: SA1019: tr.DialTLS has been deprecated since Go 1.14: Use DialTLSContext instead, which allows the transport to cancel dials as soon as they are no longer needed. If both are set, DialTLSContext takes priority. (staticcheck)
tr.DialTLS = c.buildDialTLS(tlsCtx)
^
test/integration/scep/internal/x509/oid.go:83:22: G115: integer overflow conversion int -> uint (gosec)
o := byte(n >> uint(i*7))
^
test/integration/scep/internal/x509/parser.go:279:11: SA1019: elliptic.Unmarshal has been deprecated since Go 1.21: for ECDH, use the crypto/ecdh package. This function accepts an encoding equivalent to that of the NewPublicKey methods in crypto/ecdh. (staticcheck)
x, y := elliptic.Unmarshal(namedCurve, der)
^
test/integration/scep/internal/x509/parser.go:10:2: SA1019: "crypto/dsa" has been deprecated since Go 1.16 because it shouldn't be used: DSA is a legacy algorithm, and modern alternatives such as Ed25519 (implemented by package crypto/ed25519) should be used instead. Keys with 1024-bit moduli (L1024N160 parameters) are cryptographically weak, while bigger keys are not widely supported. Note that FIPS 186-5 no longer approves DSA for signature generation. (staticcheck)
"crypto/dsa"
^
acme/linker.go:89:77: G602: slice index out of range (gosec)
return fmt.Sprintf("/%s/%s/%s/%s", provisionerName, typ, inputs[0], inputs[1])
^
acme/challenge.go:230:16: G115: integer overflow conversion uint64 -> uint8 (gosec)
return uint8(v.Uint())
^
acme/challenge.go:1105:32: G115: integer overflow conversion int64 -> int32 (gosec)
switch coseAlgorithmIdentifier(alg) {
^
scripts/badger-migration/main.go:309:18: G115: integer overflow conversion int -> uint16 (gosec)
length = uint16(len(bk))
^
scripts/badger-migration/main.go:311:11: G115: integer overflow conversion int -> uint16 (gosec)
if uint16(len(bk)) < start {
^
cas/cloudcas/certificate.go:253:25: G115: integer overflow conversion int -> int32 (gosec)
maxPathLength = int32(cert.MaxPathLen)
^
cas/cloudcas/certificate.go:307:17: G115: integer overflow conversion int -> int32 (gosec)
ret[i] = int32(v)
^
authority/provisioner/collection.go:213:39: G115: integer overflow conversion int -> uint32 (gosec)
binary.BigEndian.PutUint32(bi, uint32(c.sorted.Len()))
^
authority/provisioner/controller.go:192:19: G115: integer overflow conversion uint64 -> int64 (gosec)
if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
^
authority/provisioner/controller.go:195:20: G115: integer overflow conversion uint64 -> int64 (gosec)
if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(ssh.CertTimeInfinity) && (unixNow >= before || before < 0) && !p.Claimer.AllowRenewalAfterExpiry() {
^
authority/provisioner/jwk.go:280:63: G115: integer overflow conversion int64 -> uint64 (gosec)
signOptions = append(signOptions, sshCertValidBeforeModifier(opts.ValidBefore.RelativeTime(t).Unix()))
^
authority/provisioner/jwk.go:277:62: G115: integer overflow conversion int64 -> uint64 (gosec)
signOptions = append(signOptions, sshCertValidAfterModifier(opts.ValidAfter.RelativeTime(t).Unix()))
^
authority/provisioner/nebula.go:243:64: G115: integer overflow conversion int64 -> uint64 (gosec)
signOptions = append(signOptions, sshCertValidBeforeModifier(opts.ValidBefore.RelativeTime(t).Unix()))
^
authority/provisioner/nebula.go:240:63: G115: integer overflow conversion int64 -> uint64 (gosec)
signOptions = append(signOptions, sshCertValidAfterModifier(opts.ValidAfter.RelativeTime(t).Unix()))
^
authority/provisioner/sign_ssh_options.go:109:28: G115: integer overflow conversion int64 -> uint64 (gosec)
cert.ValidBefore = uint64(o.ValidBefore.RelativeTime(t).Unix())
^
authority/provisioner/sign_ssh_options.go:106:27: G115: integer overflow conversion int64 -> uint64 (gosec)
cert.ValidAfter = uint64(o.ValidAfter.RelativeTime(t).Unix())
^
authority/provisioner/sign_ssh_options.go:170:20: G115: integer overflow conversion int64 -> uint64 (gosec)
backdate = uint64(o.Backdate / time.Second)
^
authority/provisioner/sign_ssh_options.go:171:27: G115: integer overflow conversion int64 -> uint64 (gosec)
cert.ValidAfter = uint64(now().Truncate(time.Second).Unix())
^
authority/provisioner/sign_ssh_options.go:174:46: G115: integer overflow conversion int64 -> uint64 (gosec)
cert.ValidBefore = cert.ValidAfter + uint64(d/time.Second)
^
authority/provisioner/sign_ssh_options.go:209:20: G115: integer overflow conversion int64 -> uint64 (gosec)
backdate = uint64(o.Backdate / time.Second)
^
authority/provisioner/sign_ssh_options.go:210:27: G115: integer overflow conversion int64 -> uint64 (gosec)
cert.ValidAfter = uint64(now().Truncate(time.Second).Unix())
^
authority/provisioner/sign_ssh_options.go:213:35: G115: integer overflow conversion uint64 -> int64 (gosec)
certValidAfter := time.Unix(int64(cert.ValidAfter), 0)
^
authority/provisioner/sign_ssh_options.go:224:28: G115: integer overflow conversion int64 -> uint64 (gosec)
cert.ValidBefore = uint64(certValidBefore.Unix())
^
authority/provisioner/sign_ssh_options.go:226:37: G115: integer overflow conversion uint64 -> int64 (gosec)
certValidBefore := time.Unix(int64(cert.ValidBefore), 0)
^
authority/provisioner/sign_ssh_options.go:280:32: G115: integer overflow conversion int64 -> uint64 (gosec)
case cert.ValidBefore < uint64(now().Unix()):
^
authority/provisioner/sign_ssh_options.go:302:22: G115: integer overflow conversion uint64 -> int64 (gosec)
dur := time.Duration(cert.ValidBefore-cert.ValidAfter) * time.Second
^
authority/provisioner/sign_ssh_options.go:335:32: G115: integer overflow conversion int64 -> uint64 (gosec)
case cert.ValidBefore < uint64(now().Unix()):
^
authority/provisioner/sign_ssh_options.go:465:11: G115: integer overflow conversion int -> uint32 (gosec)
if uint32(len(in)) < length {
^
authority/provisioner/sshpop.go:121:20: G115: integer overflow conversion uint64 -> int64 (gosec)
if after := int64(sshCert.ValidAfter); after < 0 || unixNow < int64(sshCert.ValidAfter) {
^
authority/provisioner/sshpop.go:124:21: G115: integer overflow conversion uint64 -> int64 (gosec)
if before := int64(sshCert.ValidBefore); sshCert.ValidBefore != uint64(ssh.CertTimeInfinity) && (unixNow >= before || before < 0) {
^
authority/provisioner/x5c.go:338:63: G115: integer overflow conversion int64 -> uint64 (gosec)
signOptions = append(signOptions, sshCertValidBeforeModifier(opts.ValidBefore.RelativeTime(t).Unix()))
^
authority/provisioner/x5c.go:335:62: G115: integer overflow conversion int64 -> uint64 (gosec)
signOptions = append(signOptions, sshCertValidAfterModifier(opts.ValidAfter.RelativeTime(t).Unix()))
^
db/db.go:468:21: G115: integer overflow conversion uint64 -> int64 (gosec)
if time.Unix(int64(data.Expiry), 0).After(time.Now()) {
^
authority/linkedca.go:339:48: G115: integer overflow conversion int -> int32 (gosec)
ReasonCode: linkedca.RevocationReasonCode(rci.ReasonCode),
^
authority/linkedca.go:353:45: G115: integer overflow conversion int -> int32 (gosec)
ReasonCode: linkedca.RevocationReasonCode(rci.ReasonCode),
^
authority/linkedca.go:406:34: G115: integer overflow conversion int -> int32 (gosec)
Type: linkedca.Provisioner_Type(p.GetType()),
^
authority/provisioners.go:1260:43: G115: integer overflow conversion int -> int32 (gosec)
MinimumPublicKeyLength: int32(p.MinimumPublicKeyLength),
^
authority/provisioners.go:1263:43: G115: integer overflow conversion int -> int32 (gosec)
EncryptionAlgorithmIdentifier: int32(p.EncryptionAlgorithmIdentifier),
^
authority/ssh.go:359:27: G115: integer overflow conversion uint64 -> int64 (gosec)
duration := time.Duration(oldCert.ValidBefore-oldCert.ValidAfter) * time.Second
^
authority/ssh.go:373:26: G115: integer overflow conversion int64 -> uint64 (gosec)
ValidAfter: uint64(va.Unix()),
^
authority/ssh.go:374:26: G115: integer overflow conversion int64 -> uint64 (gosec)
ValidBefore: uint64(vb.Unix()),
^
authority/ssh.go:439:27: G115: integer overflow conversion uint64 -> int64 (gosec)
duration := time.Duration(oldCert.ValidBefore-oldCert.ValidAfter) * time.Second
^
authority/ssh.go:453:26: G115: integer overflow conversion int64 -> uint64 (gosec)
ValidAfter: uint64(va.Unix()),
^
authority/ssh.go:454:26: G115: integer overflow conversion int64 -> uint64 (gosec)
ValidBefore: uint64(vb.Unix()),
^
api/api.go:598:39: G115: integer overflow conversion uint64 -> int64 (gosec)
"valid-from": time.Unix(int64(cert.ValidAfter), 0).Format(time.RFC3339),
^
api/api.go:599:39: G115: integer overflow conversion uint64 -> int64 (gosec)
"valid-to": time.Unix(int64(cert.ValidBefore), 0).Format(time.RFC3339),
^
api/ssh.go:334:30: G115: integer overflow conversion uint64 -> int64 (gosec)
NotBefore: time.Unix(int64(cert.ValidAfter), 0),
^
api/ssh.go:335:30: G115: integer overflow conversion uint64 -> int64 (gosec)
NotAfter: time.Unix(int64(cert.ValidBefore), 0),
^
api/sshRekey.go:83:30: G115: integer overflow conversion uint64 -> int64 (gosec)
notBefore := time.Unix(int64(oldCert.ValidAfter), 0)
^
api/api.go:7:2: SA1019: "crypto/dsa" has been deprecated since Go 1.16 because it shouldn't be used: DSA is a legacy algorithm, and modern alternatives such as Ed25519 (implemented by package crypto/ed25519) should be used instead. Keys with 1024-bit moduli (L1024N160 parameters) are cryptographically weak, while bigger keys are not widely supported. Note that FIPS 186-5 no longer approves DSA for signature generation. (staticcheck)
"crypto/dsa" // support legacy algorithms
^
make: *** [Makefile:141 : lint] Erreur 1

@Drig69, try it without the Makefile, using go build -o bin/step-ca cmd/step-ca/main.go

Drig69 commented

Hello, I tried like we said and i have the following errors when Im trying to enroll certificate on my Router,

INFO[0013] duration="341.178µs" duration-ns=341178 fields.time="2024-12-17T17:22:49+01:00" method=GET name=ca path="/scep/myscep/pkiclient.exe?operation=GetCACert&message=ubo" protocol=HTTP/1.0 referer= remote-address=10.0.0.2 request-id=c1b81304-2598-448c-886b-3f5b4890cc3d size=1072 status=200 user-agent="Mozilla/4.0 (compatible; MSIE 5.0; Cisco PKI)" user-id=
ERRO[0064] duration="396.433µs" duration-ns=396433 error="scep get request failed: failed parsing SCEP request: pkcs7: unsupported digest "1.2.840.113549.2.5" for encryption algorithm "1.2.840.113549.1.1.1"" fields.time="2024-12-17T17:23:40+01:00" method=GET name=ca path="/scep/myscep/pkiclient.exe?operation=PKIOperation&message=MIIFvwYJKoZIhvcNAQcCoIIFsDCCBawCAQExDjAMBggqhkiG9w0CBQUAMIIDOQYJ%0AKoZIhvcNAQcBoIIDKgSCAyYwggMiBgkqhkiG9w0BBwOgggMTMIIDDwIBADGCAcow%0AggHGAgEAMC4wGjEYMBYGA1UEAxMPRXhhbXBsZSBSb290IENBAhAgQIVjywSTaGN5%0AUhomCKvHMA0GCSqGSIb3DQEBAQUABIIBgMVLNszMtEGPMUsMz%2FmRes2vHcrX2PB9%0AX0vC%2B3qvaQ5eT3%2Fm2CYe3lTJgbnjsL5uWyg4DGoDgigY2Xi89LYpxSWuu20ScKws%0A54xg8jblXuSt56ovJ511dfnBIt5Gkl3VwpuGhyPtOAkkogddIjta%2BMc0469cgVLo%0AY%2B%2BvlU6XT0EneFzLuq%2Fhb%2F%2ByA9s2H5aTtKHhlUw%2Bh6Uc73ceSeh86QLb5RZ37Rbd%0AO%2FD51e3IL8X7C0Ov6ziQtwzb4LDGACseo6EQTCIe1ICgGZg2IRR%2F4TPBMSBM6308%0AdIKC9EU1WDUob7WwSCHTuxecPKM8RsCjTFcB1wroI%2BKT%2FVZy%2F5gcuPnKftKMnwgD%0AK5vQy8g6Zs870uaub2ArfkWQ89tofQ0c7xAM2GgWoyWhFWYFYc9UHyeNNIyMw%2Fm0%0AT2pPw%2Flhnz1WrsiimbMGSBdN7qZNAhpNbIMFfbU%2FC7Qojwp5khsDEh9pi6yAZAOY%0A79C2Md5VSI6oJLdDw4jA0We26RT2xwKu3zCCAToGCSqGSIb3DQEHATARBgUrDgMC%0ABwQI9NHlYcCUz3OAggEYAovXFxWbK4gztUgWk0AY9gbMVqpj2NbPB%2Fmcew%2FTQizD%0AzFUFG4pll96ZHYwcsHQQAK6kQoY%2FwrOI6ESvl0A%2BFfl7SWJchUHBvI69OiFMKlsH%0AMvLQRUsd942nb94hdwWCeP0dZ6eh1EAJRFe5RkLHjkAIP2d83x2b4kEDTlROdLgj%0A%2FFt%2BIMW08ZQ3CU8O800ZV%2BnKrDIkAJiw3LITk9SccGWtH1p56d32o28wjen93twV%0AL1K1T7hL36D3YCXz3RqKZMwh%2BHNpzsQwZNGc1FKcYr8DBxTqTE1qydjvFSHioj0%2F%0A0v55zivEt%2BGOjiC3tYY4TG%2FoLUSJxxsLbEMquESRxGvVtEmr13tGoEoMW3krurON%0AE6Ir4xXd4KCCASUwggEhMIHMAgEDMA0GCSqGSIb3DQEBBAUAMBwxGjAYBgkqhkiG%0A9w0BCQIWC1J1Ym8udWJvLmZyMB4XDTI0MTIxNzE3MjM1NFoXDTM0MTIxNTE3MjM1%0ANFowHDEaMBgGCSqGSIb3DQEJAhYLUnViby51Ym8uZnIwXDANBgkqhkiG9w0BAQEF%0AAANLADBIAkEAvtd430gL8o9J%2FVRvxDxpjVklc0RsAuOJvPxdUmj5PqXlJKqYtVQJ%0AXSGtFiWTCVAm1%2B%2BapraVjXMy2EVVeL3GowIDAQABMA0GCSqGSIb3DQEBBAUAA0EA%0ALIwDGG%2FlYCHWTmwiU5VJoTrrTtuviPLYqh%2FGl%2B%2BmhdoZuYmfo1cdBoQC5uOwYlje%0A3e%2B9OTcxxPHX5J7N7TT1dzGCAS8wggErAgEBMCEwHDEaMBgGCSqGSIb3DQEJAhYL%0AUnViby51Ym8uZnICAQMwDAYIKoZIhvcNAgUFAKCBozASBgpghkgBhvhFAQkCMQQT%0AAjE5MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHwYJKoZIhvcNAQkEMRIEEBio%0ATl2QDMTbTNCCxbiMiXIwIAYKYIZIAYb4RQEJBTESBBCQIcRwpJefYTdXWjj7TrT9%0AMDAGCmCGSAGG%2BEUBCQcxIhMgRkI1QzZDRkEyRkIwRDNCMDkwNzY5MDY3NEFERDBE%0ARDQwDQYJKoZIhvcNAQEBBQAEQKZ%2B5RH4KeYt5Zzkq87pwk%2B%2BxYNthhQ49OckFLQM%0AZFOnvMDr4MBdx2CLFtc0jsrK4VVwWo5d4gWwtYMHjs%2BKMS0%3D%0A" protocol=HTTP/1.0 referer= remote-address=10.0.0.2 request-id=6119ca0b-155c-4457-b631-a093d9de8b7f size=149 status=500 user-agent= user-id=

I modified the pkcs7.go like this and set the replace to link it :
// Package pkcs7 implements parsing and generation of some PKCS#7 structures.
package pkcs7

import (
"bytes"
"crypto"
"crypto/dsa"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"errors"
"fmt"
"sort"
"sync"

_ "crypto/sha1" // for crypto.SHA1
_ "crypto/md5"

legacyx509 "github.com/smallstep/pkcs7/internal/legacy/x509"

)

// PKCS7 Represents a PKCS7 structure
type PKCS7 struct {
Content []byte
Certificates []*x509.Certificate
CRLs []pkix.CertificateList
Signers []signerInfo
raw interface{}
}

type contentInfo struct {
ContentType asn1.ObjectIdentifier
Content asn1.RawValue asn1:"explicit,optional,tag:0"
}

// ErrUnsupportedContentType is returned when a PKCS7 content type is not supported.
// Currently only Data (1.2.840.113549.1.7.1), Signed Data (1.2.840.113549.1.7.2),
// and Enveloped Data are supported (1.2.840.113549.1.7.3)
var ErrUnsupportedContentType = errors.New("pkcs7: cannot parse data: unimplemented content type")

type unsignedData []byte

var (
// Signed Data OIDs
OIDData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
OIDSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2}
OIDEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3}
OIDEncryptedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6}
OIDAttributeContentType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3}
OIDAttributeMessageDigest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4}
OIDAttributeSigningTime = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5}

// Digest Algorithms
OIDDigestAlgorithmSHA1   = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
OIDDigestAlgorithmSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
OIDDigestAlgorithmSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
OIDDigestAlgorithmSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
OIDDigestAlgorithmSHA224 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 4}

OIDDigestAlgorithmDSA     = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
OIDDigestAlgorithmDSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}

OIDDigestAlgorithmECDSASHA1   = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
OIDDigestAlgorithmECDSASHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
OIDDigestAlgorithmECDSASHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
OIDDigestAlgorithmECDSASHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}

// Signature Algorithms
OIDEncryptionAlgorithmRSAMD5    = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}  // see https://www.rfc-editor.org/rfc/rfc8017#appendix-A.2.4
OIDEncryptionAlgorithmRSASHA1   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}  // ditto
OIDEncryptionAlgorithmRSASHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} // ditto
OIDEncryptionAlgorithmRSASHA384 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} // ditto
OIDEncryptionAlgorithmRSASHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} // ditto
OIDEncryptionAlgorithmRSASHA224 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 14} // ditto

OIDEncryptionAlgorithmECDSAP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
OIDEncryptionAlgorithmECDSAP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
OIDEncryptionAlgorithmECDSAP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}

// Asymmetric Encryption Algorithms
OIDEncryptionAlgorithmRSA       = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} // see https://www.rfc-editor.org/rfc/rfc8017#appendix-A.2.2
OIDEncryptionAlgorithmRSAESOAEP = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 7} // see https://www.rfc-editor.org/rfc/rfc8017#appendix-A.2.1

// Symmetric Encryption Algorithms
OIDEncryptionAlgorithmDESCBC     = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7}               // see https://www.rfc-editor.org/rfc/rfc8018.html#appendix-B.2.1
OIDEncryptionAlgorithmDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7}         // see https://www.rfc-editor.org/rfc/rfc8018.html#appendix-B.2.2
OIDEncryptionAlgorithmAES256CBC  = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42} // see https://www.rfc-editor.org/rfc/rfc3565.html#section-4.1
OIDEncryptionAlgorithmAES128GCM  = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6}  // see https://www.rfc-editor.org/rfc/rfc5084.html#section-3.2
OIDEncryptionAlgorithmAES128CBC  = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}  // see https://www.rfc-editor.org/rfc/rfc8018.html#appendix-B.2.5
OIDEncryptionAlgorithmAES256GCM  = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 46} // see https://www.rfc-editor.org/rfc/rfc5084.html#section-3.2

OIDDigestAlgorithmMD5 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 5} // OID pour MD5

)

func getHashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error) {
switch {
case oid.Equal(OIDDigestAlgorithmSHA1), oid.Equal(OIDDigestAlgorithmECDSASHA1),
oid.Equal(OIDDigestAlgorithmDSA), oid.Equal(OIDDigestAlgorithmDSASHA1),
oid.Equal(OIDEncryptionAlgorithmRSA):
return crypto.SHA1, nil
case oid.Equal(OIDDigestAlgorithmSHA256), oid.Equal(OIDDigestAlgorithmECDSASHA256):
return crypto.SHA256, nil
case oid.Equal(OIDDigestAlgorithmSHA384), oid.Equal(OIDDigestAlgorithmECDSASHA384):
return crypto.SHA384, nil
case oid.Equal(OIDDigestAlgorithmSHA512), oid.Equal(OIDDigestAlgorithmECDSASHA512):
return crypto.SHA512, nil
case oid.Equal(OIDDigestAlgorithmMD5): // Ajouter la prise en charge de MD5
return crypto.MD5, nil
}
return crypto.Hash(0), ErrUnsupportedAlgorithm
}

// getDigestOIDForSignatureAlgorithm takes an x509.SignatureAlgorithm
// and returns the corresponding OID digest algorithm
func getDigestOIDForSignatureAlgorithm(digestAlg x509.SignatureAlgorithm) (asn1.ObjectIdentifier, error) {
switch digestAlg {
case x509.SHA1WithRSA, x509.ECDSAWithSHA1:
return OIDDigestAlgorithmSHA1, nil
case x509.SHA256WithRSA, x509.ECDSAWithSHA256:
return OIDDigestAlgorithmSHA256, nil
case x509.SHA384WithRSA, x509.ECDSAWithSHA384:
return OIDDigestAlgorithmSHA384, nil
case x509.SHA512WithRSA, x509.ECDSAWithSHA512:
return OIDDigestAlgorithmSHA512, nil
case x509.MD5WithRSA:
return OIDDigestAlgorithmMD5, nil

}
return nil, fmt.Errorf("pkcs7: cannot convert hash to oid, unknown hash algorithm")

}

// getOIDForEncryptionAlgorithm takes the public or private key type of the signer and
// the OID of a digest algorithm to return the appropriate signerInfo.DigestEncryptionAlgorithm
func getOIDForEncryptionAlgorithm(pkey interface{}, OIDDigestAlg asn1.ObjectIdentifier) (asn1.ObjectIdentifier, error) {
switch k := pkey.(type) {
case *rsa.PrivateKey, *rsa.PublicKey:
switch {
default:
return OIDEncryptionAlgorithmRSA, nil
case OIDDigestAlg.Equal(OIDEncryptionAlgorithmRSA):
return OIDEncryptionAlgorithmRSA, nil
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA1):
return OIDEncryptionAlgorithmRSASHA1, nil
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA256):
return OIDEncryptionAlgorithmRSASHA256, nil
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA384):
return OIDEncryptionAlgorithmRSASHA384, nil
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA512):
return OIDEncryptionAlgorithmRSASHA512, nil
}
case *ecdsa.PrivateKey, *ecdsa.PublicKey:
switch {
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA1):
return OIDDigestAlgorithmECDSASHA1, nil
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA256):
return OIDDigestAlgorithmECDSASHA256, nil
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA384):
return OIDDigestAlgorithmECDSASHA384, nil
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA512):
return OIDDigestAlgorithmECDSASHA512, nil
}
case *dsa.PrivateKey, *dsa.PublicKey:
return OIDDigestAlgorithmDSA, nil
case crypto.Signer:
// This generic case is here to cover types from other packages. It
// was specifically added to handle the private keyRSA type in the
// github.com/go-piv/piv-go/piv package.
return getOIDForEncryptionAlgorithm(k.Public(), OIDDigestAlg)
}
return nil, fmt.Errorf("pkcs7: cannot convert encryption algorithm to oid, unknown private key type %T", pkey)

}

// Parse decodes a DER encoded PKCS7 package
func Parse(data []byte) (p7 *PKCS7, err error) {
if len(data) == 0 {
return nil, errors.New("pkcs7: input data is empty")
}
var info contentInfo
der, err := ber2der(data)
if err != nil {
return nil, err
}
rest, err := asn1.Unmarshal(der, &info)
if len(rest) > 0 {
err = asn1.SyntaxError{Msg: "trailing data"}
return
}
if err != nil {
return
}

// fmt.Printf("--> Content Type: %s", info.ContentType)
switch {
case info.ContentType.Equal(OIDSignedData):
	return parseSignedData(info.Content.Bytes)
case info.ContentType.Equal(OIDEnvelopedData):
	return parseEnvelopedData(info.Content.Bytes)
case info.ContentType.Equal(OIDEncryptedData):
	return parseEncryptedData(info.Content.Bytes)
}
return nil, ErrUnsupportedContentType

}

func parseEnvelopedData(data []byte) (*PKCS7, error) {
var ed envelopedData
if _, err := asn1.Unmarshal(data, &ed); err != nil {
return nil, err
}
return &PKCS7{
raw: ed,
}, nil
}

func parseEncryptedData(data []byte) (*PKCS7, error) {
var ed encryptedData
if _, err := asn1.Unmarshal(data, &ed); err != nil {
return nil, err
}
return &PKCS7{
raw: ed,
}, nil
}

// SetFallbackLegacyX509CertificateParserEnabled enables parsing certificates
// embedded in a PKCS7 message using the logic from crypto/x509 from before
// Go 1.23. Go 1.23 introduced a breaking change in case a certificate contains
// a critical authority key identifier, which is the correct thing to do based
// on RFC 5280, but it breaks Windows devices performing the Simple Certificate
// Enrolment Protocol (SCEP), as the certificates embedded in those requests
// apparently have authority key identifier extensions marked critical.
//
// See https://go-review.googlesource.com/c/go/+/562341 for the change in the
// Go source.
//
// When [SetFallbackLegacyX509CertificateParserEnabled] is called with true, it
// enables parsing using the legacy crypto/x509 certificate parser. It'll first
// try to parse the certificates using the regular Go crypto/x509 package, but
// if it fails on the above case, it'll retry parsing the certificates using a
// copy of the crypto/x509 package based on Go 1.23, but skips checking the
// authority key identifier extension being critical or not.
func SetFallbackLegacyX509CertificateParserEnabled(v bool) {
legacyX509CertificateParser.Lock()
legacyX509CertificateParser.enabled = v
legacyX509CertificateParser.Unlock()
}

var legacyX509CertificateParser struct {
sync.RWMutex
enabled bool
}

func isLegacyX509ParserEnabled() bool {
legacyX509CertificateParser.RLock()
defer legacyX509CertificateParser.RUnlock()
return legacyX509CertificateParser.enabled
}

func (raw rawCertificates) Parse() ([]*x509.Certificate, error) {
if len(raw.Raw) == 0 {
return nil, nil
}

var val asn1.RawValue
if _, err := asn1.Unmarshal(raw.Raw, &val); err != nil {
	return nil, err
}

certificates, err := x509.ParseCertificates(val.Bytes)
if err != nil && err.Error() == "x509: authority key identifier incorrectly marked critical" {
	if isLegacyX509ParserEnabled() {
		certificates, err = legacyx509.ParseCertificates(val.Bytes)
	}
}

return certificates, err

}

func isCertMatchForIssuerAndSerial(cert *x509.Certificate, ias issuerAndSerial) bool {
return cert.SerialNumber.Cmp(ias.SerialNumber) == 0 && bytes.Equal(cert.RawIssuer, ias.IssuerName.FullBytes)
}

// Attribute represents a key value pair attribute. Value must be marshalable byte
// encoding/asn1
type Attribute struct {
Type asn1.ObjectIdentifier
Value interface{}
}

type attributes struct {
types []asn1.ObjectIdentifier
values []interface{}
}

// Add adds the attribute, maintaining insertion order
func (attrs *attributes) Add(attrType asn1.ObjectIdentifier, value interface{}) {
attrs.types = append(attrs.types, attrType)
attrs.values = append(attrs.values, value)
}

type sortableAttribute struct {
SortKey []byte
Attribute attribute
}

type attributeSet []sortableAttribute

func (sa attributeSet) Len() int {
return len(sa)
}

func (sa attributeSet) Less(i, j int) bool {
return bytes.Compare(sa[i].SortKey, sa[j].SortKey) < 0
}

func (sa attributeSet) Swap(i, j int) {
sa[i], sa[j] = sa[j], sa[i]
}

func (sa attributeSet) Attributes() []attribute {
attrs := make([]attribute, len(sa))
for i, attr := range sa {
attrs[i] = attr.Attribute
}
return attrs
}

func (attrs *attributes) ForMarshalling() ([]attribute, error) {
sortables := make(attributeSet, len(attrs.types))
for i := range sortables {
attrType := attrs.types[i]
attrValue := attrs.values[i]
asn1Value, err := asn1.Marshal(attrValue)
if err != nil {
return nil, err
}
attr := attribute{
Type: attrType,
Value: asn1.RawValue{Tag: 17, IsCompound: true, Bytes: asn1Value}, // 17 == SET tag
}
encoded, err := asn1.Marshal(attr)
if err != nil {
return nil, err
}
sortables[i] = sortableAttribute{
SortKey: encoded,
Attribute: attr,
}
}
sort.Sort(sortables)
return sortables.Attributes(), nil
}

Thanks by advance.