8 #include <boost/algorithm/hex.hpp>
9 #include <boost/scoped_array.hpp>
12 #include "logging/logging.h"
13 #include "openssl_compat.h"
14 #include "utilities/utils.h"
16 PublicKey::PublicKey(
const boost::filesystem::path &path) : value_(
Utils::readFile(path)) {
17 type_ = Crypto::IdentifyRSAKeyType(value_);
20 PublicKey::PublicKey(Json::Value uptane_json) {
21 if (!uptane_json[
"keytype"].isString()) {
22 type_ = KeyType::kUnknown;
25 if (!uptane_json[
"keyval"].isObject()) {
26 type_ = KeyType::kUnknown;
30 if (!uptane_json[
"keyval"][
"public"].isString()) {
31 type_ = KeyType::kUnknown;
35 std::string keytype = uptane_json[
"keytype"].asString();
36 std::string keyvalue = uptane_json[
"keyval"][
"public"].asString();
38 std::transform(keytype.begin(), keytype.end(), keytype.begin(), ::tolower);
41 if (keytype ==
"ed25519") {
42 type = KeyType::kED25519;
43 }
else if (keytype ==
"rsa") {
44 type = Crypto::IdentifyRSAKeyType(keyvalue);
45 if (type == KeyType::kUnknown) {
46 LOG_WARNING <<
"Couldn't identify length of RSA key";
49 type = KeyType::kUnknown;
55 PublicKey::PublicKey(
const std::string &value, KeyType type) : value_(value), type_(type) {
56 if (Crypto::IsRsaKeyType(type)) {
57 if (type != Crypto::IdentifyRSAKeyType(value)) {
58 std::logic_error(
"RSA key length is incorrect");
65 case KeyType::kED25519:
66 return Crypto::ED25519Verify(boost::algorithm::unhex(value_), Utils::fromBase64(signature), message);
67 case KeyType::kRSA2048:
68 case KeyType::kRSA3072:
69 case KeyType::kRSA4096:
70 return Crypto::RSAPSSVerify(value_, Utils::fromBase64(signature), message);
76 bool PublicKey::operator==(
const PublicKey &rhs)
const {
return value_ == rhs.value_ && type_ == rhs.type_; }
80 case KeyType::kRSA2048:
81 case KeyType::kRSA3072:
82 case KeyType::kRSA4096:
83 res[
"keytype"] =
"RSA";
85 case KeyType::kED25519:
86 res[
"keytype"] =
"ED25519";
88 case KeyType::kUnknown:
89 res[
"keytype"] =
"unknown";
92 throw std::range_error(
"Unknown key type in PublicKey::ToUptane");
94 res[
"keyval"][
"public"] = value_;
98 std::string PublicKey::KeyId()
const {
99 std::string key_content = value_;
101 boost::algorithm::trim_right_if(key_content, boost::algorithm::is_any_of(
"\n"));
102 std::string keyid = boost::algorithm::hex(Crypto::sha256digest(Utils::jsonToCanonicalStr(Json::Value(key_content))));
103 std::transform(keyid.begin(), keyid.end(), keyid.begin(), ::tolower);
107 std::string Crypto::sha256digest(
const std::string &text) {
108 std::array<unsigned char, crypto_hash_sha256_BYTES> sha256_hash{};
109 crypto_hash_sha256(sha256_hash.data(),
reinterpret_cast<const unsigned char *
>(text.c_str()), text.size());
110 return std::string(
reinterpret_cast<char *
>(sha256_hash.data()), crypto_hash_sha256_BYTES);
113 std::string Crypto::sha512digest(
const std::string &text) {
114 std::array<unsigned char, crypto_hash_sha512_BYTES> sha512_hash{};
115 crypto_hash_sha512(sha512_hash.data(),
reinterpret_cast<const unsigned char *
>(text.c_str()), text.size());
116 return std::string(
reinterpret_cast<char *
>(sha512_hash.data()), crypto_hash_sha512_BYTES);
119 std::string Crypto::RSAPSSSign(ENGINE *engine,
const std::string &private_key,
const std::string &message) {
120 StructGuard<EVP_PKEY> key(
nullptr, EVP_PKEY_free);
121 StructGuard<RSA> rsa(
nullptr, RSA_free);
122 if (engine !=
nullptr) {
124 key.reset(ENGINE_load_private_key(engine, private_key.c_str(),
nullptr,
nullptr));
126 if (key ==
nullptr) {
127 LOG_ERROR <<
"ENGINE_load_private_key failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
128 return std::string();
131 rsa.reset(EVP_PKEY_get1_RSA(key.get()));
132 if (rsa ==
nullptr) {
133 LOG_ERROR <<
"EVP_PKEY_get1_RSA failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
134 return std::string();
137 StructGuard<BIO> bio(BIO_new_mem_buf(
const_cast<char *
>(private_key.c_str()),
static_cast<int>(private_key.size())),
139 key.reset(PEM_read_bio_PrivateKey(bio.get(),
nullptr,
nullptr,
nullptr));
140 if (key !=
nullptr) {
141 rsa.reset(EVP_PKEY_get1_RSA(key.get()));
144 if (rsa ==
nullptr) {
145 LOG_ERROR <<
"PEM_read_bio_PrivateKey failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
146 return std::string();
149 #if AKTUALIZR_OPENSSL_PRE_11
150 RSA_set_method(rsa.get(), RSA_PKCS1_SSLeay());
152 RSA_set_method(rsa.get(), RSA_PKCS1_OpenSSL());
156 const auto sign_size =
static_cast<unsigned int>(RSA_size(rsa.get()));
157 boost::scoped_array<unsigned char> EM(
new unsigned char[sign_size]);
158 boost::scoped_array<unsigned char> pSignature(
new unsigned char[sign_size]);
160 std::string digest = Crypto::sha256digest(message);
161 int status = RSA_padding_add_PKCS1_PSS(rsa.get(), EM.get(),
reinterpret_cast<const unsigned char *
>(digest.c_str()),
164 LOG_ERROR <<
"RSA_padding_add_PKCS1_PSS failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
165 return std::string();
169 status = RSA_private_encrypt(RSA_size(rsa.get()), EM.get(), pSignature.get(), rsa.get(), RSA_NO_PADDING);
171 LOG_ERROR <<
"RSA_private_encrypt failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
172 return std::string();
174 std::string retval = std::string(
reinterpret_cast<char *
>(pSignature.get()), sign_size);
178 std::string Crypto::Sign(KeyType key_type, ENGINE *engine,
const std::string &private_key,
const std::string &message) {
179 if (key_type == KeyType::kED25519) {
180 return Crypto::ED25519Sign(boost::algorithm::unhex(private_key), message);
182 return Crypto::RSAPSSSign(engine, private_key, message);
185 std::string Crypto::ED25519Sign(
const std::string &private_key,
const std::string &message) {
186 std::array<unsigned char, crypto_sign_BYTES> sig{};
187 crypto_sign_detached(sig.data(),
nullptr,
reinterpret_cast<const unsigned char *
>(message.c_str()), message.size(),
188 reinterpret_cast<const unsigned char *
>(private_key.c_str()));
189 return std::string(
reinterpret_cast<char *
>(sig.data()), crypto_sign_BYTES);
192 bool Crypto::RSAPSSVerify(
const std::string &public_key,
const std::string &signature,
const std::string &message) {
193 StructGuard<RSA> rsa(
nullptr, RSA_free);
194 StructGuard<BIO> bio(BIO_new_mem_buf(
const_cast<char *
>(public_key.c_str()),
static_cast<int>(public_key.size())),
198 if (PEM_read_bio_RSA_PUBKEY(bio.get(), &r,
nullptr,
nullptr) ==
nullptr) {
199 LOG_ERROR <<
"PEM_read_bio_RSA_PUBKEY failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
205 #if AKTUALIZR_OPENSSL_PRE_11
206 RSA_set_method(rsa.get(), RSA_PKCS1_SSLeay());
208 RSA_set_method(rsa.get(), RSA_PKCS1_OpenSSL());
211 const auto size =
static_cast<unsigned int>(RSA_size(rsa.get()));
212 boost::scoped_array<unsigned char> pDecrypted(
new unsigned char[size]);
217 RSA_public_decrypt(
static_cast<int>(signature.size()),
reinterpret_cast<const unsigned char *
>(signature.c_str()),
218 pDecrypted.get(), rsa.get(), RSA_NO_PADDING);
220 LOG_ERROR <<
"RSA_public_decrypt failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
224 std::string digest = Crypto::sha256digest(message);
227 status = RSA_verify_PKCS1_PSS(rsa.get(),
reinterpret_cast<const unsigned char *
>(digest.c_str()), EVP_sha256(),
228 pDecrypted.get(), -2 );
232 bool Crypto::ED25519Verify(
const std::string &public_key,
const std::string &signature,
const std::string &message) {
233 if (public_key.size() < crypto_sign_PUBLICKEYBYTES || signature.size() < crypto_sign_BYTES) {
236 return crypto_sign_verify_detached(
reinterpret_cast<const unsigned char *
>(signature.c_str()),
237 reinterpret_cast<const unsigned char *
>(message.c_str()), message.size(),
238 reinterpret_cast<const unsigned char *
>(public_key.c_str())) == 0;
241 bool Crypto::parseP12(BIO *p12_bio,
const std::string &p12_password, std::string *out_pkey, std::string *out_cert,
242 std::string *out_ca) {
243 #if AKTUALIZR_OPENSSL_PRE_11
244 SSLeay_add_all_algorithms();
246 StructGuard<PKCS12> p12(d2i_PKCS12_bio(p12_bio,
nullptr), PKCS12_free);
247 if (p12 ==
nullptr) {
248 LOG_ERROR <<
"Could not read from " << p12_bio <<
" file pointer";
253 auto stackx509_free = [](STACK_OF(X509) * stack) {
254 sk_X509_pop_free(stack, X509_free);
257 StructGuard<EVP_PKEY> pkey(
nullptr, EVP_PKEY_free);
258 StructGuard<X509> x509_cert(
nullptr, X509_free);
259 StructGuard<STACK_OF(X509)> ca_certs(
nullptr, stackx509_free);
262 X509 *x509c =
nullptr;
263 STACK_OF(X509) *cacs =
nullptr;
264 if (PKCS12_parse(p12.get(), p12_password.c_str(), &pk, &x509c, &cacs) == 0) {
265 LOG_ERROR <<
"Could not parse file from " << p12_bio <<
" source pointer";
269 x509_cert.reset(x509c);
270 ca_certs.reset(cacs);
273 StructGuard<BIO> pkey_pem_sink(BIO_new(BIO_s_mem()), BIO_vfree);
274 if (pkey_pem_sink ==
nullptr) {
275 LOG_ERROR <<
"Could not open pkey buffer for writing";
278 PEM_write_bio_PrivateKey(pkey_pem_sink.get(), pkey.get(),
nullptr,
nullptr, 0,
nullptr,
nullptr);
281 auto pkey_len = BIO_get_mem_data(pkey_pem_sink.get(), &pkey_buf);
282 *out_pkey = std::string(pkey_buf,
static_cast<size_t>(pkey_len));
286 StructGuard<BIO> cert_sink(BIO_new(BIO_s_mem()), BIO_vfree);
287 if (cert_sink ==
nullptr) {
288 LOG_ERROR <<
"Could not open certificate buffer for writing";
291 PEM_write_bio_X509(cert_sink.get(), x509_cert.get());
295 StructGuard<BIO> ca_sink(BIO_new(BIO_s_mem()), BIO_vfree);
296 if (ca_sink ==
nullptr) {
297 LOG_ERROR <<
"Could not open ca buffer for writing";
300 X509 *ca_cert =
nullptr;
301 for (
int i = 0; i < sk_X509_num(ca_certs.get()); i++) {
302 ca_cert = sk_X509_value(ca_certs.get(), i);
303 PEM_write_bio_X509(ca_sink.get(), ca_cert);
304 PEM_write_bio_X509(cert_sink.get(), ca_cert);
307 ca_len =
static_cast<size_t>(BIO_get_mem_data(ca_sink.get(), &ca_buf));
308 *out_ca = std::string(ca_buf, ca_len);
311 cert_len =
static_cast<size_t>(BIO_get_mem_data(cert_sink.get(), &cert_buf));
312 *out_cert = std::string(cert_buf, cert_len);
317 std::string Crypto::extractSubjectCN(
const std::string &cert) {
318 StructGuard<BIO> bio(BIO_new_mem_buf(
const_cast<char *
>(cert.c_str()),
static_cast<int>(cert.size())), BIO_vfree);
319 StructGuard<X509> x(PEM_read_bio_X509(bio.get(),
nullptr,
nullptr,
nullptr), X509_free);
321 throw std::runtime_error(
"Could not parse certificate");
324 int len = X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName,
nullptr, 0);
326 throw std::runtime_error(
"Could not get CN from certificate");
328 boost::scoped_array<char> buf(
new char[len + 1]);
329 X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName, buf.get(), len + 1);
330 return std::string(buf.get());
333 StructGuard<EVP_PKEY> Crypto::generateRSAKeyPairEVP(KeyType key_type) {
336 case KeyType::kRSA2048:
339 case KeyType::kRSA3072:
342 case KeyType::kRSA4096:
346 return {
nullptr, EVP_PKEY_free};
349 return Crypto::generateRSAKeyPairEVP(bits);
352 StructGuard<EVP_PKEY> Crypto::generateRSAKeyPairEVP(
const int bits) {
354 throw std::runtime_error(
"RSA key size can't be smaller than 31 bits");
357 int ret = RAND_status();
361 throw std::runtime_error(
"Random generator has not been sufficiently seeded.");
366 StructGuard<BIGNUM> bne(BN_new(), BN_free);
367 if (BN_set_word(bne.get(), RSA_F4) != 1) {
368 throw std::runtime_error(std::string(
"BN_set_word failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
371 StructGuard<RSA> rsa(RSA_new(), RSA_free);
372 if (RSA_generate_key_ex(rsa.get(), bits, bne.get(),
nullptr) != 1) {
373 throw std::runtime_error(std::string(
"RSA_generate_key_ex failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
376 StructGuard<EVP_PKEY> pkey(EVP_PKEY_new(), EVP_PKEY_free);
377 if (pkey.get() ==
nullptr) {
378 throw std::runtime_error(std::string(
"EVP_PKEY_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
382 if (!EVP_PKEY_assign_RSA(pkey.get(), rsa.release())) {
383 throw std::runtime_error(std::string(
"EVP_PKEY_assign_RSA failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
398 StructGuard<EVP_PKEY> pkey = generateRSAKeyPairEVP(key_type);
399 if (pkey ==
nullptr) {
404 StructGuard<BIO> pubkey_sink(BIO_new(BIO_s_mem()), BIO_vfree);
405 if (pubkey_sink ==
nullptr) {
408 ret = PEM_write_bio_PUBKEY(pubkey_sink.get(), pkey.get());
412 auto pubkey_len = BIO_get_mem_data(pubkey_sink.get(), &pubkey_buf);
413 *public_key = std::string(pubkey_buf,
static_cast<size_t>(pubkey_len));
416 StructGuard<BIO> privkey_sink(BIO_new(BIO_s_mem()), BIO_vfree);
417 if (privkey_sink ==
nullptr) {
421 ret = PEM_write_bio_RSAPrivateKey(privkey_sink.get(),
static_cast<RSA *
>(EVP_PKEY_get0(pkey.get())),
nullptr,
nullptr,
422 0,
nullptr,
nullptr);
427 auto privkey_len = BIO_get_mem_data(privkey_sink.get(), &privkey_buf);
428 *private_key = std::string(privkey_buf,
static_cast<size_t>(privkey_len));
432 bool Crypto::generateEDKeyPair(std::string *public_key, std::string *private_key) {
433 std::array<unsigned char, crypto_sign_PUBLICKEYBYTES> pk{};
434 std::array<unsigned char, crypto_sign_SECRETKEYBYTES> sk{};
435 crypto_sign_keypair(pk.data(), sk.data());
436 *public_key = boost::algorithm::hex(std::string(
reinterpret_cast<char *
>(pk.data()), crypto_sign_PUBLICKEYBYTES));
438 *private_key = boost::algorithm::hex(std::string(
reinterpret_cast<char *
>(sk.data()), crypto_sign_SECRETKEYBYTES));
443 bool Crypto::generateKeyPair(KeyType key_type, std::string *public_key, std::string *private_key) {
444 if (key_type == KeyType::kED25519) {
445 return Crypto::generateEDKeyPair(public_key, private_key);
450 bool Crypto::IsRsaKeyType(KeyType type) {
452 case KeyType::kRSA2048:
453 case KeyType::kRSA3072:
454 case KeyType::kRSA4096:
461 KeyType Crypto::IdentifyRSAKeyType(
const std::string &public_key_pem) {
462 StructGuard<BIO> bufio(BIO_new_mem_buf(
reinterpret_cast<const void *
>(public_key_pem.c_str()),
463 static_cast<int>(public_key_pem.length())),
465 if (bufio.get() ==
nullptr) {
466 throw std::runtime_error(
"BIO_new_mem_buf failed");
468 StructGuard<::RSA> rsa(PEM_read_bio_RSA_PUBKEY(bufio.get(),
nullptr,
nullptr,
nullptr), RSA_free);
470 if (rsa.get() ==
nullptr) {
471 return KeyType::kUnknown;
474 int key_length = RSA_size(rsa.get()) * 8;
479 switch (key_length) {
481 return KeyType::kRSA2048;
483 return KeyType::kRSA3072;
485 return KeyType::kRSA4096;
487 LOG_WARNING <<
"Weird key length:" << key_length;
488 return KeyType::kUnknown;
492 StructGuard<X509> Crypto::generateCert(
const int rsa_bits,
const int cert_days,
const std::string &cert_c,
493 const std::string &cert_st,
const std::string &cert_o,
494 const std::string &cert_cn,
bool self_sign) {
496 StructGuard<X509> certificate(X509_new(), X509_free);
497 if (certificate.get() ==
nullptr) {
498 throw std::runtime_error(std::string(
"X509_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
501 X509_set_version(certificate.get(), 2);
504 std::random_device urandom;
505 std::uniform_int_distribution<> serial_dist(0, (1UL << 20) - 1);
506 ASN1_INTEGER_set(X509_get_serialNumber(certificate.get()), serial_dist(urandom));
510 StructGuard<X509_NAME> subj(X509_NAME_new(), X509_NAME_free);
511 if (subj.get() ==
nullptr) {
512 throw std::runtime_error(std::string(
"X509_NAME_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
515 if (!cert_c.empty()) {
516 if (X509_NAME_add_entry_by_txt(subj.get(),
"C", MBSTRING_ASC,
517 reinterpret_cast<const unsigned char *
>(cert_c.c_str()), -1, -1, 0) == 0) {
518 throw std::runtime_error(std::string(
"X509_NAME_add_entry_by_txt failed: ") +
519 ERR_error_string(ERR_get_error(),
nullptr));
523 if (!cert_st.empty()) {
524 if (X509_NAME_add_entry_by_txt(subj.get(),
"ST", MBSTRING_ASC,
525 reinterpret_cast<const unsigned char *
>(cert_st.c_str()), -1, -1, 0) == 0) {
526 throw std::runtime_error(std::string(
"X509_NAME_add_entry_by_txt failed: ") +
527 ERR_error_string(ERR_get_error(),
nullptr));
531 if (!cert_o.empty()) {
532 if (X509_NAME_add_entry_by_txt(subj.get(),
"O", MBSTRING_ASC,
533 reinterpret_cast<const unsigned char *
>(cert_o.c_str()), -1, -1, 0) == 0) {
534 throw std::runtime_error(std::string(
"X509_NAME_add_entry_by_txt failed: ") +
535 ERR_error_string(ERR_get_error(),
nullptr));
539 assert(!cert_cn.empty());
540 if (X509_NAME_add_entry_by_txt(subj.get(),
"CN", MBSTRING_ASC,
541 reinterpret_cast<const unsigned char *
>(cert_cn.c_str()), -1, -1, 0) == 0) {
542 throw std::runtime_error(std::string(
"X509_NAME_add_entry_by_txt failed: ") +
543 ERR_error_string(ERR_get_error(),
nullptr));
546 if (X509_set_subject_name(certificate.get(), subj.get()) == 0) {
547 throw std::runtime_error(std::string(
"X509_set_subject_name failed: ") +
548 ERR_error_string(ERR_get_error(),
nullptr));
552 StructGuard<EVP_PKEY> certificate_pkey(Crypto::generateRSAKeyPairEVP(rsa_bits));
554 if (X509_set_pubkey(certificate.get(), certificate_pkey.get()) == 0) {
555 throw std::runtime_error(std::string(
"X509_set_pubkey failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
559 if (X509_gmtime_adj(X509_get_notBefore(certificate.get()), 0) ==
nullptr) {
560 throw std::runtime_error(std::string(
"X509_gmtime_adj failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
563 if (X509_gmtime_adj(X509_get_notAfter(certificate.get()), 60L * 60L * 24L * cert_days) ==
nullptr) {
564 throw std::runtime_error(std::string(
"X509_gmtime_adj failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
569 const EVP_MD *cert_digest = EVP_sha256();
570 if (X509_sign(certificate.get(), certificate_pkey.get(), cert_digest) == 0) {
571 throw std::runtime_error(std::string(
"X509_sign failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
573 LOG_INFO <<
"Successfully self-signed the generated certificate. This should not be used in production!";
579 void Crypto::signCert(
const std::string &cacert_path,
const std::string &capkey_path, X509 *
const certificate) {
581 std::string cacert_contents = Utils::readFile(cacert_path);
582 StructGuard<BIO> bio_in_cacert(BIO_new_mem_buf(cacert_contents.c_str(),
static_cast<int>(cacert_contents.size())),
584 StructGuard<X509> ca_certificate(PEM_read_bio_X509(bio_in_cacert.get(),
nullptr,
nullptr,
nullptr), X509_free);
585 if (ca_certificate.get() ==
nullptr) {
586 throw std::runtime_error(std::string(
"Reading CA certificate failed: ") +
587 ERR_error_string(ERR_get_error(),
nullptr));
591 std::string capkey_contents = Utils::readFile(capkey_path);
592 StructGuard<BIO> bio_in_capkey(BIO_new_mem_buf(capkey_contents.c_str(),
static_cast<int>(capkey_contents.size())),
594 StructGuard<EVP_PKEY> ca_privkey(PEM_read_bio_PrivateKey(bio_in_capkey.get(),
nullptr,
nullptr,
nullptr),
596 if (ca_privkey.get() ==
nullptr) {
597 throw std::runtime_error(std::string(
"PEM_read_bio_PrivateKey failed: ") +
598 ERR_error_string(ERR_get_error(),
nullptr));
602 X509_NAME *ca_subj = X509_get_subject_name(ca_certificate.get());
603 if (ca_subj ==
nullptr) {
604 throw std::runtime_error(std::string(
"X509_get_subject_name failed: ") +
605 ERR_error_string(ERR_get_error(),
nullptr));
608 if (X509_set_issuer_name(certificate, ca_subj) == 0) {
609 throw std::runtime_error(std::string(
"X509_set_issuer_name failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
613 const EVP_MD *cert_digest = EVP_sha256();
614 if (X509_sign(certificate, ca_privkey.get(), cert_digest) == 0) {
615 throw std::runtime_error(std::string(
"X509_sign failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
619 void Crypto::serializeCert(std::string *pkey, std::string *cert, X509 *
const certificate) {
622 StructGuard<BIO> privkey_file(BIO_new(BIO_s_mem()), BIO_vfree);
623 if (privkey_file ==
nullptr) {
624 throw std::runtime_error(std::string(
"BIO_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
627 StructGuard<EVP_PKEY> certificate_pkey(X509_get_pubkey(certificate), EVP_PKEY_free);
628 if (certificate_pkey ==
nullptr) {
629 throw std::runtime_error(std::string(
"X509_get_pubkey failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
632 StructGuard<RSA> certificate_rsa(EVP_PKEY_get1_RSA(certificate_pkey.get()), RSA_free);
633 if (certificate_rsa ==
nullptr) {
634 throw std::runtime_error(std::string(
"EVP_PKEY_get1_RSA failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
638 PEM_write_bio_RSAPrivateKey(privkey_file.get(), certificate_rsa.get(),
nullptr,
nullptr, 0,
nullptr,
nullptr);
640 throw std::runtime_error(std::string(
"PEM_write_RSAPrivateKey failed: ") +
641 ERR_error_string(ERR_get_error(),
nullptr));
644 auto privkey_len = BIO_get_mem_data(privkey_file.get(), &privkey_buf);
645 *pkey = std::string(privkey_buf,
static_cast<size_t>(privkey_len));
649 StructGuard<BIO> cert_file(BIO_new(BIO_s_mem()), BIO_vfree);
650 if (cert_file ==
nullptr) {
651 throw std::runtime_error(std::string(
"BIO_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
653 ret = PEM_write_bio_X509(cert_file.get(), certificate);
655 throw std::runtime_error(std::string(
"PEM_write_bio_X509 failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
658 auto cert_len = BIO_get_mem_data(cert_file.get(), &cert_buf);
659 *cert = std::string(cert_buf,
static_cast<size_t>(cert_len));
662 MultiPartHasher::Ptr MultiPartHasher::create(Hash::Type hash_type) {
664 case Hash::Type::kSha256: {
665 return std::make_shared<MultiPartSHA256Hasher>();
667 case Hash::Type::kSha512: {
668 return std::make_shared<MultiPartSHA512Hasher>();
671 LOG_ERROR <<
"Unsupported type of hashing: " << Hash::TypeString(hash_type);
677 Hash Hash::generate(Type type,
const std::string &
data) {
681 case Type::kSha256: {
682 hash = boost::algorithm::hex(Crypto::sha256digest(
data));
685 case Type::kSha512: {
686 hash = boost::algorithm::hex(Crypto::sha512digest(
data));
690 throw std::invalid_argument(
"Unsupported hash type");
694 return Hash(type, hash);
697 Hash::Hash(
const std::string &type,
const std::string &hash) : hash_(boost::algorithm::to_upper_copy(hash)) {
698 if (type ==
"sha512") {
699 type_ = Hash::Type::kSha512;
700 }
else if (type ==
"sha256") {
701 type_ = Hash::Type::kSha256;
703 type_ = Hash::Type::kUnknownAlgorithm;
707 Hash::Hash(Type type,
const std::string &hash) : type_(type), hash_(boost::algorithm::to_upper_copy(hash)) {}
709 bool Hash::operator==(
const Hash &other)
const {
return type_ == other.type_ && hash_ == other.hash_; }
711 std::string Hash::TypeString(Type type) {
722 std::string Hash::TypeString()
const {
return TypeString(type_); }
724 Hash::Type Hash::type()
const {
return type_; }
726 std::ostream &operator<<(std::ostream &os,
const Hash &h) {
727 os <<
"Hash: " << h.hash_;