From 192d78d40551ec5d9aade5ca72dd6e33ad700a2b Mon Sep 17 00:00:00 2001 From: Anirudh Ramachandran Date: Sun, 3 Dec 2017 23:56:21 -0800 Subject: [PATCH] Add wrapper for getting X509_digest from a cert Summary: X509_digest, or the "fingerprint" of the cert, is useful to identify certificates with the same CN/SANs. This adds an API to get the SHA1 or SHA256 digest of a cert. Reviewed By: yfeldblum Differential Revision: D6457917 fbshipit-source-id: 148a5a2270e938b39065e00d7947c2fc57cd7f75 --- folly/ssl/OpenSSLCertUtils.cpp | 25 +++++++++++++++++++++++++ folly/ssl/OpenSSLCertUtils.h | 8 ++++++++ folly/ssl/test/OpenSSLCertUtilsTest.cpp | 15 +++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/folly/ssl/OpenSSLCertUtils.cpp b/folly/ssl/OpenSSLCertUtils.cpp index 9b9efa3e..ac7cd741 100644 --- a/folly/ssl/OpenSSLCertUtils.cpp +++ b/folly/ssl/OpenSSLCertUtils.cpp @@ -216,5 +216,30 @@ std::vector OpenSSLCertUtils::readCertsFromBuffer( return certs; } +std::array OpenSSLCertUtils::getDigestSha1( + X509& x509) { + unsigned int len; + std::array md; + int rc = X509_digest(&x509, EVP_sha1(), md.data(), &len); + + if (rc <= 0) { + throw std::runtime_error("Could not calculate SHA1 digest for cert"); + } + return md; +} + +std::array OpenSSLCertUtils::getDigestSha256( + X509& x509) { + unsigned int len; + std::array md; + int rc = X509_digest(&x509, EVP_sha256(), md.data(), &len); + + if (rc <= 0) { + throw std::runtime_error("Could not calculate SHA256 digest for cert"); + } + return md; +} + + } // namespace ssl } // namespace folly diff --git a/folly/ssl/OpenSSLCertUtils.h b/folly/ssl/OpenSSLCertUtils.h index 1f5f63d2..31273d02 100644 --- a/folly/ssl/OpenSSLCertUtils.h +++ b/folly/ssl/OpenSSLCertUtils.h @@ -82,6 +82,14 @@ class OpenSSLCertUtils { */ static std::vector readCertsFromBuffer(ByteRange); + /** + * Return the output of the X509_digest for chosen message-digest algo + * NOTE: The returned digest will be in binary, and may need to be + * hex-encoded + */ + static std::array getDigestSha1(X509& x509); + static std::array getDigestSha256(X509& x509); + private: static std::string getDateTimeStr(const ASN1_TIME* time); }; diff --git a/folly/ssl/test/OpenSSLCertUtilsTest.cpp b/folly/ssl/test/OpenSSLCertUtilsTest.cpp index 41af7dc1..ac747b33 100644 --- a/folly/ssl/test/OpenSSLCertUtilsTest.cpp +++ b/folly/ssl/test/OpenSSLCertUtilsTest.cpp @@ -258,3 +258,18 @@ TEST_F(OpenSSLCertUtilsTest, TestReadCertsFromBuffer) { EXPECT_EQ(*identity, folly::sformat("test cert {}", i.index + 1)); } } + +TEST_F(OpenSSLCertUtilsTest, TestX509Digest) { + auto x509 = readCertFromFile(kTestCertWithoutSan); + EXPECT_NE(x509, nullptr); + + auto sha1Digest = folly::ssl::OpenSSLCertUtils::getDigestSha1(*x509); + EXPECT_EQ( + folly::hexlify(folly::range(sha1Digest)), + "b84e951d6c4e6cc70346357fab43d7ed73a07b0f"); + + auto sha2Digest = folly::ssl::OpenSSLCertUtils::getDigestSha256(*x509); + EXPECT_EQ( + folly::hexlify(folly::range(sha2Digest)), + "364d3a6a0b10d0635ce59b40c0b7f505ab2cd9fd0a06661cdc61d9cb8c9c9821"); +} -- 2.34.1