diff --git a/certvalidator/validate.py b/certvalidator/validate.py index b0cfb05..5dea292 100644 --- a/certvalidator/validate.py +++ b/certvalidator/validate.py @@ -319,6 +319,9 @@ def _validate_path(validation_context, path, end_entity_name_override=None): verify_func = asymmetric.dsa_verify elif signature_algo == 'ecdsa': verify_func = asymmetric.ecdsa_verify + elif hasattr(asymmetric, "eddsa_verify") and signature_algo in ['ed25519', 'ed448']: + verify_func = asymmetric.eddsa_verify + hash_algo = "raw" else: raise PathValidationError(pretty_message( ''' diff --git a/docs/readme.md b/docs/readme.md index 1e622f4..5018cb8 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -57,4 +57,5 @@ Testing is performed using: - [Public Key Interoperability Test Suite from NIST](http://csrc.nist.gov/groups/ST/crypto_apps_infra/pki/pkitesting.html) - [OCSP tests from OpenSSL](https://github.com/openssl/openssl/blob/master/test/recipes/80-test_ocsp.t) + - [S/MIME example certificates from RFC 9216](https://www.rfc-editor.org/rfc/rfc9216.txt) - Various certificates generated for TLS certificate validation diff --git a/tests/fixtures/rfc9216/Sample_LAMPS_Ed25519_Certification_Authority.crosssigned.pem b/tests/fixtures/rfc9216/Sample_LAMPS_Ed25519_Certification_Authority.crosssigned.pem new file mode 100644 index 0000000..533572a --- /dev/null +++ b/tests/fixtures/rfc9216/Sample_LAMPS_Ed25519_Certification_Authority.crosssigned.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICvzCCAaegAwIBAgITR49T5oAgYhF5+eBYQ3ZBZIMuujANBgkqhkiG9w0BAQsF +ADBVMQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQLEwhMQU1QUyBXRzExMC8GA1UEAxMo +U2FtcGxlIExBTVBTIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0yMDEy +MTUyMTM1NDRaGA8yMDUyMDkyNzA2NTQxOFowWTENMAsGA1UEChMESUVURjERMA8G +A1UECxMITEFNUFMgV0cxNTAzBgNVBAMTLFNhbXBsZSBMQU1QUyBFZDI1NTE5IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MCowBQYDK2VwAyEAhIFGfciP65F//Ng4oas1 +SGUGfkShN1Ecqfnjdk8SQwSjfDB6MA8GA1UdEwEB/wQFMAMBAf8wFwYDVR0gBBAw +DjAMBgpghkgBZQMCATACMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUa6KVfboU +m+QtBNEHpNGC5C5rjLUwHwYDVR0jBBgwFoAUkTCOfAcXDKfxCShlNhpnHGh29Fkw +DQYJKoZIhvcNAQELBQADggEBAGV0x0OEzgYlRKixMcztiikxxJDbmRat1pcipD15 +1n8kiBoGhsT4fNZJVoL0OQBa/WTMntL+qcAk2itqZCNIeZeGklUljXBAz5tkDRAF +f/v99LEcsZTcuIbnJqz35danQkp4/upG4hPkfx+nbc1bsVylrITwIGOpnGhz7z3m +VCk03DFE3Qt4w9mlv9yuMse33nmsBGXog/XZvM2JRY0iKt0xksQqQD9uYm7MoMeH +qQs3Ot7EaoPj54xyWvy42run6TLUye64D94SNjB/q/wjL96bsVIKGrRn10T1ybCh +4F5HD00hQZgP15Dlb1rg+vskN8MSk5nuD+6z1VsugioW0+k= +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/Sample_LAMPS_Ed25519_Certification_Authority.selfsigned.pem b/tests/fixtures/rfc9216/Sample_LAMPS_Ed25519_Certification_Authority.selfsigned.pem new file mode 100644 index 0000000..e08ac74 --- /dev/null +++ b/tests/fixtures/rfc9216/Sample_LAMPS_Ed25519_Certification_Authority.selfsigned.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBtzCCAWmgAwIBAgITH59R65FuWGNFHoyc0N3iWesrXzAFBgMrZXAwWTENMAsG +A1UEChMESUVURjERMA8GA1UECxMITEFNUFMgV0cxNTAzBgNVBAMTLFNhbXBsZSBM +QU1QUyBFZDI1NTE5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MCAXDTIwMTIxNTIx +MzU0NFoYDzIwNTIxMjE1MjEzNTQ0WjBZMQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQL +EwhMQU1QUyBXRzE1MDMGA1UEAxMsU2FtcGxlIExBTVBTIEVkMjU1MTkgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwKjAFBgMrZXADIQCEgUZ9yI/rkX/82DihqzVIZQZ+ +RKE3URyp+eN2TxJDBKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFGuilX26FJvkLQTRB6TRguQua4y1MAUGAytlcANBAFAJrlWo +QjzwT0ph7rXe023x3GaLPMXMwQI2Of+apkdG2mH9ID6PE1bu3gRRqIH5w2tyS+xF +Jw0ouxcJyAyXEQ4= +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/Sample_LAMPS_RSA_Certification_Authority.crosssigned.pem b/tests/fixtures/rfc9216/Sample_LAMPS_RSA_Certification_Authority.crosssigned.pem new file mode 100644 index 0000000..3cf662b --- /dev/null +++ b/tests/fixtures/rfc9216/Sample_LAMPS_RSA_Certification_Authority.crosssigned.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC5zCCApmgAwIBAgITcTQnnf8DUsvAdvkX7mUemYos7DAFBgMrZXAwWTENMAsG +A1UEChMESUVURjERMA8GA1UECxMITEFNUFMgV0cxNTAzBgNVBAMTLFNhbXBsZSBM +QU1QUyBFZDI1NTE5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MCAXDTIwMTIxNTIx +MzU0NFoYDzIwNTIwOTI3MDY1NDE4WjBVMQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQL +EwhMQU1QUyBXRzExMC8GA1UEAxMoU2FtcGxlIExBTVBTIFJTQSBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALYY +Y9MQVU12LQuyJDv0DQzPYb4tEmVtfa82jxJOJsCfJD1XMWsYkeNSFFf86as4/esM +IHZJh8E9XB3QJ0LrP2p8mRxXENzWEr5VL28qdwvQg9RiWQnBa4yldrUh6XP7MK5X +6CNXzdS+frBOff0wKbKa7ucU/OKFy46dsxg4J0yZRuLUObxNf0/qK0VHeGIgelIo +xuSheUzXzftZoV/HnuQEigi42MoTI8i4r3AZQB6mlzlAAcmD3k88Qc0eWYzKEHMK +WaCTKjNFJ5KuTGr1d4kpT3iVYZpnTNviRqsK6v96IygKTdg1Xwvey3K9wwbWpQMI +BorHoVkR/uET1E3ovdsCAwEAAaN8MHowDwYDVR0TAQH/BAUwAwEB/zAXBgNVHSAE +EDAOMAwGCmCGSAFlAwIBMAIwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSRMI58 +BxcMp/EJKGU2GmccaHb0WTAfBgNVHSMEGDAWgBRropV9uhSb5C0E0Qek0YLkLmuM +tTAFBgMrZXADQQBnQ+0eFP/BBKz8bVELVEPw9WFXwIGnyH7rrmLQJSE5GJmm7cYX +FFJBGyc3NWzlxxyfJLsh0yYh04dxdM8R5hcD +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/Sample_LAMPS_RSA_Certification_Authority.selfsigned.pem b/tests/fixtures/rfc9216/Sample_LAMPS_RSA_Certification_Authority.selfsigned.pem new file mode 100644 index 0000000..afaf2d8 --- /dev/null +++ b/tests/fixtures/rfc9216/Sample_LAMPS_RSA_Certification_Authority.selfsigned.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgITcBn0xb/zdaeCQlqp6yZUAGZUCDANBgkqhkiG9w0BAQ0F +ADBVMQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQLEwhMQU1QUyBXRzExMC8GA1UEAxMo +U2FtcGxlIExBTVBTIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0xOTEx +MjAwNjU0MThaGA8yMDUyMDkyNzA2NTQxOFowVTENMAsGA1UEChMESUVURjERMA8G +A1UECxMITEFNUFMgV0cxMTAvBgNVBAMTKFNhbXBsZSBMQU1QUyBSU0EgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQC2GGPTEFVNdi0LsiQ79A0Mz2G+LRJlbX2vNo8STibAnyQ9VzFrGJHjUhRX/Omr +OP3rDCB2SYfBPVwd0CdC6z9qfJkcVxDc1hK+VS9vKncL0IPUYlkJwWuMpXa1Ielz ++zCuV+gjV83Uvn6wTn39MCmymu7nFPzihcuOnbMYOCdMmUbi1Dm8TX9P6itFR3hi +IHpSKMbkoXlM1837WaFfx57kBIoIuNjKEyPIuK9wGUAeppc5QAHJg95PPEHNHlmM +yhBzClmgkyozRSeSrkxq9XeJKU94lWGaZ0zb4karCur/eiMoCk3YNV8L3styvcMG +1qUDCAaKx6FZEf7hE9RN6L3bAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSRMI58BxcMp/EJKGU2GmccaHb0WTANBgkq +hkiG9w0BAQ0FAAOCAQEACDXWlJGjzKadNMPcFlZInZC+Hl7RLrcBDR25jMCXg9yL +IwGVEcNp2fH4+YHTRTGLH81aPADMdUGHgpfcfqwjesavt/mO0T0S0LjJ0RVm93fE +heSNUHUigVR9njTVw2EBz7e2p+v3tOsMnunvm6PIDgHxx0W6mjzMX7lG74bJfo+v +dx+jI/aXt+iih5pi7/2Yu9eTDVu+S52wsnF89BEJeV0r+EmGDxUv47D+5KuQpKM9 +U/isXpwC6K/36T8RhhdOQXDq0Mt91TZ4dJTT0m3cmo80zzcxsKMDStZHOOzCBtBq +uIbwWw5Oa72o/Iwg9v+W0WkSBCWEadf/uK+cRicxrQ== +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/alice@smime.example.enc.pem b/tests/fixtures/rfc9216/alice@smime.example.enc.pem new file mode 100644 index 0000000..bc7db08 --- /dev/null +++ b/tests/fixtures/rfc9216/alice@smime.example.enc.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgITDy0lvRE5l0rOQlSHoe49NAaKtDANBgkqhkiG9w0BAQ0F +ADBVMQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQLEwhMQU1QUyBXRzExMC8GA1UEAxMo +U2FtcGxlIExBTVBTIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0xOTEx +MjAwNjU0MThaGA8yMDUyMDkyNzA2NTQxOFowOzENMAsGA1UEChMESUVURjERMA8G +A1UECxMITEFNUFMgV0cxFzAVBgNVBAMTDkFsaWNlIExvdmVsYWNlMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmpUp+ovBouOP6AFQJ+RpwpODxxzY60n1 +lJ53pTeNSiJlWkwtw/cxQq0t4uD2vWYB8gOUH/CVt2Zp1c+auzPKJ2Zu5mY6kHm+ +hVB+IthjLeI7Htg6rNeuXq50/TuTSxX5R1I1EXGt8p6hAQVeA5oZ2afHg4b97enV +8gozR0/Nkug4AkXmbk7THNc8vvjMUJanZ/VmS4TgDqXjWShplcI3lcvvBZMswt41 +/0HJvmSwqpS6oQcAx3Weag0yCNj1V9V9yu/3DjcYbwW2lJf5NbMHbM1LY4X5chWf +NEbkN6hQury/zxnlsukgn+fHbqvwDhJLAgFpW/jA/EB/WI+whUpqtQIDAQABo4Gv +MIGsMAwGA1UdEwEB/wQCMAAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMB4GA1Ud +EQQXMBWBE2FsaWNlQHNtaW1lLmV4YW1wbGUwEwYDVR0lBAwwCgYIKwYBBQUHAwQw +DgYDVR0PAQH/BAQDAgUgMB0GA1UdDgQWBBSiU0HVRDyAKRV8ASPw546vzfN3DzAf +BgNVHSMEGDAWgBSRMI58BxcMp/EJKGU2GmccaHb0WTANBgkqhkiG9w0BAQ0FAAOC +AQEAgUl4oJyxMpwWpAylOvK6NEbMl1gD5H14EC4Muxq1u0q2XgXOSBHI6DfX/4LD +sfx7fSIus8gWVY3WqMeuOA7IizkBD+GDEu8uKveERRXZncxGwy2MfbH1Ib3U8QzT +jqB8+dz2AwYeMxODWq9opwtA/lTOkRg8uuivZfg/m5fFo/QshlHNaaTDVEXsU4Ps +98Hm/3gznbvhdjFbZbi4oZ3tAadRlE5K9JiQaJYOnUmGpfB8PPwDR6chMZeegSQA +W++OIKqHrg/WEh4yiuPfqmAvX2hZkPpivNJYdTPUXTSO7K459CyqbqG+sNOo2kc1 +nTXl85RHNrVKQK+L0YWY1Q+hWA== +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/alice@smime.example.sig.pem b/tests/fixtures/rfc9216/alice@smime.example.sig.pem new file mode 100644 index 0000000..f6dd7e9 --- /dev/null +++ b/tests/fixtures/rfc9216/alice@smime.example.sig.pem @@ -0,0 +1,68 @@ +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgITN0EFee11f0Kpolw69Phqzpqp1zANBgkqhkiG9w0BAQ0F +ADBVMQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQLEwhMQU1QUyBXRzExMC8GA1UEAxMo +U2FtcGxlIExBTVBTIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0xOTEx +MjAwNjU0MThaGA8yMDUyMDkyNzA2NTQxOFowOzENMAsGA1UEChMESUVURjERMA8G +A1UECxMITEFNUFMgV0cxFzAVBgNVBAMTDkFsaWNlIExvdmVsYWNlMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtPSJ6Fg4Fj5Nmn9PkrYo0jTkfCv4TfA/ +pdO/KLpZbJOAEr0sI7AjaO7B1GuMUFJeSTulamNfCwDcDkY63PQWl+DILs7GxVwX +urhYdZlaV5hcUqVAckPvedDBc/3rz4D/esFfs+E7QMFtmd+K04s+A8TCNO12DRVB +DpbP4JFD9hsc8prDtpGmFk7rd0q8gqnhxBW2RZAeLqzJOMayCQtws1q7ktkNBR2w +ZX5ICjecF1YJFhX4jrnHwp/iELGqqaNXd3/Y0pG7QFecN7836IPPdfTMSiPR+peC +rhJZwLSewbWXLJe3VMvbvQjoBMpEYlaJBUIKkO1zQ1Pq90njlsJLOwIDAQABo4Gv +MIGsMAwGA1UdEwEB/wQCMAAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMB4GA1Ud +EQQXMBWBE2FsaWNlQHNtaW1lLmV4YW1wbGUwEwYDVR0lBAwwCgYIKwYBBQUHAwQw +DgYDVR0PAQH/BAQDAgbAMB0GA1UdDgQWBBS79syyLR0GEhyXrilqkBDTIGZmczAf +BgNVHSMEGDAWgBSRMI58BxcMp/EJKGU2GmccaHb0WTANBgkqhkiG9w0BAQ0FAAOC +AQEAc4miNqfOqaBpI3f+CpJDhxtuZ2P9HjQEQ+v6BdP7GKJ19naIs3BjJOd64roA +KHAp+c284VvyVXWJ99FMX8q2ZUQMxH+xh6oAfzcozmnd6XaVWHg4eHIjSo27PmhK +E1oAJKKhDbdbEcZXL2+x1V+duGymWtaD01DZZukKYr7agyHahiXRn/C9cy31wbqN +sy9x0fjPQg6+DqatiQpMz9EIae6aCHHBhOiPU7IPkazgPYgkLD59fk4PGHnYxs1F +hdO6zZk9E8zwlc1ALgZa/iSbczisqckN3qGehD2s16jMhwFXLJtBiN+uCDgNG/D0 +qyTbY4fgKieUHx/tHuzUszZxJg== +-----END CERTIFICATE----- + +4.2. Alice's Signing Private Key Material + +This private key material is used by Alice to create signatures. + +-----BEGIN PRIVATE KEY----- +MIIE+gIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC09InoWDgWPk2a +f0+StijSNOR8K/hN8D+l078oullsk4ASvSwjsCNo7sHUa4xQUl5JO6VqY18LANwO +Rjrc9BaX4MguzsbFXBe6uFh1mVpXmFxSpUByQ+950MFz/evPgP96wV+z4TtAwW2Z +34rTiz4DxMI07XYNFUEOls/gkUP2GxzymsO2kaYWTut3SryCqeHEFbZFkB4urMk4 +xrIJC3CzWruS2Q0FHbBlfkgKN5wXVgkWFfiOucfCn+IQsaqpo1d3f9jSkbtAV5w3 +vzfog8919MxKI9H6l4KuElnAtJ7BtZcsl7dUy9u9COgEykRiVokFQgqQ7XNDU+r3 +SeOWwks7AgMBAAECggEAFKD2DG9A1u77q3u3p2WDH3zueTtiqgaT8u8XO+jhOI/+ +HzoX9eo8DIJ/b/G3brwHyfh17JFvLH1zbgsn5bghJTz3r+JcZZ5l3srqMV8t8zjI +JEHOKC3szH8gYVKWrIgBAqOt1H9Ti8J2oKk2aymqBFr3ZXpBUCTWpEz2s3FMBUUI +qCEsAJqsdEch+kt43X5kvAom7LC1DHiE6RKfhMEub/LGNHSwY4dmzhaG6p95FJ1h +s8HoURI2ReVpsTadaKd3KoYNc1lcffmwdZs/hFs7xmmwXKMmlonh1mzHqD1/BqeJ +Hc8MP4ueDdyVgIe/uVtlQ9NcRQbuokkDyDYMYV6hzQKBgQD75ahYGFGZznRKtSE3 +w/2rUqTYIWxx2PQz5G58PcsTZM89Hj4aZOoLmudHbrTQHluRNcHoXEI62rs0cVPs +D7IlZOLfs+SSTeNEXxD57mjyyufpV65OcNc1mSJAmMX2jWQ8ndnOuWPcc5J6fNvT +au0a7ZBOaeKHnA8XXL3GYilM9QKBgQC35xKi7f2JmGtsYY21tfRuDUm6EjhMW6b7 +GWnI9IXF8TGj15s7oDEYvqSPTJdB6PAb/tZwdbj9mB4qj176x1kB/N7GO974O8UP +/PdHkU7duyf5nRq1mrI+yGFHVsGD313rc+akYdKcC207e6IRMST1ZFoznC6qNgpi +nNTuDz4ZbwKBgA5Dd9/dKKm77gvY69Objn6oBFuUsO5VaaaSlcsFOL2VZMLCNqQJ ++NLFZ7k8xJJQVcEIOT2uE7X/csBKdoUUcnL5nnsqVZQPQwI5G937KQgugylMZLte +WmFXlX/w5qzKXtWr3ox9JPFzveSfs1bqZBi1QQmfp0skhBo/jyNvpYUNAoGAMNkw +GhcdQW87GY7QFXQ/ePwOmV49lgrCT/BwKPDKl8l5ZgvfL/ddEzWQgH/XraoyHT2T +uEuM18+QM73hfLt26RBCHGXK1CUMMzL+fAQc7sjH1YXlkleFASg4rrpcrKqoR+KB +YSiayNhAK4yrf+WN66C8VPknbA7us0L1TEbAOAECgYEAtwRiiQwk3BlqENFypyc8 +0Q1pxp3U7ciHi8mni0kNcTqe57Y/2o8nY9ISnt1GffMs79YQfRXTRdEm2St6oChI +9Cv5j74LHZXkgEVFfO2Nq/uwSzTZkePk+HoPJo4WtAdokZgRAyyHl0gEae8Rl89e +yBX7dutONALjRZFTrg18CuegOzA5BgorBgEEAZIIEggBMSswKQYJYIZIAWUDBAIC +BBySyJ1DMNPY4x1P3pudD+bp/BQhQd1lpF5bQ28F +-----END PRIVATE KEY----- + +This secret key was generated using provable prime generation found +in [FIPS186-4] using the seed +92c89d4330d3d8e31d4fde9b9d0fe6e9fc142141dd65a45e5b436f05. This seed +is the first 224 bits of the SHA-256 ([SHA]) digest of the string +draft-lamps-sample-certs-keygen.alice.sign.seed. + +4.3. Alice's Encryption End-Entity Certificate + +This certificate is used to encrypt messages to Alice. + diff --git a/tests/fixtures/rfc9216/bob@smime.example.enc.pem b/tests/fixtures/rfc9216/bob@smime.example.enc.pem new file mode 100644 index 0000000..0770c01 --- /dev/null +++ b/tests/fixtures/rfc9216/bob@smime.example.enc.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDyjCCArKgAwIBAgITMHxHQA+GJjocYtLrgy+WwNeGlDANBgkqhkiG9w0BAQ0F +ADBVMQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQLEwhMQU1QUyBXRzExMC8GA1UEAxMo +U2FtcGxlIExBTVBTIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0xOTEx +MjAwNjU0MThaGA8yMDUyMDkyNzA2NTQxOFowODENMAsGA1UEChMESUVURjERMA8G +A1UECxMITEFNUFMgV0cxFDASBgNVBAMTC0JvYiBCYWJiYWdlMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqtHAlBNMiBIk8iJqwHk/yDoFWwj8P9Z1uYdq +1aqIuofvjoAyjdA8TbsBRGdmvaIOSQOepsNjW1ko7lE8HlDs9JHn1E+tzH3mKfn+ +G2erY+alkMJTXPvMAUdCA8+e1OJ7k91gYXDpzIWrP3Kc0xTlsJ8tGJ6mhydJX3wP +0/HuyHpfKQQfDusPH8S5yidPciWuB7Wj0X4xY1pUAz2rSSAlnGvhEzKFbW43BPjY +XPUnRWMtXFya1djq6Eb9M/klbhdZheDLLsjLUSXYU70r9VXGM/qcjd/NhWYphCeB +cqswaM5mXLYdm0mFmqoecF62mUE0DiNdhwKTtnefd0cll+D3FQIDAQABo4GtMIGq +MAwGA1UdEwEB/wQCMAAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMBwGA1UdEQQV +MBOBEWJvYkBzbWltZS5leGFtcGxlMBMGA1UdJQQMMAoGCCsGAQUFBwMEMA4GA1Ud +DwEB/wQEAwIFIDAdBgNVHQ4EFgQUSrOsMVMCSZxN42554CVhlT6IYiUwHwYDVR0j +BBgwFoAUkTCOfAcXDKfxCShlNhpnHGh29FkwDQYJKoZIhvcNAQENBQADggEBAC2c +Y8FgaxgB+Dx9gAFj35ae1vgzYiWI3Ax3FSxogo/GzpK//LB4215oeBuKXbm0ixBn +4nojxD7PMlM0i+ilAvVNJNaHY9TtgIgq8V/C0C7vL8SdBN01e5ZRI764ohu9ivYv +Ixvvt7gzvSTpe+NUT1i09xNgsC8v19WB/BwkqMAgDqMxqCxT4fyrvVwpxNBke75j +E6Q3xCjfdOWYcfMLK7EsTSgimYuonZjN7v/yqTdjn/iVH+agL/2MlSfiU36w/Yf1 +7EM09uKGH/Javh+2Vjd0j8rE/q2Iaac5VI91M6xz5oDZUknycBKKinR+nJWMt5AK +UAaL2Mjl3YtrUGBpxxY= +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/bob@smime.example.sig.pem b/tests/fixtures/rfc9216/bob@smime.example.sig.pem new file mode 100644 index 0000000..5f64aa8 --- /dev/null +++ b/tests/fixtures/rfc9216/bob@smime.example.sig.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDyjCCArKgAwIBAgITaqOkD33fBy/kGaVsmPv8LghbwzANBgkqhkiG9w0BAQ0F +ADBVMQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQLEwhMQU1QUyBXRzExMC8GA1UEAxMo +U2FtcGxlIExBTVBTIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0xOTEx +MjAwNjU0MThaGA8yMDUyMDkyNzA2NTQxOFowODENMAsGA1UEChMESUVURjERMA8G +A1UECxMITEFNUFMgV0cxFDASBgNVBAMTC0JvYiBCYWJiYWdlMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5nAF0glRof9NjBKke6g+7RLrOgRfwQjcH+2z +m0Af67FJRNrEwTuOutlWamUA3p9+wb7XqizVHOQhVesjwgp8PJpo8Adm8ar84d2t +tey1OVdxaCJuNe7SJjfrwShB6NvAm7S8CDG3+EapkO9fzn2pWwaREQ6twWtHi1QT +51PduRtiQ1oqsuJk8LBDgUMZlKUsaXfF8GKzJlGuaLRl5/3Kfr9+b6VkCDuxTZYL +Zxt6+a3/QkaC3I9m2ygPubtHFJB5P5+s8boROSKm1OB1gsLow8eF9S7OtcGGeooZ +JiJUQCR14NaU5bIyfKEZV2YStXwdztoEJJ2fRURIK+8YnwlB3QIDAQABo4GtMIGq +MAwGA1UdEwEB/wQCMAAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMBwGA1UdEQQV +MBOBEWJvYkBzbWltZS5leGFtcGxlMBMGA1UdJQQMMAoGCCsGAQUFBwMEMA4GA1Ud +DwEB/wQEAwIGwDAdBgNVHQ4EFgQUF8WEe9Cn73aQOLizbwi8krWeK5QwHwYDVR0j +BBgwFoAUkTCOfAcXDKfxCShlNhpnHGh29FkwDQYJKoZIhvcNAQENBQADggEBAG7e +QY6Px7WZC5vCbF5hjOitxoz3oyM+LRcSTGWoYXdmlwsNUzy31pE3dtADvevRtsP8 +uN7xyfK6XZBzhShA/BtkkqYGiFvXDpluOxWmqC0WPmc1PNK2mHil+pGMfvnUwnxd +6gKcHED5p+bUhDyIH2fy9hGyeOUs8nvi+7/HwBipN+nA/PfsPn+aU4l1K6qDoG/i +kwyuiWcFFlc5yE5rkAe2J0/a4+HtzNmTK4jB/4GbyI6xlUszPlEqKE+Es10Xut/y +UWL5nKKaqpRRd07Pq371MpFQs2+zXt4fGheKzZU3XXrIPcAPyJjWiyU1DzpqgSJM +OIp/HtXdFscHb9+Qic8= +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/carlos@smime.example.enc.pem b/tests/fixtures/rfc9216/carlos@smime.example.enc.pem new file mode 100644 index 0000000..8f3a4ba --- /dev/null +++ b/tests/fixtures/rfc9216/carlos@smime.example.enc.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICNDCCAeagAwIBAgITfz0Bv+b1OMAT79aCh3arViNvhDAFBgMrZXAwWTENMAsG +A1UEChMESUVURjERMA8GA1UECxMITEFNUFMgV0cxNTAzBgNVBAMTLFNhbXBsZSBM +QU1QUyBFZDI1NTE5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MCAXDTIwMTIxNTIx +MzU0NFoYDzIwNTIxMjE1MjEzNTQ0WjA6MQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQL +EwhMQU1QUyBXRzEWMBQGA1UEAxMNQ2FybG9zIFR1cmluZzAqMAUGAytlbgMhAC5o +MczTIMiddTUYTc/WymEqXw8hZm1QbIz2xX2gFDx0o4HdMIHaMCsGCSqGSIb3DQEJ +DwQeMBwwGgYLKoZIhvcNAQkQAxMwCwYJYIZIAWUDBAEFMAwGA1UdEwEB/wQCMAAw +FwYDVR0gBBAwDjAMBgpghkgBZQMCATABMB8GA1UdEQQYMBaBFGNhcmxvc0BzbWlt +ZS5leGFtcGxlMBMGA1UdJQQMMAoGCCsGAQUFBwMEMA4GA1UdDwEB/wQEAwIDCDAd +BgNVHQ4EFgQUgSmg+iOgSyCMDXgA3u3aFss0JbkwHwYDVR0jBBgwFoAUa6KVfboU +m+QtBNEHpNGC5C5rjLUwBQYDK2VwA0EAzss75UzFuADPfd4hQdo5jyAQ3GvkyyvI +BdBGnWtJ1eT1WuMaIMhi1rH4vPGPd9scwW+sqd9fG+pv3MShl+zKAQ== +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/carlos@smime.example.sig.pem b/tests/fixtures/rfc9216/carlos@smime.example.sig.pem new file mode 100644 index 0000000..123ebd2 --- /dev/null +++ b/tests/fixtures/rfc9216/carlos@smime.example.sig.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICBzCCAbmgAwIBAgITP14fVCTRtAFDeA9zwYoXhR52ljAFBgMrZXAwWTENMAsG +A1UEChMESUVURjERMA8GA1UECxMITEFNUFMgV0cxNTAzBgNVBAMTLFNhbXBsZSBM +QU1QUyBFZDI1NTE5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MCAXDTIwMTIxNTIx +MzU0NFoYDzIwNTIxMjE1MjEzNTQ0WjA6MQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQL +EwhMQU1QUyBXRzEWMBQGA1UEAxMNQ2FybG9zIFR1cmluZzAqMAUGAytlcAMhAMLO +gDIs3mHITYRNYO+RnOedrq5/HuQHXSPyAKaS98ito4GwMIGtMAwGA1UdEwEB/wQC +MAAwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMB8GA1UdEQQYMBaBFGNhcmxvc0Bz +bWltZS5leGFtcGxlMBMGA1UdJQQMMAoGCCsGAQUFBwMEMA4GA1UdDwEB/wQEAwIG +wDAdBgNVHQ4EFgQUZIXjO5wdWs3mC7oafwi+xJzMhD8wHwYDVR0jBBgwFoAUa6KV +fboUm+QtBNEHpNGC5C5rjLUwBQYDK2VwA0EAwVGQWbdy6FQIpTFsaWvG2/US2fnS +6B+BzgCrkGQKWX1WgkTj4MEOqL+0cFXLr7ZQ2DQUo2iXyTAu58BR6btcCQ== +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/dana@smime.example.enc.pem b/tests/fixtures/rfc9216/dana@smime.example.enc.pem new file mode 100644 index 0000000..048dd41 --- /dev/null +++ b/tests/fixtures/rfc9216/dana@smime.example.enc.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICMDCCAeKgAwIBAgITDksKNqnvupyaO2gkjlIdwN7zpzAFBgMrZXAwWTENMAsG +A1UEChMESUVURjERMA8GA1UECxMITEFNUFMgV0cxNTAzBgNVBAMTLFNhbXBsZSBM +QU1QUyBFZDI1NTE5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MCAXDTIwMTIxNTIx +MzU0NFoYDzIwNTIxMjE1MjEzNTQ0WjA4MQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQL +EwhMQU1QUyBXRzEUMBIGA1UEAxMLRGFuYSBIb3BwZXIwKjAFBgMrZW4DIQDgMaI2 +AWkU9LG8CvaRHgDSEY9d72Y8ENZeMwibPugkVKOB2zCB2DArBgkqhkiG9w0BCQ8E +HjAcMBoGCyqGSIb3DQEJEAMTMAsGCWCGSAFlAwQBBTAMBgNVHRMBAf8EAjAAMBcG +A1UdIAQQMA4wDAYKYIZIAWUDAgEwATAdBgNVHREEFjAUgRJkYW5hQHNtaW1lLmV4 +YW1wbGUwEwYDVR0lBAwwCgYIKwYBBQUHAwQwDgYDVR0PAQH/BAQDAgMIMB0GA1Ud +DgQWBBSd303UBe+a7GCGvCdtBOnOWtyPpDAfBgNVHSMEGDAWgBRropV9uhSb5C0E +0Qek0YLkLmuMtTAFBgMrZXADQQD6f7DCCxXzpnY3BwmrIuf/SNQSf//Otri7USkd +9GF+VthGS+9KJ4HTBCh0ZGuHIU9EgnfgdSL1UR3WUkL7tv8A +-----END CERTIFICATE----- diff --git a/tests/fixtures/rfc9216/dana@smime.example.sig.pem b/tests/fixtures/rfc9216/dana@smime.example.sig.pem new file mode 100644 index 0000000..78f3e8a --- /dev/null +++ b/tests/fixtures/rfc9216/dana@smime.example.sig.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICAzCCAbWgAwIBAgITaWZI+hVtn8pQZviAmPmBXzWfnjAFBgMrZXAwWTENMAsG +A1UEChMESUVURjERMA8GA1UECxMITEFNUFMgV0cxNTAzBgNVBAMTLFNhbXBsZSBM +QU1QUyBFZDI1NTE5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MCAXDTIwMTIxNTIx +MzU0NFoYDzIwNTIxMjE1MjEzNTQ0WjA4MQ0wCwYDVQQKEwRJRVRGMREwDwYDVQQL +EwhMQU1QUyBXRzEUMBIGA1UEAxMLRGFuYSBIb3BwZXIwKjAFBgMrZXADIQCy2h3h +hkaKDY67PuCuNLnnrQiHdSWYpPlgFsOif85vrqOBrjCBqzAMBgNVHRMBAf8EAjAA +MBcGA1UdIAQQMA4wDAYKYIZIAWUDAgEwATAdBgNVHREEFjAUgRJkYW5hQHNtaW1l +LmV4YW1wbGUwEwYDVR0lBAwwCgYIKwYBBQUHAwQwDgYDVR0PAQH/BAQDAgbAMB0G +A1UdDgQWBBRIA4bBabh4ba7e88wGsDOsVzLdljAfBgNVHSMEGDAWgBRropV9uhSb +5C0E0Qek0YLkLmuMtTAFBgMrZXADQQDpORBZitzXGYUjxnoKVLIcWL5xner97it5 +VKxEf8E7AeAp96POPEu//2jXnh4qAT40ymW0wrqxU1NT8WW/dSgC +-----END CERTIFICATE----- diff --git a/tests/test_certificate_validator.py b/tests/test_certificate_validator.py index 84b5715..b854129 100644 --- a/tests/test_certificate_validator.py +++ b/tests/test_certificate_validator.py @@ -7,8 +7,9 @@ from asn1crypto import pem, x509 from asn1crypto.util import timezone +from oscrypto import asymmetric from certvalidator import CertificateValidator, ValidationContext -from certvalidator.errors import PathValidationError +from certvalidator.errors import PathBuildingError, PathValidationError from ._unittest_compat import patch @@ -24,6 +25,9 @@ class CertificateValidatorTests(unittest.TestCase): def _load_nist_cert(self, filename): return self._load_cert_object('nist_pkits', 'certs', filename) + def _load_smime_cert(self, filename): + return self._load_cert_object('rfc9216', filename) + def _load_cert_object(self, *path_components): with open(os.path.join(fixtures_dir, *path_components), 'rb') as f: cert_bytes = f.read() @@ -122,3 +126,211 @@ def test_basic_certificate_validator_tls_whitelist(self): # If whitelist does not work, this will raise exception for key usage validator.validate_usage(set(['crl_sign'])) + + def test_basic_certificate_validator_rsa_smime_sig(self): + cert = self._load_smime_cert('alice@smime.example.sig.pem') + root_certs = [self._load_smime_cert('Sample_LAMPS_RSA_Certification_Authority.selfsigned.pem')] + + moment = datetime(2022, 4, 21, 0, 0, 0, tzinfo=timezone.utc) + + context = ValidationContext(trust_roots=root_certs, moment=moment) + validator = CertificateValidator(cert, validation_context=context) + + path = validator.validate_usage( + set(['digital_signature']), + set(['email_protection']) + ) + + expected_names = [ + "Common Name: Sample LAMPS RSA Certification Authority, " + "Organizational Unit: LAMPS WG, Organization: IETF", + "Common Name: Alice Lovelace, " + "Organizational Unit: LAMPS WG, Organization: IETF", + ] + expected_hashes = [ + b'HkZ\x81\tDM\xbb\r\x8c\x89\x7f\x08\xaa\xa5\xf2\xfb+\xc0\xb1', + b'*\x86\x97\xa3\x9a^}8\xf6\n\x96\x10\xb7M\xfb}m%,&', + ] + + names = [item.subject.human_friendly for item in path] + hashes = [item.subject.sha1 for item in path] + + if len(path) == 2 and hashes == expected_hashes[1:]: + self.assertEqual(expected_names[1:], names) + self.assertEqual(expected_hashes[1:], hashes) + else: + self.assertEqual(expected_names, names) + self.assertEqual(expected_hashes, hashes) + + @unittest.skipIf(not hasattr(asymmetric, "eddsa_verify"), + "EdDSA not supported in this oscrypto version") + def test_basic_certificate_validator_eddsa_smime_sig(self): + cert = self._load_smime_cert('carlos@smime.example.sig.pem') + root_certs = [self._load_smime_cert('Sample_LAMPS_Ed25519_Certification_Authority.selfsigned.pem')] + + moment = datetime(2022, 4, 21, 0, 0, 0, tzinfo=timezone.utc) + + context = ValidationContext(trust_roots=root_certs, moment=moment) + validator = CertificateValidator(cert, validation_context=context) + + path = validator.validate_usage( + set(['digital_signature', 'non_repudiation']), + set(['email_protection']) + ) + + expected_names = [ + "Common Name: Sample LAMPS Ed25519 Certification Authority, " + "Organizational Unit: LAMPS WG, Organization: IETF", + "Common Name: Carlos Turing, " + "Organizational Unit: LAMPS WG, Organization: IETF", + ] + expected_hashes = [ + b'\x05,gW\xc7\xfd\\g\xb0$$\x7f\xd84-FJ\x94$.', + b'h\t\xcd\x86\xc8|P\xa0\x187vYSL^\xb1\x9f\xfe\xc9\x1d', + ] + + names = [item.subject.human_friendly for item in path] + hashes = [item.subject.sha1 for item in path] + + if len(path) == 2 and hashes == expected_hashes[1:]: + self.assertEqual(expected_names[1:], names) + self.assertEqual(expected_hashes[1:], hashes) + else: + self.assertEqual(expected_names, names) + self.assertEqual(expected_hashes, hashes) + + @unittest.skipIf(not hasattr(asymmetric, "eddsa_verify"), + "EdDSA not supported in this oscrypto version") + def test_basic_certificate_validator_eddsa_smime_enc(self): + cert = self._load_smime_cert('carlos@smime.example.enc.pem') + root_certs = [self._load_smime_cert('Sample_LAMPS_Ed25519_Certification_Authority.selfsigned.pem')] + + moment = datetime(2022, 4, 21, 0, 0, 0, tzinfo=timezone.utc) + + context = ValidationContext(trust_roots=root_certs, moment=moment) + validator = CertificateValidator(cert, validation_context=context) + + path = validator.validate_usage( + set(['key_agreement']), + set(['email_protection']) + ) + + expected_names = [ + "Common Name: Sample LAMPS Ed25519 Certification Authority, " + "Organizational Unit: LAMPS WG, Organization: IETF", + "Common Name: Carlos Turing, " + "Organizational Unit: LAMPS WG, Organization: IETF", + ] + expected_hashes = [ + b'\x05,gW\xc7\xfd\\g\xb0$$\x7f\xd84-FJ\x94$.', + b'h\t\xcd\x86\xc8|P\xa0\x187vYSL^\xb1\x9f\xfe\xc9\x1d', + ] + + names = [item.subject.human_friendly for item in path] + hashes = [item.subject.sha1 for item in path] + + if len(path) == 2 and hashes == expected_hashes[1:]: + self.assertEqual(expected_names[1:], names) + self.assertEqual(expected_hashes[1:], hashes) + else: + self.assertEqual(expected_names, names) + self.assertEqual(expected_hashes, hashes) + + @unittest.skipIf(not hasattr(asymmetric, "eddsa_verify"), + "EdDSA not supported in this oscrypto version") + def test_cross_rsa_certificate_validator_eddsa_smime_sig(self): + cert = self._load_smime_cert('dana@smime.example.sig.pem') + root_certs = [self._load_smime_cert('Sample_LAMPS_Ed25519_Certification_Authority.crosssigned.pem')] + cross_certs = [self._load_smime_cert('Sample_LAMPS_RSA_Certification_Authority.selfsigned.pem')] + + moment = datetime(2022, 4, 21, 0, 0, 0, tzinfo=timezone.utc) + + context = ValidationContext(trust_roots=cross_certs, moment=moment) + validator = CertificateValidator(cert, root_certs, validation_context=context) + + path = validator.validate_usage( + set(['digital_signature', 'non_repudiation']), + set(['email_protection']) + ) + + expected_names = [ + "Common Name: Sample LAMPS RSA Certification Authority, " + "Organizational Unit: LAMPS WG, Organization: IETF", + "Common Name: Sample LAMPS Ed25519 Certification Authority, " + "Organizational Unit: LAMPS WG, Organization: IETF", + "Common Name: Dana Hopper, " + "Organizational Unit: LAMPS WG, Organization: IETF", + ] + expected_hashes = [ + b'HkZ\x81\tDM\xbb\r\x8c\x89\x7f\x08\xaa\xa5\xf2\xfb+\xc0\xb1', + b'\x05,gW\xc7\xfd\\g\xb0$$\x7f\xd84-FJ\x94$.', + b'\tPP\xe6\xee\x8d\x82\xe7R\x920N\x1a\x96!\t\x95\x1d\x11\x8e', + ] + + names = [item.subject.human_friendly for item in path] + hashes = [item.subject.sha1 for item in path] + + if len(path) == 2 and hashes == expected_hashes[1:]: + self.assertEqual(expected_names[1:], names) + self.assertEqual(expected_hashes[1:], hashes) + else: + self.assertEqual(expected_names, names) + self.assertEqual(expected_hashes, hashes) + + @unittest.skipIf(not hasattr(asymmetric, "eddsa_verify"), + "EdDSA not supported in this oscrypto version") + def test_cross_eddsa_certificate_validator_rsa_smime_sig(self): + cert = self._load_smime_cert('bob@smime.example.sig.pem') + root_certs = [self._load_smime_cert('Sample_LAMPS_RSA_Certification_Authority.crosssigned.pem')] + cross_certs = [self._load_smime_cert('Sample_LAMPS_Ed25519_Certification_Authority.selfsigned.pem')] + + moment = datetime(2022, 4, 21, 0, 0, 0, tzinfo=timezone.utc) + + context = ValidationContext(trust_roots=cross_certs, moment=moment) + validator = CertificateValidator(cert, root_certs, validation_context=context) + + path = validator.validate_usage( + set(['digital_signature', 'non_repudiation']), + set(['email_protection']) + ) + + expected_names = [ + "Common Name: Sample LAMPS Ed25519 Certification Authority, " + "Organizational Unit: LAMPS WG, Organization: IETF", + "Common Name: Sample LAMPS RSA Certification Authority, " + "Organizational Unit: LAMPS WG, Organization: IETF", + "Common Name: Bob Babbage, " + "Organizational Unit: LAMPS WG, Organization: IETF", + ] + expected_hashes = [ + b'\x05,gW\xc7\xfd\\g\xb0$$\x7f\xd84-FJ\x94$.', + b'HkZ\x81\tDM\xbb\r\x8c\x89\x7f\x08\xaa\xa5\xf2\xfb+\xc0\xb1', + b"\xe7\x189h\xd9+_F\xce\x0b\xc8\xfb\xdc'\xd1\xf6\xfe]\xb1\xcd", + ] + + names = [item.subject.human_friendly for item in path] + hashes = [item.subject.sha1 for item in path] + + if len(path) == 2 and hashes == expected_hashes[1:]: + self.assertEqual(expected_names[1:], names) + self.assertEqual(expected_hashes[1:], hashes) + else: + self.assertEqual(expected_names, names) + self.assertEqual(expected_hashes, hashes) + + @unittest.skipIf(not hasattr(asymmetric, "eddsa_verify"), + "EdDSA not supported in this oscrypto version") + def test_non_cross_rsa_eddsa_smime(self): + cert = self._load_smime_cert('bob@smime.example.sig.pem') + root_certs = [self._load_smime_cert('Sample_LAMPS_Ed25519_Certification_Authority.crosssigned.pem')] + + moment = datetime(2022, 4, 21, 0, 0, 0, tzinfo=timezone.utc) + + context = ValidationContext(trust_roots=root_certs, moment=moment) + validator = CertificateValidator(cert, validation_context=context) + + with self.assertRaisesRegex(PathBuildingError, "no issuer matching \"Common Name: Sample LAMPS RSA"): + validator.validate_usage( + set(['digital_signature', 'non_repudiation']), + set(['email_protection']) + )