From 20077fdb54dbc569f0fa687626646c1a5af17656 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Wed, 27 Sep 2017 22:41:26 +0200 Subject: [PATCH] crypt: add helper for fingerprinting certificates --- src/crypt/certificate.vala | 31 ++++++++++++++++++++++++++++++ test/mconn-crypt-vala-test.vala | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/crypt/certificate.vala b/src/crypt/certificate.vala index c4a2850..0930c89 100644 --- a/src/crypt/certificate.vala +++ b/src/crypt/certificate.vala @@ -146,5 +146,36 @@ namespace Mconn { export_to_file(cert_path, export_certificate(cert)); export_to_file(key_path, export_private_key(key)); } + + private GnuTLS.X509.Certificate cert_from_pem(uint8[] certificate_pem) { + var datum = GnuTLS.Datum() { data=certificate_pem, + size=certificate_pem.length }; + + var cert = GnuTLS.X509.Certificate.create(); + var res = cert.import(ref datum, GnuTLS.X509.CertificateFormat.PEM); + assert(res == GnuTLS.ErrorCode.SUCCESS); + return cert; + } + + /** + * fingerprint_certificate: + * Produce a SHA1 fingerprint of the certificate + * + * @param certificate_pem PEM encoded certificate + * @return SHA1 fingerprint as bytes + */ + public uint8[] fingerprint_certificate(uint8[] certificate_pem) { + var cert = cert_from_pem(certificate_pem); + + // TOOD: make digest configurable, for now assume it's SHA1 + var data = new uint8[20]; + size_t sz = data.length; + var res = cert.get_fingerprint(GnuTLS.DigestAlgorithm.SHA1, + data, ref sz); + assert(res == GnuTLS.ErrorCode.SUCCESS); + assert(sz == data.length); + + return data; + } } } \ No newline at end of file diff --git a/test/mconn-crypt-vala-test.vala b/test/mconn-crypt-vala-test.vala index 6c6d169..4b5a863 100644 --- a/test/mconn-crypt-vala-test.vala +++ b/test/mconn-crypt-vala-test.vala @@ -86,11 +86,45 @@ void test_custom_cn() { assert("CN=custom-cn" in subject); } +void test_fingerprint() { + var pem = """-----BEGIN CERTIFICATE----- +MIIC8jCCAdoCAQowDQYJKoZIhvcNAQEFBQAwPzERMA8GA1UEChMIbWNvbm5lY3Qx +ETAPBgNVBAsTCG1jb25uZWN0MRcwFQYDVQQDDA5tYWNpZWtAY29yc2FpcjAeFw0x +NzA5MjQxOTU3NDVaFw0yNzA5MjQxOTU3NDVaMD8xETAPBgNVBAoTCG1jb25uZWN0 +MREwDwYDVQQLEwhtY29ubmVjdDEXMBUGA1UEAwwObWFjaWVrQGNvcnNhaXIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBWMM09dCCGXjY1aZ261nCa8+q +3ejDOHf21+Mt6yJnoWjPGvTK21MbRFPkeQe62FJHF3q8iXe3sSEdFk/f56G8ZZ4t +Qw/ST//kxtf/CKHPuoZeAFgQpYEKE3GVUX5M3b8+4YSKSRXs3FE4D5awQVdstI31 +N53plyOLdJe5IeK1kESsT0UgVo2RTHCOByel9WB2zcalQVTl8UxGKJcgrSuXj2f2 +1SBxHupOX0Ej7vTr+gIBNBRbwbVdsafEW/gRngyCWIO30cPKoaUSkoCppXQ+6hYd +/aOt+6/bBOISGJdy6uyM74jqoEbEMdhUXHfPFNCelIABxUMez0SNrRmdag2VAgMB +AAEwDQYJKoZIhvcNAQEFBQADggEBAEnJ+IsjGvBmlWAg5vlmWUY0OVMJa8Gl9ept +HWLIjK16XARAOwIcePNfDPyITWaxT5YV+MZotm1m6HkY5rPCeOjV7nzHrHjTjZqO +sCmsSGcb9ZkEQfRNGTmFFthkcnfTU9mKh8oGc/a9r0DDgYcPSCgqERt2fgiBrt85 +85PVl16fCSObVwOu5u5TtrfWkHpEHbjBU9AX52+IOYg7RsM7I4OnH+5svhmWqAxW +/PXFBB3q2nX2XXqFRhqeN9eOlHBQ5EoZh8GUp7vJyxp5eAS9g2KVtCBwTDElQt4D +4hu+QuzzEmoWY9w1R+hblNu/37mWkzFFrLqYlkNU2vbKkuWMOTg= +-----END CERTIFICATE-----"""; + var expected = "eb2611a447085322b206fa61d4bc5869b4a55657"; + + var fingerprint = Crypt.fingerprint_certificate(pem.data); + // SHA1 + assert(fingerprint.length == 20); + + var sb = new StringBuilder.sized(20*2); + foreach(var b in fingerprint) { + sb.append_printf("%02x", b); + } + + assert(sb.str == expected); +} + public static void main(string[] args) { Test.init(ref args); Test.add_func("/mconn-crypt-vala/generated", test_generate); Test.add_func("/mconn-crypt-vala/load", test_generate_load); Test.add_func("/mconn-crypt-vala/verify-cn", test_custom_cn); + Test.add_func("/mconn-crypt-vala/fingerprint", test_fingerprint); Test.run(); } \ No newline at end of file