Created
May 12, 2022 19:23
-
-
Save nwalker/e77a372f27aabaae83d229a261671505 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(pkcs7_demo). | |
% reduced example for issue in github.com/erlang/otp | |
-compile([export_all]). | |
-include_lib("public_key/include/public_key.hrl"). | |
pkcs7_verify(Message, #'SignedData'{version = Vsn} = SD, Config) -> | |
Vsn == sdVer1 orelse erlang:error({unsupported_version, Vsn}), | |
#'SignedData'{ | |
certificates = {certSet, CS}, | |
signerInfos = {siSet, SignerInfos} | |
} = SD, | |
CertList = [C || {certificate, C} <- CS], | |
lists:foreach(fun(SI) -> | |
verify_signer_info(Message, SI, CertList, Config) | |
end, SignerInfos). | |
verify_signer_info(_Message, #'SignerInfo'{version = siVer1} = SI, CertList, _Config) -> | |
#'SignerInfo'{ | |
issuerAndSerialNumber = #'IssuerAndSerialNumber'{serialNumber = Serial}, | |
digestAlgorithm = {_, HashType, _}, | |
digestEncryptionAlgorithm = {_, _SignType, _}, | |
authenticatedAttributes = AuthenticatedAttributes, | |
encryptedDigest = Digest | |
} = SI, | |
AuthenticatedAttributes == undefined | |
andalso erlang:error({unsupported, authenticated_attributes_missing}), | |
{aaSet, _AAs} = AuthenticatedAttributes, | |
Found = [PKI || | |
#'OTPCertificate'{ | |
tbsCertificate = #'OTPTBSCertificate'{ | |
serialNumber = S, | |
subjectPublicKeyInfo = PKI | |
} | |
} <- CertList, S == Serial], | |
length(Found) > 0 orelse erlang:error({no_certificate_found, {serial, Serial}}), | |
#'OTPSubjectPublicKeyInfo'{ | |
algorithm = {_, _, NamedCurve}, | |
subjectPublicKey = ECPoint | |
} = hd(Found), | |
PublicKey = {ECPoint, NamedCurve}, | |
% ... skipped a few extra checks ... | |
AASetDER = case public_key:der_encode('SignerInfoAuthenticatedAttributes', AuthenticatedAttributes) of | |
% workaround mentioned in issue - asn1 tag replacement | |
% comment next line to get verification error | |
<<16#A0:8, Rest/binary>> -> <<16#31:8, Rest/binary>>; | |
Other -> Other | |
end, | |
public_key:verify(AASetDER, public_key:pkix_hash_type(HashType), Digest, PublicKey) | |
orelse erlang:error({bad_signature, {digest_mismatch, attributes}}); | |
verify_signer_info(_, #'SignerInfo'{version = Vsn}, _, _) -> | |
erlang:error({unsupported_version, Vsn}). | |
patch(#'SignedData'{version = sdVer1, certificates = {certSet, CS}} = SD) -> | |
% replace #'Certificate' with #'OTPCertificate' | |
CS1 = lists:map(fun ({certificate, C}) -> | |
C1 = public_key:pkix_decode_cert( | |
public_key:der_encode('Certificate', C), otp), | |
{certificate, C1} | |
end, CS), | |
SD#'SignedData'{ | |
certificates = {certSet, CS1} | |
}. | |
-ifdef(TEST). | |
simple_test() -> | |
Message = <<>>, % not used in reduced code | |
Signature = base64:decode(<< | |
"MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgEFADCABgkqhkiG9w0BBwEAAK", | |
"CAMIID4jCCA4igAwIBAgIIJEPyqAad9XcwCgYIKoZIzj0EAwIwejEuMCwGA1UEAwwlQXBwb", | |
"GUgQXBwbGljYXRpb24gSW50ZWdyYXRpb24gQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2Vyd", | |
"GlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTM", | |
"B4XDTE0MDkyNTIyMDYxMVoXDTE5MDkyNDIyMDYxMVowXzElMCMGA1UEAwwcZWNjLXNtcC1ic", | |
"m9rZXItc2lnbl9VQzQtUFJPRDEUMBIGA1UECwwLaU9TIFN5c3RlbXMxEzARBgNVBAoMCkFwcG", | |
"xlIEluYy4xCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwhV37evWx7I", | |
"hj2jdcJChIY3HsL1vLCg9hGCV2Ur0pUEbg0IO2BHzQH6DMx8cVMP36zIg1rrV1O/0komJPnwP", | |
"E6OCAhEwggINMEUGCCsGAQUFBwEBBDkwNzA1BggrBgEFBQcwAYYpaHR0cDovL29jc3AuYXBwb", | |
"GUuY29tL29jc3AwNC1hcHBsZWFpY2EzMDEwHQYDVR0OBBYEFJRX22/VdIGGiYl2L35XhQfnm1", | |
"gkMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUI/JJxE+T5O8n5sT2KGw/orv9LkswggEdBgN", | |
"VHSAEggEUMIIBEDCCAQwGCSqGSIb3Y2QFATCB/jCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5j", | |
"ZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb", | |
"2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZi", | |
"B1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF", | |
"0ZW1lbnRzLjA2BggrBgEFBQcCARYqaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVh", | |
"dXRob3JpdHkvMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuYXBwbGUuY29tL2FwcGxlY", | |
"WljYTMuY3JsMA4GA1UdDwEB/wQEAwIHgDAPBgkqhkiG92NkBh0EAgUAMAoGCCqGSM49BAMCA0", | |
"gAMEUCIHKKnw+Soyq5mXQr1V62c0BXKpaHodYu9TWXEPUWPpbpAiEAkTecfW6+W5l0r0ADfzT", | |
"CPq2YtbS39w01XIayqBNy8bEwggLuMIICdaADAgECAghJbS+/OpjalzAKBggqhkjOPQQDAjBn", | |
"MRswGQYDVQQDDBJBcHBsZSBSb290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljY", | |
"XRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0xND", | |
"A1MDYyMzQ2MzBaFw0yOTA1MDYyMzQ2MzBaMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9", | |
"uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0", | |
"aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGC", | |
"CqGSM49AwEHA0IABPAXEYQZ12SF1RpeJYEHduiAou/ee65N4I38S5PhM1bVZls1riLQl3YNIk", | |
"57ugj9dhfOiMt2u2ZwvsjoKYT/VEWjgfcwgfQwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzA", | |
"BhipodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDA0LWFwcGxlcm9vdGNhZzMwHQYDVR0OBBYE", | |
"FCPyScRPk+TvJ+bE9ihsP6K7/S5LMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUu7Deo", | |
"VgziJqkipnevr3rr9rLJKswNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5hcHBsZS5jb2", | |
"0vYXBwbGVyb290Y2FnMy5jcmwwDgYDVR0PAQH/BAQDAgEGMBAGCiqGSIb3Y2QGAg4EAgUAMAoG", | |
"CCqGSM49BAMCA2cAMGQCMDrPcoNRFpmxhvs1w1bKYr/0F+3ZD3VNoo6+8ZyBXkK3ifiY95tZn5", | |
"jVQQ2PnenC/gIwMi3VRCGwowV3bF3zODuQZ/0XfCwhbZZPxnJpghJvVPh6fRuZy5sJiSFhBpkP", | |
"CZIdAAAxggFfMIIBWwIBATCBhjB6MS4wLAYDVQQDDCVBcHBsZSBBcHBsaWNhdGlvbiBJbnRlZ3", | |
"JhdGlvbiBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTET", | |
"MBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMCCCRD8qgGnfV3MA0GCWCGSAFlAwQCAQ", | |
"UAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTQxMDI3MTk1", | |
"MTQzWjAvBgkqhkiG9w0BCQQxIgQge01fe4e1+woRnaV3o8bZL7vmTLEDsnZfTQq+D7GYjnIwCg", | |
"YIKoZIzj0EAwIERzBFAiEA5090eyrUE7pjWb8MqUeDp/vEY98vtrT0Uvre/66ccqQCICYe6cen", | |
"516x/xsfi/tJr3SbTdxO25ZdN1bPH0Jiqgw7AAAAAAAA">>), | |
#'ContentInfo'{ | |
content = SignedData | |
} = public_key:der_decode('ContentInfo', Signature), | |
#'SignedData'{} = SI = patch(SignedData), | |
pkcs7_verify(Message, SI, #{}). | |
-endif. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment