33#include " source/common/common/assert.h"
44#include " source/common/crypto/crypto_impl.h"
55
6- #include " absl/container/fixed_array.h"
76#include " absl/strings/ascii.h"
87#include " absl/strings/str_cat.h"
8+ #include " absl/types/span.h"
9+ #include " openssl/pem.h"
910
1011namespace Envoy {
1112namespace Common {
@@ -25,7 +26,7 @@ std::vector<uint8_t> UtilityImpl::getSha256Digest(const Buffer::Instance& buffer
2526 return digest;
2627}
2728
28- std::vector<uint8_t > UtilityImpl::getSha256Hmac (const std::vector< uint8_t >& key,
29+ std::vector<uint8_t > UtilityImpl::getSha256Hmac (absl::Span< const uint8_t > key,
2930 absl::string_view message) {
3031 std::vector<uint8_t > hmac (SHA256_DIGEST_LENGTH);
3132 const auto ret =
@@ -35,46 +36,109 @@ std::vector<uint8_t> UtilityImpl::getSha256Hmac(const std::vector<uint8_t>& key,
3536 return hmac;
3637}
3738
38- const VerificationOutput UtilityImpl::verifySignature (absl::string_view hash, CryptoObject& key,
39- const std::vector<uint8_t >& signature,
40- const std::vector<uint8_t >& text) {
41- // Step 1: initialize EVP_MD_CTX
39+ absl::Status UtilityImpl::verifySignature (absl::string_view hash_function, PKeyObject& key,
40+ absl::Span<const uint8_t > signature,
41+ absl::Span<const uint8_t > text) {
4242 bssl::ScopedEVP_MD_CTX ctx;
4343
44- // Step 2: initialize EVP_MD
45- const EVP_MD* md = getHashFunction (hash);
44+ const EVP_MD* md = getHashFunction (hash_function);
4645
4746 if (md == nullptr ) {
48- return { false , absl::StrCat (hash , " is not supported." )} ;
47+ return absl::InvalidArgumentError ( absl:: StrCat (hash_function , " is not supported." )) ;
4948 }
50- // Step 3: initialize EVP_DigestVerify
51- auto pkey_wrapper = Common::Crypto::Access::getTyped<Common::Crypto::PublicKeyObject>(key);
52- EVP_PKEY* pkey = pkey_wrapper->getEVP_PKEY ();
49+ EVP_PKEY* pkey = key.getEVP_PKEY ();
5350
5451 if (pkey == nullptr ) {
55- return { false , " Failed to initialize digest verify." } ;
52+ return absl::InternalError ( " Failed to initialize digest verify." ) ;
5653 }
5754
5855 int ok = EVP_DigestVerifyInit (ctx.get (), nullptr , md, nullptr , pkey);
5956 if (!ok) {
60- return { false , " Failed to initialize digest verify." } ;
57+ return absl::InternalError ( " Failed to initialize digest verify." ) ;
6158 }
6259
63- // Step 4: verify signature
6460 ok = EVP_DigestVerify (ctx.get (), signature.data (), signature.size (), text.data (), text.size ());
6561
66- // Step 5: check result
6762 if (ok == 1 ) {
68- return { true , " " } ;
63+ return absl::OkStatus () ;
6964 }
7065
71- return { false , absl::StrCat (" Failed to verify digest. Error code: " , ok)} ;
66+ return absl::InternalError ( absl:: StrCat (" Failed to verify digest. Error code: " , ok)) ;
7267}
7368
74- CryptoObjectPtr UtilityImpl::importPublicKey (const std::vector<uint8_t >& key) {
69+ absl::StatusOr<std::vector<uint8_t >> UtilityImpl::sign (absl::string_view hash_function,
70+ PKeyObject& key,
71+ absl::Span<const uint8_t > text) {
72+ bssl::ScopedEVP_MD_CTX ctx;
73+
74+ const EVP_MD* md = getHashFunction (hash_function);
75+
76+ if (md == nullptr ) {
77+ return absl::InvalidArgumentError (absl::StrCat (hash_function, " is not supported." ));
78+ }
79+
80+ EVP_PKEY* pkey = key.getEVP_PKEY ();
81+
82+ if (pkey == nullptr ) {
83+ return absl::InternalError (" Invalid key type: private key required for signing operation." );
84+ }
85+
86+ int ok = EVP_DigestSignInit (ctx.get (), nullptr , md, nullptr , pkey);
87+ if (!ok) {
88+ return absl::InternalError (" Invalid private key: key data is corrupted or malformed." );
89+ }
90+
91+ size_t sig_len = 0 ;
92+ ok = EVP_DigestSign (ctx.get (), nullptr , &sig_len, text.data (), text.size ());
93+ if (!ok) {
94+ return absl::InternalError (" Failed to get signature length." );
95+ }
96+
97+ std::vector<uint8_t > signature (sig_len);
98+ ok = EVP_DigestSign (ctx.get (), signature.data (), &sig_len, text.data (), text.size ());
99+ if (!ok) {
100+ return absl::InternalError (" Failed to create signature." );
101+ }
102+
103+ RELEASE_ASSERT (signature.size () >= sig_len, " signature.size() >= sig_len" );
104+ signature.resize (sig_len);
105+ return signature;
106+ }
107+
108+ namespace {
109+ // Template helper for importing keys with different formats and types
110+ template <typename KeyObjectType, typename ParseFunction>
111+ PKeyObjectPtr importKeyPEM (absl::string_view key, ParseFunction parse_func) {
112+ // PEM format: Use PEM parsing which automatically handles both PKCS#1 and PKCS#8 formats
113+ bssl::UniquePtr<BIO> bio (BIO_new_mem_buf (key.data (), key.size ()));
114+ if (!bio) {
115+ return std::make_unique<KeyObjectType>(nullptr );
116+ }
117+ return std::make_unique<KeyObjectType>(parse_func (bio.get (), nullptr , nullptr , nullptr ));
118+ }
119+
120+ template <typename KeyObjectType, typename ParseFunction>
121+ PKeyObjectPtr importKeyDER (absl::Span<const uint8_t > key, ParseFunction parse_func) {
122+ // DER format: Use DER parsing
75123 CBS cbs ({key.data (), key.size ()});
124+ return std::make_unique<KeyObjectType>(parse_func (&cbs));
125+ }
126+ } // namespace
127+
128+ PKeyObjectPtr UtilityImpl::importPublicKeyPEM (absl::string_view key) {
129+ return importKeyPEM<PKeyObject>(key, PEM_read_bio_PUBKEY);
130+ }
131+
132+ PKeyObjectPtr UtilityImpl::importPublicKeyDER (absl::Span<const uint8_t > key) {
133+ return importKeyDER<PKeyObject>(key, EVP_parse_public_key);
134+ }
135+
136+ PKeyObjectPtr UtilityImpl::importPrivateKeyPEM (absl::string_view key) {
137+ return importKeyPEM<PKeyObject>(key, PEM_read_bio_PrivateKey);
138+ }
76139
77- return std::make_unique<PublicKeyObject>(EVP_parse_public_key (&cbs));
140+ PKeyObjectPtr UtilityImpl::importPrivateKeyDER (absl::Span<const uint8_t > key) {
141+ return importKeyDER<PKeyObject>(key, EVP_parse_private_key);
78142}
79143
80144const EVP_MD* UtilityImpl::getHashFunction (absl::string_view name) {
0 commit comments