From 63114e925bc3a75ca577eef95a855e80542142f4 Mon Sep 17 00:00:00 2001 From: Emil Volckmar Ry Date: Wed, 17 May 2023 10:02:34 +0200 Subject: [PATCH] adds builtin: crypto.x509.parse_keypair. crypto.x509.parse_keypair(cert, key) takes PEM/DER (base64) encoded input. if key pair is valid, returns the tls.certificate(https://pkg.go.dev/crypto/tls#Certificate) as an object. if key pair is invalid, returns an error. Fixes #5853 Signed-off-by: Emil Volckmar Ry --- ast/builtins.go | 12 + builtin_metadata.json | 26 ++ capabilities.json | 25 ++ .../test-cryptox509parsekeypairs-0118.yaml | 13 + .../test-cryptox509parsekeypairs-0119.yaml | 13 + topdown/crypto.go | 79 ++++++ topdown/crypto_test.go | 260 ++++++++++++++++++ 7 files changed, 428 insertions(+) create mode 100644 test/cases/testdata/cryptox509parsekeypair/test-cryptox509parsekeypairs-0118.yaml create mode 100644 test/cases/testdata/cryptox509parsekeypair/test-cryptox509parsekeypairs-0119.yaml diff --git a/ast/builtins.go b/ast/builtins.go index c696eb1053..a0d68c6643 100644 --- a/ast/builtins.go +++ b/ast/builtins.go @@ -210,6 +210,7 @@ var DefaultBuiltins = [...]*Builtin{ CryptoSha256, CryptoX509ParseCertificateRequest, CryptoX509ParseRSAPrivateKey, + CryptoX509ParseKeyPair, CryptoHmacMd5, CryptoHmacSha1, CryptoHmacSha256, @@ -2289,6 +2290,17 @@ var CryptoX509ParseCertificateRequest = &Builtin{ ), } +var CryptoX509ParseKeyPair = &Builtin{ + Name: "crypto.x509.parse_keypair", + Description: "Returns a valid key pair", + Decl: types.NewFunction( + types.Args( + types.Named("cert", types.S).Description("string containing PEM or base64 encoded DER certificates"), + types.Named("pem", types.S).Description("string containing PEM or base64 encoded DER keys"), + ), + types.Named("output", types.NewObject(nil, types.NewDynamicProperty(types.S, types.A))).Description("if key pair is valid, returns the tls.certificate(https://pkg.go.dev/crypto/tls#Certificate) as an object. If the key pair is invalid, nil and an error are returned."), + ), +} var CryptoX509ParseRSAPrivateKey = &Builtin{ Name: "crypto.x509.parse_rsa_private_key", Description: "Returns a JWK for signing a JWT from the given PEM-encoded RSA private key.", diff --git a/builtin_metadata.json b/builtin_metadata.json index c4802da739..5cc287f9a0 100644 --- a/builtin_metadata.json +++ b/builtin_metadata.json @@ -44,6 +44,7 @@ "crypto.x509.parse_and_verify_certificates", "crypto.x509.parse_certificate_request", "crypto.x509.parse_certificates", + "crypto.x509.parse_keypair", "crypto.x509.parse_rsa_private_key" ], "encoding": [ @@ -4070,6 +4071,31 @@ }, "wasm": false }, + "crypto.x509.parse_keypair": { + "args": [ + { + "description": "string containing PEM or base64 encoded DER certificates", + "name": "cert", + "type": "string" + }, + { + "description": "string containing PEM or base64 encoded DER keys", + "name": "pem", + "type": "string" + } + ], + "available": [ + "edge" + ], + "description": "Returns a valid key pair", + "introduced": "edge", + "result": { + "description": "if key pair is valid, returns the tls.certificate(https://pkg.go.dev/crypto/tls#Certificate) as an object. If the key pair is invalid, nil and an error are returned.", + "name": "output", + "type": "object[string: any]" + }, + "wasm": false + }, "crypto.x509.parse_rsa_private_key": { "args": [ { diff --git a/capabilities.json b/capabilities.json index bfa43f4a59..a89d1f859e 100644 --- a/capabilities.json +++ b/capabilities.json @@ -779,6 +779,31 @@ "type": "function" } }, + { + "name": "crypto.x509.parse_keypair", + "decl": { + "args": [ + { + "type": "string" + }, + { + "type": "string" + } + ], + "result": { + "dynamic": { + "key": { + "type": "string" + }, + "value": { + "type": "any" + } + }, + "type": "object" + }, + "type": "function" + } + }, { "name": "crypto.x509.parse_rsa_private_key", "decl": { diff --git a/test/cases/testdata/cryptox509parsekeypair/test-cryptox509parsekeypairs-0118.yaml b/test/cases/testdata/cryptox509parsekeypair/test-cryptox509parsekeypairs-0118.yaml new file mode 100644 index 0000000000..d7bc4498d5 --- /dev/null +++ b/test/cases/testdata/cryptox509parsekeypair/test-cryptox509parsekeypairs-0118.yaml @@ -0,0 +1,13 @@ +cases: + - note: cryptoX509ParseKeyPairs/PEM_encoded_string_cert_and_key + query: data.test.p = x + modules: + - | + package test + p := crypto.x509.parse_keypair(input.cert, input.key)["Certificate"][0] + input: { + cert: "-----BEGIN CERTIFICATE-----\nMIIEszCCApsCFDPRm4sTNZqiH601E6E6pEaJaCKqMA0GCSqGSIb3DQEBCwUAMBYx\nFDASBgNVBAMMC2V4YW1wbGUuY29tMB4XDTIzMDUxMjEyMDIxNFoXDTIzMDYxMTEy\nMDIxNFowFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUA\nA4ICDwAwggIKAoICAQDTcNASD17ohP3V14LMUIkFwAeeeniSXy4Pl3EqIgVpt9ul\n2IZiTm4JOYSgQ681bjt1OdwCkBf2Cg62DUyHMMwwnbaznN/Y5piYlaS33XCvcNpM\nOWxwA4Z5Q0jNAshBExp8EzjEojbIUoeSncAP9jtOO/NArhLq+XodmONLqBG8KmZc\n2uiAeJ7ZjTpOckASYPYy7tUc4Ha3XUV0SoF/+0SJrXYOtpyMuMxwks6jMbpacmZn\njFIe8m2xH97s5inmHkzjBVKbpBQQHROP6A61VOrH9FrJRiACZ440zFJ1CGlXZau4\noJgs9S1YRDI4W2Ha1WIYLpUBEMYXVYyn4swTBj42HqpSmfppOoR2g1d/AjxpFVAk\nPLrict/nszhTIkEUE39vJh4HuytT49ss/cp4KokxBjLz7LmTUEzxJS8dB9714KzO\nhFRHnpap0onU7Yb+Yz8/21bZL4AEL1d2Jg48jRET1Mrl9GOnWjzo7JxioUsbLcOo\ny8Qcu2L87BQZqHCVpq6TcJKfPgh9t7y1AHvAfoXJdGSwimCZXuR4VEA3NJAHgPOw\nLypB+dukzseWLdN+e7YOYqyWfjJg4aQmCx+nr866/QlQ4mrEBTkBsDOO5tEsKugI\nredu+lL6z9QFdmeQpoC+s6JKnV29KHZXNDBZ1gnXOyA6lIBjjFjZqnkwT1ToHwID\nAQABMA0GCSqGSIb3DQEBCwUAA4ICAQC8v5BIEooDSe5Kpzwsh9QLK7Ip33v4VHo+\nq82DRjAXiosFoaJ1dg+hwXOUo5VPSOqWCPNYRHDabuX4oiZAGPA9O5lTKQ/PQS4y\nYIsD9XgeuDllBo3Y/uBwjoFFAD169fYMmZgGQ/PCdFS9nrYduPAIzNnsip+Z+XRK\nqLwm83H/nKKgVvbGprNcivG3c8H42CKQ7aqDkEGuSG9EVRnQOMaI7ILMx/oj33Mk\nuJ/21z4AHj7ads3dUF4syEBo5gWCAiBd+g1E/BkFnn+G+oOYo7c12dB+r6rbgrA0\nBk+bW0NvU2ApP/LRRGaJD4wW2UoAklL618+CRWNtXdT+WeKIPlrEdC/0yzU5t6sA\nII+PfvbeWQfL5CssbWhkTbJFt3JKTrIMc9cMjNcqeS+bAELuI16d4CZ5TlmZZeMd\n1WCv6R3YifkR9IogZhix20nPCF1mfo7Q0XAywkx8pPAC4n6uYStU9YobNAGlWXz+\nYbbJDf9r9au88Gu6xFf3eETKu2tJsQgVYBmXic85+FoV45qBI5YZvqiX9XZtWXw2\n391fW+NdK01Jc0tqtADubaF6D4ncnriufqcz+70O0p7CzPbTMtUsPFxcfqZ6x1KX\ngP1TgZM++PuYjHEyCFhHQBz9cQlxPdW4alaDYBnnKvLZXDOAXCWVWS6SXa5tkU3n\nk9i0HC1bhg==\n-----END CERTIFICATE-----\n", + key: "-----BEGIN PRIVATE KEY-----\n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\nAj0c+XArCS87P4iflF9maJ3Tk/NfaA==\n-----END PRIVATE KEY-----\n" + } + want_result: + - x: "MIIEszCCApsCFDPRm4sTNZqiH601E6E6pEaJaCKqMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNVBAMMC2V4YW1wbGUuY29tMB4XDTIzMDUxMjEyMDIxNFoXDTIzMDYxMTEyMDIxNFowFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDTcNASD17ohP3V14LMUIkFwAeeeniSXy4Pl3EqIgVpt9ul2IZiTm4JOYSgQ681bjt1OdwCkBf2Cg62DUyHMMwwnbaznN/Y5piYlaS33XCvcNpMOWxwA4Z5Q0jNAshBExp8EzjEojbIUoeSncAP9jtOO/NArhLq+XodmONLqBG8KmZc2uiAeJ7ZjTpOckASYPYy7tUc4Ha3XUV0SoF/+0SJrXYOtpyMuMxwks6jMbpacmZnjFIe8m2xH97s5inmHkzjBVKbpBQQHROP6A61VOrH9FrJRiACZ440zFJ1CGlXZau4oJgs9S1YRDI4W2Ha1WIYLpUBEMYXVYyn4swTBj42HqpSmfppOoR2g1d/AjxpFVAkPLrict/nszhTIkEUE39vJh4HuytT49ss/cp4KokxBjLz7LmTUEzxJS8dB9714KzOhFRHnpap0onU7Yb+Yz8/21bZL4AEL1d2Jg48jRET1Mrl9GOnWjzo7JxioUsbLcOoy8Qcu2L87BQZqHCVpq6TcJKfPgh9t7y1AHvAfoXJdGSwimCZXuR4VEA3NJAHgPOwLypB+dukzseWLdN+e7YOYqyWfjJg4aQmCx+nr866/QlQ4mrEBTkBsDOO5tEsKugIredu+lL6z9QFdmeQpoC+s6JKnV29KHZXNDBZ1gnXOyA6lIBjjFjZqnkwT1ToHwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQC8v5BIEooDSe5Kpzwsh9QLK7Ip33v4VHo+q82DRjAXiosFoaJ1dg+hwXOUo5VPSOqWCPNYRHDabuX4oiZAGPA9O5lTKQ/PQS4yYIsD9XgeuDllBo3Y/uBwjoFFAD169fYMmZgGQ/PCdFS9nrYduPAIzNnsip+Z+XRKqLwm83H/nKKgVvbGprNcivG3c8H42CKQ7aqDkEGuSG9EVRnQOMaI7ILMx/oj33MkuJ/21z4AHj7ads3dUF4syEBo5gWCAiBd+g1E/BkFnn+G+oOYo7c12dB+r6rbgrA0Bk+bW0NvU2ApP/LRRGaJD4wW2UoAklL618+CRWNtXdT+WeKIPlrEdC/0yzU5t6sAII+PfvbeWQfL5CssbWhkTbJFt3JKTrIMc9cMjNcqeS+bAELuI16d4CZ5TlmZZeMd1WCv6R3YifkR9IogZhix20nPCF1mfo7Q0XAywkx8pPAC4n6uYStU9YobNAGlWXz+YbbJDf9r9au88Gu6xFf3eETKu2tJsQgVYBmXic85+FoV45qBI5YZvqiX9XZtWXw2391fW+NdK01Jc0tqtADubaF6D4ncnriufqcz+70O0p7CzPbTMtUsPFxcfqZ6x1KXgP1TgZM++PuYjHEyCFhHQBz9cQlxPdW4alaDYBnnKvLZXDOAXCWVWS6SXa5tkU3nk9i0HC1bhg==" diff --git a/test/cases/testdata/cryptox509parsekeypair/test-cryptox509parsekeypairs-0119.yaml b/test/cases/testdata/cryptox509parsekeypair/test-cryptox509parsekeypairs-0119.yaml new file mode 100644 index 0000000000..634cc73f5d --- /dev/null +++ b/test/cases/testdata/cryptox509parsekeypair/test-cryptox509parsekeypairs-0119.yaml @@ -0,0 +1,13 @@ +cases: + - note: cryptoX509ParseKeyPairs/base64_encoded_string_cert_and_key + query: data.test.p = x + modules: + - | + package test + p := crypto.x509.parse_keypair(input.cert, input.key)["Certificate"][0] + input: { + cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUY3ekNDQTllZ0F3SUJBZ0lVZFJIQStCMC9aZ2tuS1BsQjJmc3dFOThsekFjd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2dZWXhDekFKQmdOVkJBWVRBbGhZTVJJd0VBWURWUVFJREFsVGRHRjBaVTVoYldVeEVUQVBCZ05WQkFjTQpDRU5wZEhsT1lXMWxNUlF3RWdZRFZRUUtEQXREYjIxd1lXNTVUbUZ0WlRFYk1Ca0dBMVVFQ3d3U1EyOXRjR0Z1CmVWTmxZM1JwYjI1T1lXMWxNUjB3R3dZRFZRUUREQlJEYjIxdGIyNU9ZVzFsVDNKSWIzTjBibUZ0WlRBZUZ3MHkKTXpBMU1UQXhNalV4TWpoYUZ3MHpNekExTURjeE1qVXhNamhhTUlHR01Rc3dDUVlEVlFRR0V3SllXREVTTUJBRwpBMVVFQ0F3SlUzUmhkR1ZPWVcxbE1SRXdEd1lEVlFRSERBaERhWFI1VG1GdFpURVVNQklHQTFVRUNnd0xRMjl0CmNHRnVlVTVoYldVeEd6QVpCZ05WQkFzTUVrTnZiWEJoYm5sVFpXTjBhVzl1VG1GdFpURWRNQnNHQTFVRUF3d1UKUTI5dGJXOXVUbUZ0WlU5eVNHOXpkRzVoYldVd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJSwpBb0lDQVFDM045anZpY21LcEdkMVAzcFhlQStNb2lkZE5qSjV2TTEzS3FhVGMxMjltY21ISHRJcmpHbmhvTHJOClNMV2NMR0tOQmJzQk5pNWxvcTQxc0pvZ3ltTnhVc3hRUUVyWG41RGlFbkVRZjFCcStuU0d6SWRHbWJtSlZXcUgKdDR0U0lIZENJRWF4SERIV2tJb2tsUjR0OENnTkl2aEtxbEdHSmx2TGZQVlpnV0hqczlIQSs2K0czNXRwL1pnQQp2U0EvTnV0azVQOUFMT2pseXNpeVNpWDZtYVJQayt5ck5mcHF6QTljbEllVlFRQ1RTR0hSUGVPeGcxU1NxcEhoCk11a3VZMDFKSHdvdEJVUWxOS3VEV0J3ejEzRk91YVBjNzRnMHBzTlFXZUNJaTdJWjZjUFpXSmZiQ2tSSEIwZUYKcGFPR2NueUZGYWZBZk5ZWjF3Wjg3SDZVM1U0endyMElMeFl6NkRuOEI0Zklra29ZMTlQSEVtbjR0ckhtNXdiUgpuSlZQaWVmZkFaenFLL3pjYWlCRlZEZEdRQy9UeTNLNXo5K1ZGYkl6UFdJUjVTNndlV3RiQThoM2FhL0UvdEhTCkNZV3ZpKzRSd3FQeGZXUTZKZXZ4ZFdDMDhSZ3kxSVB6N3Zxa3ZEMGJnN1JmMDF2SVVvaE8zdmJvSDdKejJLMG8KdkVHaVJkY1BRZkJ4eS9SNk80ZXN0UHBUTEU5Q1NTa2NUQVFjaWZDcG4zT1U4L3Z1UkxERXk5QXQrbWFkK0c1VgpLaVNubzhENXlnbGpPSEVRSUNaTzBjRU5GNXVWY3JOTmhRWVMwSmQ3RjllVkNTTzhIVUNzbE1xRjJlZG5GQ3BTCmZyWUlRa3NSVGdlajRiWFV4bFRGM3ZmakVabjVpZFZzSWdqMnRWUW9OMGRybjhNQVNRSURBUUFCbzFNd1VUQWQKQmdOVkhRNEVGZ1FVbERYeVAySHIrVlFNMWFIbHpjTjliRGxNYkpzd0h3WURWUjBqQkJnd0ZvQVVsRFh5UDJIcgorVlFNMWFIbHpjTjliRGxNYkpzd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DCkFnRUFDekdyZlhWWWhmQ210RlpOMFk2TktRN2cxSFZHSVg1VjNBbDRVK29vM3krOW40S1ZHa2dWOWpoL2RaOGsKbXpXbXBYT0dSZkQxdWZSY0Q5cW9YeStHSFJ3LzBibTJ3a1ZjTXZFc25NeCtEa3VoaVZPSWMwUFlETmo4N3VLMwp2TkZCTTM5dW8xZmlKOXlkOVNLUXNqQjk0bFZNYUYxMDg5d2V2UFlsNXFtYm9rdTJxdXJYM3V3NVZ2eXNIQUF3ClUyeTB4OHkvYzNqdzlNZksxWDBHWWhTY1owcFYzeTN4dGxxckhuTmpTUmFaM3BmUGw3NGFjMGJndEU5cThKdDUKbzNEMGdmWmkwOFJrdW5ua2dKMS9QZDVpYUgvWEdnVG56NXdTRUF6VFJCWEhLWVlvRnBGV0wwcnowa0pvamZDdwpSdXQ2T21uL0w2blFXL1I1endzcXZrQUR1by9LWFkyTjY5L1J4UHcwejhFcTZZTVR0OHBXOGU1ZHpSRlFUS2N2CktUdDJCNTB1VFVEUlBRbW92dkYzRmRqcllaYkhyRlhHUXIyaGV6bDU2QkRSSkJaTzhIQ0g0NEIxc3d6K3QySWYKb3V2MlBIZDA1V3ZDVHIvM0dFL2ZiVGpabFVWeDhaYTJUWXdWakhTUzl3OWtRQ1V2dzNXM25OdVF6TklHVGJzYQpEdlQzeVN0MjJkRDQwTVlrNHpOc3o4d1YwUVYwdmJ5enorMUZUSXJlVldJSXhpMHVveWdNaHVGTDdJem4xeHNBClQ4TWVsbHQzN20wM2V2QkxwUXdPWHF0N1JXWlNaMllydVQ2clpkZ2RBOXRlK2Y3VUxhYUNGRDJxYzloRFRLOGoKemh3Mk41cGNIMVpYZGZBRjNNUWo1VmErSElDRElaL3BtTmNkVlJnWWxWN0hkOWc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + key: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRQzNOOWp2aWNtS3BHZDEKUDNwWGVBK01vaWRkTmpKNXZNMTNLcWFUYzEyOW1jbUhIdElyakduaG9Mck5TTFdjTEdLTkJic0JOaTVsb3E0MQpzSm9neW1OeFVzeFFRRXJYbjVEaUVuRVFmMUJxK25TR3pJZEdtYm1KVldxSHQ0dFNJSGRDSUVheEhESFdrSW9rCmxSNHQ4Q2dOSXZoS3FsR0dKbHZMZlBWWmdXSGpzOUhBKzYrRzM1dHAvWmdBdlNBL051dGs1UDlBTE9qbHlzaXkKU2lYNm1hUlBrK3lyTmZwcXpBOWNsSWVWUVFDVFNHSFJQZU94ZzFTU3FwSGhNdWt1WTAxSkh3b3RCVVFsTkt1RApXQnd6MTNGT3VhUGM3NGcwcHNOUVdlQ0lpN0laNmNQWldKZmJDa1JIQjBlRnBhT0djbnlGRmFmQWZOWVoxd1o4CjdINlUzVTR6d3IwSUx4WXo2RG44QjRmSWtrb1kxOVBIRW1uNHRySG01d2JSbkpWUGllZmZBWnpxSy96Y2FpQkYKVkRkR1FDL1R5M0s1ejkrVkZiSXpQV0lSNVM2d2VXdGJBOGgzYWEvRS90SFNDWVd2aSs0UndxUHhmV1E2SmV2eApkV0MwOFJneTFJUHo3dnFrdkQwYmc3UmYwMXZJVW9oTzN2Ym9IN0p6Mkswb3ZFR2lSZGNQUWZCeHkvUjZPNGVzCnRQcFRMRTlDU1NrY1RBUWNpZkNwbjNPVTgvdnVSTERFeTlBdCttYWQrRzVWS2lTbm84RDV5Z2xqT0hFUUlDWk8KMGNFTkY1dVZjck5OaFFZUzBKZDdGOWVWQ1NPOEhVQ3NsTXFGMmVkbkZDcFNmcllJUWtzUlRnZWo0YlhVeGxURgozdmZqRVpuNWlkVnNJZ2oydFZRb04wZHJuOE1BU1FJREFRQUJBb0lDQUJKaUttUm9neDRqM2xTYm5Lc3Jtd1hOCm5GMEVLOTdlcEpBTktiOFlQNExmYkNMZ1l3Nm5EVldzQXFwSDNoOFFMZ2cvMTdKb3JSR2FGOWcvd3N0QSsyYmEKdTdEZXJwUEJpVEJCMFBIcWtGZFhqM3NhQ1FXNnRXelQ4dmN3b2F4SklTWXpwbHd0ZTh1dlg0a0pwRWhRTlRpUwpObThKZFZvY1BiQW1kdGkyL0dzME52cmgxZ3dXb2htcHJnZCs4bjRkUk5Pd0RYTnpQaUFXYjNwQ0tkcmg4U1JoCjc0aURSei9SZjBZWENoNmQ4ZENWWGVrNGlFRGVzRXp5QythWWJPQ3dhb2dJY3dVdTV0WkQyV1M1b2NUSzNHM2QKZnhWVFBHdXFBdVZzU3pUd0xWdmZ3bnlyb0xzRDVmTnBoZEhoVzQzSkxYak9BakcwWk9nZFZPT1NlQ1g0S1prbwptcWc4b3Y1TksxclVRVGQwNng2bmg0elBXdEdaTDIwbE9EMTZvRWgzUlZoRFU5akQ1U25aZ2M1Mzg2bVkxeTVJClV0QTBUUnh3MzNIcjRWT1ExaXVCZzlrNTU2MzFIcGl0clBWZ1QvLzVzYzdjMjhpQ2lBRnVFZGg3SDF5cG5NNkgKc1pjL2prRTJBOFF1NnpKSTV2NzRoYkFaTmxONVMrcDU4ajhrV2pPYTd4bnZwYk5saXc1a2JDK2Ezb25ZSVNHZApTNVZITzVEVkVaOEY3aUtUTS8zTEFZdDZScG0vdEZJOUhFZVRGWHVCVEVsYTlsb0srUWdXbjF1QVVMeGtKUHFyCkFXZ0tzL0FYYWpxVyt0d3ZUM2M5cUFDaGFTakhjV3lxem05WGh6RDRwNTg2cnpDZ3M5VUNSSStudlEvOGFIMWoKNm9CdkRqbUxpem9WUEVkR2k1VkJBb0lCQVFEM2pRZThEdVIxVjYveS9HcXRNRVcyVXptdTl2d1R4VXRBSFZtawpob25PbFo0MDVEL1B3b0s1dXBORjV2QWtxNDN1b1M2OXVuQWxxbGpraVNmOTEzU3pYZEE4dXRRYlQzVFczUmxWCkZ2dXZlN3YvcWtRZFdScm5rdXJhcWtFbnhUMnlKOGdlaG1Qcmo1STMwVHVRVXpSdmFRc2hyYkIwV3NCcGcrRmIKdWJnV29wU21hVTY5aEJpSGxwWFYrcjJRUXIrVllHT3JLUkNSWDRhMGxtbEJxbDdnemVZSTA2d2RpamszelF5cgorcVltYjRkdEFqd3huQ09CRG9qbVJBM2hGTmpVbC8wNlVvMmZzUEM1cjduWlA2cURUMUU2MU5tVDhPZ3kyUWE1Cm90Uk4wS1E3bThGRXAwUDA4aHByOTRxVlZLaHB2NzMzcGMwQkhCQXZ6VG9RdTdKcEFvSUJBUUM5ZUxZZzVSS3cKMDZQSEVmRlhMTnZ1NU12Q2I0T2NHY1BHUElLaHEyWExTbFJSSElVSkdueFB2RVRrcm93YXhDVGVVc2g0WUFtUApZUjZxKzE2aHRwN1JBZ1RWNkxvZUpnQ2hDNVRvTWlkZkR2MmxEUnZneVpMWWtsU0VIcEpaSXRWWTI4NzFWTkRaClhFQWwwOGFGcHlENDNseXdNc3UxaHYzSnRMVGJVTDNZdGtBZnBQVFJBZ0ZaaFlxbVJUdTJKeXN5dXVoWWFVbS8KeEw3WDcvYmlJZ2FPemR1YkF0QXBFTUlEbnFOdVdKOUVBQit4a1c5VUIyTFpRZjBuOTh2bG40aUowaDhsb1V5RAphWElPbWpDZFJXeGFzeVRRQkNEZUR0eXgxbHNvb1R1U2JWU1FFSHVUeUgzVno2UHZBZC9xNGxwRW5hY0UvMjE5CjRXUEh6NnArcDJMaEFvSUJBQ28yQXhhZkYzZW16eHJJemN2Z1NsTFBtQ3RzZEFsUEFBamJ1RmhrbElVRVlDaTIKcnViWFRRRXNma1pTSGFxekVnMlpzR1dycjhuTVpVSDYzVFhja2txdmVYMlJnZTl5T2dNVlNtZUc5cjJ5aEprUQp5SEtVcWhESXJZRkJ2TUJ5VXBYWlVMZGJ4UmY2c0QwU1VXekhzMDQ0QkN6bStBcXZHdFlqSmI5RlNNMmJSV3VtCjAwVmZpK3M2MHl2Y2lJeGJ4VjFNUlZKL094TCt6ZkpuSDJXU0RvR1l1bHZROUMxSlQzNWpXWUROeVowT01YSjIKQ2h1UGUwSmJYeDZjaGgxV042N3doNzUxS3k4S3RkR0QxRlhtRkVZMXRTMHA5RHZVdlZOR1RHNUZCSnlNTWlUego1eDIwdzlLMW9hbTlXUVVqbldBQzBQcTBhK04vakljS0lKZVAyZGtDZ2dFQVhPZzhKcFV0UFJnS1R5czFOSklDCnBubjZrRFV1Uy9VMlVwYUpWODA3OVJ0VmpSQjNDNmU1SFVBc2FCWlBEVER4QXpPRXFjSXQ3ZWlwcVIzcG9WSnoKUGZuSGRUelJSc2RMdDZ4K0wvMm40S3p4STJYeUxaK3FLaGhXNlJJMG9SQzduUDdyMU5EcU9DdE1LVUJYTUdKcgpnSjFJeGYyaWRqamphV3o2NGpBTlo1NjJnczNZWGtTbGRNaE8zSWxHWm1OK2d6bXpoT2JjQ3ZUbXYrd2pHMitqCjE1S0tCTkMwVWU2dHRDaXQ2d1g1MHRaY3RDMmtjWWZOcU1yNjRBWmFMUmExVlI5N3RuQUpuTWF2N3drY25ZSFYKU0FSZ0lNQmxmWDI4S2xmNkMwcEVjK0M0Zm93V2pMamJPMlM5OWd6dFI3Z0dtMjdTMzFpQTBDRWRWSFU0SFRMbgpBUUtDQVFFQXNzajBmRThqa0ZpdnpRMmxTZTBEeGhwUXFHZVF1UGROYkJKVnNBcVdmRXRKQ0h2R0JYaTZBeEIrClFnN015RE14dnVPYXQ1TVNUQ01GYzNYdVFUdEtxdlF3SGxXMXZpTnJxckNzRHVRNTVDa1ZQTUxmazk4VlFoeHkKMnpUd20zOUd5a1ZpLy9CaU5LQzRCU2ZtZlN6cGdiYlJnSEI2Ny9zcGIwejBMbXUrWG5uL0ROemxxS1pvQUZFQgpwcDdzNkVmWGdJN1Npbm94dGxuRHM4eDdFM2dlcEtENVVWbnQzM3FZbUhCOVZ3WHpUZDBaSkhrY0x1b1VpanJjCko2cENYVTcrRlpPd3pJQi9IcFFPZ2pwdklqQ0pJaHRGeFZ5Z2JqdXVjRThRS2Naaml5VXNGTHZkQzVkZTFNZVQKMXJKalFFc2laeEgrUVBSODh0dUJ5VVZHMDAwbHBBPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=" + } + want_result: + - x: "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" diff --git a/topdown/crypto.go b/topdown/crypto.go index b9b3816af2..5c4cf1b973 100644 --- a/topdown/crypto.go +++ b/topdown/crypto.go @@ -11,6 +11,7 @@ import ( "crypto/sha1" "crypto/sha256" "crypto/sha512" + "crypto/tls" "crypto/x509" "encoding/base64" "encoding/json" @@ -96,6 +97,29 @@ func builtinCryptoX509ParseAndVerifyCertificates(_ BuiltinContext, operands []*a return iter(valid) } +func builtinCryptoX509ParseKeyPair(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { + certificate, err := builtins.StringOperand(operands[0].Value, 1) + if err != nil { + return err + } + + key, err := builtins.StringOperand(operands[1].Value, 1) + if err != nil { + return err + } + + certs, err := getTLSx509KeyPairFromString([]byte(certificate), []byte(key)) + if err != nil { + return err + } + v, err := ast.InterfaceToValue(certs) + if err != nil { + return err + } + + return iter(ast.NewTerm(v)) +} + func builtinCryptoX509ParseCertificateRequest(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { input, err := builtins.StringOperand(operands[0].Value, 1) if err != nil { @@ -275,6 +299,7 @@ func init() { RegisterBuiltinFunc(ast.CryptoSha256.Name, builtinCryptoSha256) RegisterBuiltinFunc(ast.CryptoX509ParseCertificateRequest.Name, builtinCryptoX509ParseCertificateRequest) RegisterBuiltinFunc(ast.CryptoX509ParseRSAPrivateKey.Name, builtinCryptoX509ParseRSAPrivateKey) + RegisterBuiltinFunc(ast.CryptoX509ParseKeyPair.Name, builtinCryptoX509ParseKeyPair) RegisterBuiltinFunc(ast.CryptoHmacMd5.Name, builtinCryptoHmacMd5) RegisterBuiltinFunc(ast.CryptoHmacSha1.Name, builtinCryptoHmacSha1) RegisterBuiltinFunc(ast.CryptoHmacSha256.Name, builtinCryptoHmacSha256) @@ -447,6 +472,60 @@ func readCertFromFile(localCertFile string) ([]byte, error) { return certPEM, nil } +func getTLSx509KeyPairFromString(certPemBlock []byte, keyPemBlock []byte) (*tls.Certificate, error) { + + if !strings.HasPrefix(string(certPemBlock), "-----BEGIN") { + s, err := base64.StdEncoding.DecodeString(string(certPemBlock)) + if err != nil { + return nil, err + } + certPemBlock = s + } + + if !strings.HasPrefix(string(keyPemBlock), "-----BEGIN") { + s, err := base64.StdEncoding.DecodeString(string(keyPemBlock)) + if err != nil { + return nil, err + } + keyPemBlock = s + } + + // we assume it a DER certificate and try to convert it to a PEM. + if !bytes.HasPrefix(certPemBlock, []byte("-----BEGIN")) { + + pemBlock := &pem.Block{ + Type: "CERTIFICATE", + Bytes: certPemBlock, + } + + var buf bytes.Buffer + if err := pem.Encode(&buf, pemBlock); err != nil { + return nil, err + } + certPemBlock = buf.Bytes() + + } + // we assume it a DER key and try to convert it to a PEM. + if !bytes.HasPrefix(keyPemBlock, []byte("-----BEGIN")) { + pemBlock := &pem.Block{ + Type: "PRIVATE KEY", + Bytes: keyPemBlock, + } + var buf bytes.Buffer + if err := pem.Encode(&buf, pemBlock); err != nil { + return nil, err + } + keyPemBlock = buf.Bytes() + } + + cert, err := tls.X509KeyPair(certPemBlock, keyPemBlock) + if err != nil { + return nil, err + } + + return &cert, nil +} + // ReadKeyFromFile reads a key from file func readKeyFromFile(localKeyFile string) ([]byte, error) { // Read in the cert file diff --git a/topdown/crypto_test.go b/topdown/crypto_test.go index d2b7cbb9c9..bdfa49048e 100644 --- a/topdown/crypto_test.go +++ b/topdown/crypto_test.go @@ -205,3 +205,263 @@ qPYXB5U6tdTrexzaYBKr4gQ= }) } + +func Test_parsex509KeyPair(t *testing.T) { + certPemEC := []byte(`-----BEGIN CERTIFICATE----- +MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d +7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B +5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr +BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 +NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l +Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc +6MF9+Yw1Yy0t +-----END CERTIFICATE-----`) + keyPemEC := []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 +AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q +EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== +-----END EC PRIVATE KEY-----`) + + certPemx509 := []byte(`-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIUdRHA+B0/ZgknKPlB2fswE98lzAcwDQYJKoZIhvcNAQEL +BQAwgYYxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlTdGF0ZU5hbWUxETAPBgNVBAcM +CENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFtZTEbMBkGA1UECwwSQ29tcGFu +eVNlY3Rpb25OYW1lMR0wGwYDVQQDDBRDb21tb25OYW1lT3JIb3N0bmFtZTAeFw0y +MzA1MTAxMjUxMjhaFw0zMzA1MDcxMjUxMjhaMIGGMQswCQYDVQQGEwJYWDESMBAG +A1UECAwJU3RhdGVOYW1lMREwDwYDVQQHDAhDaXR5TmFtZTEUMBIGA1UECgwLQ29t +cGFueU5hbWUxGzAZBgNVBAsMEkNvbXBhbnlTZWN0aW9uTmFtZTEdMBsGA1UEAwwU +Q29tbW9uTmFtZU9ySG9zdG5hbWUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQC3N9jvicmKpGd1P3pXeA+MoiddNjJ5vM13KqaTc129mcmHHtIrjGnhoLrN +SLWcLGKNBbsBNi5loq41sJogymNxUsxQQErXn5DiEnEQf1Bq+nSGzIdGmbmJVWqH +t4tSIHdCIEaxHDHWkIoklR4t8CgNIvhKqlGGJlvLfPVZgWHjs9HA+6+G35tp/ZgA +vSA/Nutk5P9ALOjlysiySiX6maRPk+yrNfpqzA9clIeVQQCTSGHRPeOxg1SSqpHh +MukuY01JHwotBUQlNKuDWBwz13FOuaPc74g0psNQWeCIi7IZ6cPZWJfbCkRHB0eF +paOGcnyFFafAfNYZ1wZ87H6U3U4zwr0ILxYz6Dn8B4fIkkoY19PHEmn4trHm5wbR +nJVPieffAZzqK/zcaiBFVDdGQC/Ty3K5z9+VFbIzPWIR5S6weWtbA8h3aa/E/tHS +CYWvi+4RwqPxfWQ6JevxdWC08Rgy1IPz7vqkvD0bg7Rf01vIUohO3vboH7Jz2K0o +vEGiRdcPQfBxy/R6O4estPpTLE9CSSkcTAQcifCpn3OU8/vuRLDEy9At+mad+G5V +KiSno8D5ygljOHEQICZO0cENF5uVcrNNhQYS0Jd7F9eVCSO8HUCslMqF2ednFCpS +frYIQksRTgej4bXUxlTF3vfjEZn5idVsIgj2tVQoN0drn8MASQIDAQABo1MwUTAd +BgNVHQ4EFgQUlDXyP2Hr+VQM1aHlzcN9bDlMbJswHwYDVR0jBBgwFoAUlDXyP2Hr ++VQM1aHlzcN9bDlMbJswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC +AgEACzGrfXVYhfCmtFZN0Y6NKQ7g1HVGIX5V3Al4U+oo3y+9n4KVGkgV9jh/dZ8k +mzWmpXOGRfD1ufRcD9qoXy+GHRw/0bm2wkVcMvEsnMx+DkuhiVOIc0PYDNj87uK3 +vNFBM39uo1fiJ9yd9SKQsjB94lVMaF1089wevPYl5qmboku2qurX3uw5VvysHAAw +U2y0x8y/c3jw9MfK1X0GYhScZ0pV3y3xtlqrHnNjSRaZ3pfPl74ac0bgtE9q8Jt5 +o3D0gfZi08RkunnkgJ1/Pd5iaH/XGgTnz5wSEAzTRBXHKYYoFpFWL0rz0kJojfCw +Rut6Omn/L6nQW/R5zwsqvkADuo/KXY2N69/RxPw0z8Eq6YMTt8pW8e5dzRFQTKcv +KTt2B50uTUDRPQmovvF3FdjrYZbHrFXGQr2hezl56BDRJBZO8HCH44B1swz+t2If +ouv2PHd05WvCTr/3GE/fbTjZlUVx8Za2TYwVjHSS9w9kQCUvw3W3nNuQzNIGTbsa +DvT3ySt22dD40MYk4zNsz8wV0QV0vbyzz+1FTIreVWIIxi0uoygMhuFL7Izn1xsA +T8Mellt37m03evBLpQwOXqt7RWZSZ2YruT6rZdgdA9te+f7ULaaCFD2qc9hDTK8j +zhw2N5pcH1ZXdfAF3MQj5Va+HICDIZ/pmNcdVRgYlV7Hd9g= +-----END CERTIFICATE----- +`) + + certPemRSA := []byte(`-----BEGIN PRIVATE KEY----- +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 +1rJjQEsiZxH+QPR88tuByUVG000lpA== +-----END PRIVATE KEY----- +`) + + certDERx509 := []byte(`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 +`) + certDERRSA := []byte(`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 +`) + + certPemRSACrtB64 := []byte(`LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUY3ekNDQTllZ0F3SUJBZ0lVZFJIQStCMC9aZ2tuS1BsQjJmc3dFOThsekFjd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2dZWXhDekFKQmdOVkJBWVRBbGhZTVJJd0VBWURWUVFJREFsVGRHRjBaVTVoYldVeEVUQVBCZ05WQkFjTQpDRU5wZEhsT1lXMWxNUlF3RWdZRFZRUUtEQXREYjIxd1lXNTVUbUZ0WlRFYk1Ca0dBMVVFQ3d3U1EyOXRjR0Z1CmVWTmxZM1JwYjI1T1lXMWxNUjB3R3dZRFZRUUREQlJEYjIxdGIyNU9ZVzFsVDNKSWIzTjBibUZ0WlRBZUZ3MHkKTXpBMU1UQXhNalV4TWpoYUZ3MHpNekExTURjeE1qVXhNamhhTUlHR01Rc3dDUVlEVlFRR0V3SllXREVTTUJBRwpBMVVFQ0F3SlUzUmhkR1ZPWVcxbE1SRXdEd1lEVlFRSERBaERhWFI1VG1GdFpURVVNQklHQTFVRUNnd0xRMjl0CmNHRnVlVTVoYldVeEd6QVpCZ05WQkFzTUVrTnZiWEJoYm5sVFpXTjBhVzl1VG1GdFpURWRNQnNHQTFVRUF3d1UKUTI5dGJXOXVUbUZ0WlU5eVNHOXpkRzVoYldVd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJSwpBb0lDQVFDM045anZpY21LcEdkMVAzcFhlQStNb2lkZE5qSjV2TTEzS3FhVGMxMjltY21ISHRJcmpHbmhvTHJOClNMV2NMR0tOQmJzQk5pNWxvcTQxc0pvZ3ltTnhVc3hRUUVyWG41RGlFbkVRZjFCcStuU0d6SWRHbWJtSlZXcUgKdDR0U0lIZENJRWF4SERIV2tJb2tsUjR0OENnTkl2aEtxbEdHSmx2TGZQVlpnV0hqczlIQSs2K0czNXRwL1pnQQp2U0EvTnV0azVQOUFMT2pseXNpeVNpWDZtYVJQayt5ck5mcHF6QTljbEllVlFRQ1RTR0hSUGVPeGcxU1NxcEhoCk11a3VZMDFKSHdvdEJVUWxOS3VEV0J3ejEzRk91YVBjNzRnMHBzTlFXZUNJaTdJWjZjUFpXSmZiQ2tSSEIwZUYKcGFPR2NueUZGYWZBZk5ZWjF3Wjg3SDZVM1U0endyMElMeFl6NkRuOEI0Zklra29ZMTlQSEVtbjR0ckhtNXdiUgpuSlZQaWVmZkFaenFLL3pjYWlCRlZEZEdRQy9UeTNLNXo5K1ZGYkl6UFdJUjVTNndlV3RiQThoM2FhL0UvdEhTCkNZV3ZpKzRSd3FQeGZXUTZKZXZ4ZFdDMDhSZ3kxSVB6N3Zxa3ZEMGJnN1JmMDF2SVVvaE8zdmJvSDdKejJLMG8KdkVHaVJkY1BRZkJ4eS9SNk80ZXN0UHBUTEU5Q1NTa2NUQVFjaWZDcG4zT1U4L3Z1UkxERXk5QXQrbWFkK0c1VgpLaVNubzhENXlnbGpPSEVRSUNaTzBjRU5GNXVWY3JOTmhRWVMwSmQ3RjllVkNTTzhIVUNzbE1xRjJlZG5GQ3BTCmZyWUlRa3NSVGdlajRiWFV4bFRGM3ZmakVabjVpZFZzSWdqMnRWUW9OMGRybjhNQVNRSURBUUFCbzFNd1VUQWQKQmdOVkhRNEVGZ1FVbERYeVAySHIrVlFNMWFIbHpjTjliRGxNYkpzd0h3WURWUjBqQkJnd0ZvQVVsRFh5UDJIcgorVlFNMWFIbHpjTjliRGxNYkpzd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DCkFnRUFDekdyZlhWWWhmQ210RlpOMFk2TktRN2cxSFZHSVg1VjNBbDRVK29vM3krOW40S1ZHa2dWOWpoL2RaOGsKbXpXbXBYT0dSZkQxdWZSY0Q5cW9YeStHSFJ3LzBibTJ3a1ZjTXZFc25NeCtEa3VoaVZPSWMwUFlETmo4N3VLMwp2TkZCTTM5dW8xZmlKOXlkOVNLUXNqQjk0bFZNYUYxMDg5d2V2UFlsNXFtYm9rdTJxdXJYM3V3NVZ2eXNIQUF3ClUyeTB4OHkvYzNqdzlNZksxWDBHWWhTY1owcFYzeTN4dGxxckhuTmpTUmFaM3BmUGw3NGFjMGJndEU5cThKdDUKbzNEMGdmWmkwOFJrdW5ua2dKMS9QZDVpYUgvWEdnVG56NXdTRUF6VFJCWEhLWVlvRnBGV0wwcnowa0pvamZDdwpSdXQ2T21uL0w2blFXL1I1endzcXZrQUR1by9LWFkyTjY5L1J4UHcwejhFcTZZTVR0OHBXOGU1ZHpSRlFUS2N2CktUdDJCNTB1VFVEUlBRbW92dkYzRmRqcllaYkhyRlhHUXIyaGV6bDU2QkRSSkJaTzhIQ0g0NEIxc3d6K3QySWYKb3V2MlBIZDA1V3ZDVHIvM0dFL2ZiVGpabFVWeDhaYTJUWXdWakhTUzl3OWtRQ1V2dzNXM25OdVF6TklHVGJzYQpEdlQzeVN0MjJkRDQwTVlrNHpOc3o4d1YwUVYwdmJ5enorMUZUSXJlVldJSXhpMHVveWdNaHVGTDdJem4xeHNBClQ4TWVsbHQzN20wM2V2QkxwUXdPWHF0N1JXWlNaMllydVQ2clpkZ2RBOXRlK2Y3VUxhYUNGRDJxYzloRFRLOGoKemh3Mk41cGNIMVpYZGZBRjNNUWo1VmErSElDRElaL3BtTmNkVlJnWWxWN0hkOWc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K`) + certPemRSAKeyB64 := []byte(`LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRQzNOOWp2aWNtS3BHZDEKUDNwWGVBK01vaWRkTmpKNXZNMTNLcWFUYzEyOW1jbUhIdElyakduaG9Mck5TTFdjTEdLTkJic0JOaTVsb3E0MQpzSm9neW1OeFVzeFFRRXJYbjVEaUVuRVFmMUJxK25TR3pJZEdtYm1KVldxSHQ0dFNJSGRDSUVheEhESFdrSW9rCmxSNHQ4Q2dOSXZoS3FsR0dKbHZMZlBWWmdXSGpzOUhBKzYrRzM1dHAvWmdBdlNBL051dGs1UDlBTE9qbHlzaXkKU2lYNm1hUlBrK3lyTmZwcXpBOWNsSWVWUVFDVFNHSFJQZU94ZzFTU3FwSGhNdWt1WTAxSkh3b3RCVVFsTkt1RApXQnd6MTNGT3VhUGM3NGcwcHNOUVdlQ0lpN0laNmNQWldKZmJDa1JIQjBlRnBhT0djbnlGRmFmQWZOWVoxd1o4CjdINlUzVTR6d3IwSUx4WXo2RG44QjRmSWtrb1kxOVBIRW1uNHRySG01d2JSbkpWUGllZmZBWnpxSy96Y2FpQkYKVkRkR1FDL1R5M0s1ejkrVkZiSXpQV0lSNVM2d2VXdGJBOGgzYWEvRS90SFNDWVd2aSs0UndxUHhmV1E2SmV2eApkV0MwOFJneTFJUHo3dnFrdkQwYmc3UmYwMXZJVW9oTzN2Ym9IN0p6Mkswb3ZFR2lSZGNQUWZCeHkvUjZPNGVzCnRQcFRMRTlDU1NrY1RBUWNpZkNwbjNPVTgvdnVSTERFeTlBdCttYWQrRzVWS2lTbm84RDV5Z2xqT0hFUUlDWk8KMGNFTkY1dVZjck5OaFFZUzBKZDdGOWVWQ1NPOEhVQ3NsTXFGMmVkbkZDcFNmcllJUWtzUlRnZWo0YlhVeGxURgozdmZqRVpuNWlkVnNJZ2oydFZRb04wZHJuOE1BU1FJREFRQUJBb0lDQUJKaUttUm9neDRqM2xTYm5Lc3Jtd1hOCm5GMEVLOTdlcEpBTktiOFlQNExmYkNMZ1l3Nm5EVldzQXFwSDNoOFFMZ2cvMTdKb3JSR2FGOWcvd3N0QSsyYmEKdTdEZXJwUEJpVEJCMFBIcWtGZFhqM3NhQ1FXNnRXelQ4dmN3b2F4SklTWXpwbHd0ZTh1dlg0a0pwRWhRTlRpUwpObThKZFZvY1BiQW1kdGkyL0dzME52cmgxZ3dXb2htcHJnZCs4bjRkUk5Pd0RYTnpQaUFXYjNwQ0tkcmg4U1JoCjc0aURSei9SZjBZWENoNmQ4ZENWWGVrNGlFRGVzRXp5QythWWJPQ3dhb2dJY3dVdTV0WkQyV1M1b2NUSzNHM2QKZnhWVFBHdXFBdVZzU3pUd0xWdmZ3bnlyb0xzRDVmTnBoZEhoVzQzSkxYak9BakcwWk9nZFZPT1NlQ1g0S1prbwptcWc4b3Y1TksxclVRVGQwNng2bmg0elBXdEdaTDIwbE9EMTZvRWgzUlZoRFU5akQ1U25aZ2M1Mzg2bVkxeTVJClV0QTBUUnh3MzNIcjRWT1ExaXVCZzlrNTU2MzFIcGl0clBWZ1QvLzVzYzdjMjhpQ2lBRnVFZGg3SDF5cG5NNkgKc1pjL2prRTJBOFF1NnpKSTV2NzRoYkFaTmxONVMrcDU4ajhrV2pPYTd4bnZwYk5saXc1a2JDK2Ezb25ZSVNHZApTNVZITzVEVkVaOEY3aUtUTS8zTEFZdDZScG0vdEZJOUhFZVRGWHVCVEVsYTlsb0srUWdXbjF1QVVMeGtKUHFyCkFXZ0tzL0FYYWpxVyt0d3ZUM2M5cUFDaGFTakhjV3lxem05WGh6RDRwNTg2cnpDZ3M5VUNSSStudlEvOGFIMWoKNm9CdkRqbUxpem9WUEVkR2k1VkJBb0lCQVFEM2pRZThEdVIxVjYveS9HcXRNRVcyVXptdTl2d1R4VXRBSFZtawpob25PbFo0MDVEL1B3b0s1dXBORjV2QWtxNDN1b1M2OXVuQWxxbGpraVNmOTEzU3pYZEE4dXRRYlQzVFczUmxWCkZ2dXZlN3YvcWtRZFdScm5rdXJhcWtFbnhUMnlKOGdlaG1Qcmo1STMwVHVRVXpSdmFRc2hyYkIwV3NCcGcrRmIKdWJnV29wU21hVTY5aEJpSGxwWFYrcjJRUXIrVllHT3JLUkNSWDRhMGxtbEJxbDdnemVZSTA2d2RpamszelF5cgorcVltYjRkdEFqd3huQ09CRG9qbVJBM2hGTmpVbC8wNlVvMmZzUEM1cjduWlA2cURUMUU2MU5tVDhPZ3kyUWE1Cm90Uk4wS1E3bThGRXAwUDA4aHByOTRxVlZLaHB2NzMzcGMwQkhCQXZ6VG9RdTdKcEFvSUJBUUM5ZUxZZzVSS3cKMDZQSEVmRlhMTnZ1NU12Q2I0T2NHY1BHUElLaHEyWExTbFJSSElVSkdueFB2RVRrcm93YXhDVGVVc2g0WUFtUApZUjZxKzE2aHRwN1JBZ1RWNkxvZUpnQ2hDNVRvTWlkZkR2MmxEUnZneVpMWWtsU0VIcEpaSXRWWTI4NzFWTkRaClhFQWwwOGFGcHlENDNseXdNc3UxaHYzSnRMVGJVTDNZdGtBZnBQVFJBZ0ZaaFlxbVJUdTJKeXN5dXVoWWFVbS8KeEw3WDcvYmlJZ2FPemR1YkF0QXBFTUlEbnFOdVdKOUVBQit4a1c5VUIyTFpRZjBuOTh2bG40aUowaDhsb1V5RAphWElPbWpDZFJXeGFzeVRRQkNEZUR0eXgxbHNvb1R1U2JWU1FFSHVUeUgzVno2UHZBZC9xNGxwRW5hY0UvMjE5CjRXUEh6NnArcDJMaEFvSUJBQ28yQXhhZkYzZW16eHJJemN2Z1NsTFBtQ3RzZEFsUEFBamJ1RmhrbElVRVlDaTIKcnViWFRRRXNma1pTSGFxekVnMlpzR1dycjhuTVpVSDYzVFhja2txdmVYMlJnZTl5T2dNVlNtZUc5cjJ5aEprUQp5SEtVcWhESXJZRkJ2TUJ5VXBYWlVMZGJ4UmY2c0QwU1VXekhzMDQ0QkN6bStBcXZHdFlqSmI5RlNNMmJSV3VtCjAwVmZpK3M2MHl2Y2lJeGJ4VjFNUlZKL094TCt6ZkpuSDJXU0RvR1l1bHZROUMxSlQzNWpXWUROeVowT01YSjIKQ2h1UGUwSmJYeDZjaGgxV042N3doNzUxS3k4S3RkR0QxRlhtRkVZMXRTMHA5RHZVdlZOR1RHNUZCSnlNTWlUego1eDIwdzlLMW9hbTlXUVVqbldBQzBQcTBhK04vakljS0lKZVAyZGtDZ2dFQVhPZzhKcFV0UFJnS1R5czFOSklDCnBubjZrRFV1Uy9VMlVwYUpWODA3OVJ0VmpSQjNDNmU1SFVBc2FCWlBEVER4QXpPRXFjSXQ3ZWlwcVIzcG9WSnoKUGZuSGRUelJSc2RMdDZ4K0wvMm40S3p4STJYeUxaK3FLaGhXNlJJMG9SQzduUDdyMU5EcU9DdE1LVUJYTUdKcgpnSjFJeGYyaWRqamphV3o2NGpBTlo1NjJnczNZWGtTbGRNaE8zSWxHWm1OK2d6bXpoT2JjQ3ZUbXYrd2pHMitqCjE1S0tCTkMwVWU2dHRDaXQ2d1g1MHRaY3RDMmtjWWZOcU1yNjRBWmFMUmExVlI5N3RuQUpuTWF2N3drY25ZSFYKU0FSZ0lNQmxmWDI4S2xmNkMwcEVjK0M0Zm93V2pMamJPMlM5OWd6dFI3Z0dtMjdTMzFpQTBDRWRWSFU0SFRMbgpBUUtDQVFFQXNzajBmRThqa0ZpdnpRMmxTZTBEeGhwUXFHZVF1UGROYkJKVnNBcVdmRXRKQ0h2R0JYaTZBeEIrClFnN015RE14dnVPYXQ1TVNUQ01GYzNYdVFUdEtxdlF3SGxXMXZpTnJxckNzRHVRNTVDa1ZQTUxmazk4VlFoeHkKMnpUd20zOUd5a1ZpLy9CaU5LQzRCU2ZtZlN6cGdiYlJnSEI2Ny9zcGIwejBMbXUrWG5uL0ROemxxS1pvQUZFQgpwcDdzNkVmWGdJN1Npbm94dGxuRHM4eDdFM2dlcEtENVVWbnQzM3FZbUhCOVZ3WHpUZDBaSkhrY0x1b1VpanJjCko2cENYVTcrRlpPd3pJQi9IcFFPZ2pwdklqQ0pJaHRGeFZ5Z2JqdXVjRThRS2Naaml5VXNGTHZkQzVkZTFNZVQKMXJKalFFc2laeEgrUVBSODh0dUJ5VVZHMDAwbHBBPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=`) + + t.Run("ParseX509KeyPairEC", func(t *testing.T) { + validKeyPairEc, err := getTLSx509KeyPairFromString(certPemEC, keyPemEC) + if err != nil { + t.Fatal("failed to parse x509 key pair") + } + if validKeyPairEc == nil { + t.Fatal("expected certificate but got nil") + } + + }) + + t.Run("ParseX509KeyPairRSA", func(t *testing.T) { + validCertPair, err := getTLSx509KeyPairFromString(certPemx509, certPemRSA) + if err != nil { + t.Fatal("failed to parse x509 Pair with RSAkey") + } + if validCertPair == nil { + t.Fatal("expected certificate but got nil") + } + + }) + + t.Run("ParseX509KeyPairRSABase64", func(t *testing.T) { + validCertPair, err := getTLSx509KeyPairFromString(certPemRSACrtB64, certPemRSAKeyB64) + if err != nil { + t.Fatal("failed to parse x509 Pair with RSAkey") + } + if validCertPair == nil { + t.Fatal("expected certificate but got nil") + } + + }) + + t.Run("ParseX509KeyPairDERx509", func(t *testing.T) { + validCertPair, err := getTLSx509KeyPairFromString(certDERx509, certDERRSA) + if err != nil { + t.Fatal("failed to parse x509 Pair with RSAkey", err) + } + if validCertPair == nil { + t.Fatal("expected certificate but got nil") + } + }) + + t.Run("ParseX509KeyPairPEMstringB64Key", func(t *testing.T) { + validCertPair, err := getTLSx509KeyPairFromString(certPemx509, certPemRSAKeyB64) + if err != nil { + t.Fatal("failed to parse x509 Pair with RSAkey") + } + if validCertPair == nil { + t.Fatal("expected certificate but got nil") + } + + }) + + t.Run("ParseX509KeyPairB64CRTBPEMKey", func(t *testing.T) { + validCertPair, err := getTLSx509KeyPairFromString(certPemRSACrtB64, certPemRSA) + if err != nil { + t.Fatal("failed to parse x509 Pair with RSAkey") + } + if validCertPair == nil { + t.Fatal("expected certificate but got nil") + } + + }) + + t.Run("ParseX509KeyPairMisMatchedTypes", func(t *testing.T) { + certPair, err := getTLSx509KeyPairFromString(certPemEC, certPemRSA) + if err == nil { + t.Fatal("expected error but got nil") + } + if certPair != nil { + t.Fatalf("expected no certificate but got %v\n", certPair) + } + }) + +}