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(
const Json::Value &uptane_json) {
25 if (!uptane_json[
"keytype"].isString()) {
26 type_ = KeyType::kUnknown;
29 if (!uptane_json[
"keyval"].isObject()) {
30 type_ = KeyType::kUnknown;
34 if (!uptane_json[
"keyval"][
"public"].isString()) {
35 type_ = KeyType::kUnknown;
39 keytype = uptane_json[
"keytype"].asString();
40 keyvalue = uptane_json[
"keyval"][
"public"].asString();
41 }
catch (
const std::exception &ex) {
42 LOG_ERROR <<
"Failed to initialize public key: " << ex.what();
43 type_ = KeyType::kUnknown;
47 std::transform(keytype.begin(), keytype.end(), keytype.begin(), ::tolower);
50 if (keytype ==
"ed25519") {
51 type = KeyType::kED25519;
52 }
else if (keytype ==
"rsa") {
53 type = Crypto::IdentifyRSAKeyType(keyvalue);
54 if (type == KeyType::kUnknown) {
55 LOG_WARNING <<
"Couldn't identify length of RSA key";
58 type = KeyType::kUnknown;
64 PublicKey::PublicKey(
const std::string &value, KeyType type) : value_(value), type_(type) {
65 if (Crypto::IsRsaKeyType(type)) {
66 if (type != Crypto::IdentifyRSAKeyType(value)) {
67 throw std::logic_error(
"RSA key length is incorrect");
74 case KeyType::kED25519:
75 return Crypto::ED25519Verify(boost::algorithm::unhex(value_), Utils::fromBase64(signature), message);
76 case KeyType::kRSA2048:
77 case KeyType::kRSA3072:
78 case KeyType::kRSA4096:
79 return Crypto::RSAPSSVerify(value_, Utils::fromBase64(signature), message);
85 bool PublicKey::operator==(
const PublicKey &rhs)
const {
return value_ == rhs.value_ && type_ == rhs.type_; }
89 case KeyType::kRSA2048:
90 case KeyType::kRSA3072:
91 case KeyType::kRSA4096:
92 res[
"keytype"] =
"RSA";
94 case KeyType::kED25519:
95 res[
"keytype"] =
"ED25519";
97 case KeyType::kUnknown:
98 res[
"keytype"] =
"unknown";
101 throw std::range_error(
"Unknown key type in PublicKey::ToUptane");
103 res[
"keyval"][
"public"] = value_;
107 std::string PublicKey::KeyId()
const {
108 std::string key_content = value_;
110 boost::algorithm::trim_right_if(key_content, boost::algorithm::is_any_of(
"\n"));
111 std::string keyid = boost::algorithm::hex(Crypto::sha256digest(Utils::jsonToCanonicalStr(Json::Value(key_content))));
112 std::transform(keyid.begin(), keyid.end(), keyid.begin(), ::tolower);
116 std::string Crypto::sha256digest(
const std::string &text) {
117 std::array<unsigned char, crypto_hash_sha256_BYTES> sha256_hash{};
118 crypto_hash_sha256(sha256_hash.data(),
reinterpret_cast<const unsigned char *
>(text.c_str()), text.size());
119 return std::string(
reinterpret_cast<char *
>(sha256_hash.data()), crypto_hash_sha256_BYTES);
122 std::string Crypto::sha512digest(
const std::string &text) {
123 std::array<unsigned char, crypto_hash_sha512_BYTES> sha512_hash{};
124 crypto_hash_sha512(sha512_hash.data(),
reinterpret_cast<const unsigned char *
>(text.c_str()), text.size());
125 return std::string(
reinterpret_cast<char *
>(sha512_hash.data()), crypto_hash_sha512_BYTES);
128 std::string Crypto::RSAPSSSign(ENGINE *engine,
const std::string &private_key,
const std::string &message) {
129 StructGuard<EVP_PKEY> key(
nullptr, EVP_PKEY_free);
130 StructGuard<RSA> rsa(
nullptr, RSA_free);
131 if (engine !=
nullptr) {
133 key.reset(ENGINE_load_private_key(engine, private_key.c_str(),
nullptr,
nullptr));
135 if (key ==
nullptr) {
136 LOG_ERROR <<
"ENGINE_load_private_key failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
137 return std::string();
140 rsa.reset(EVP_PKEY_get1_RSA(key.get()));
141 if (rsa ==
nullptr) {
142 LOG_ERROR <<
"EVP_PKEY_get1_RSA failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
143 return std::string();
146 StructGuard<BIO> bio(BIO_new_mem_buf(
const_cast<char *
>(private_key.c_str()),
static_cast<int>(private_key.size())),
148 key.reset(PEM_read_bio_PrivateKey(bio.get(),
nullptr,
nullptr,
nullptr));
149 if (key !=
nullptr) {
150 rsa.reset(EVP_PKEY_get1_RSA(key.get()));
153 if (rsa ==
nullptr) {
154 LOG_ERROR <<
"PEM_read_bio_PrivateKey failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
155 return std::string();
158 #if AKTUALIZR_OPENSSL_PRE_11
159 RSA_set_method(rsa.get(), RSA_PKCS1_SSLeay());
161 RSA_set_method(rsa.get(), RSA_PKCS1_OpenSSL());
165 const auto sign_size =
static_cast<unsigned int>(RSA_size(rsa.get()));
166 boost::scoped_array<unsigned char> EM(
new unsigned char[sign_size]);
167 boost::scoped_array<unsigned char> pSignature(
new unsigned char[sign_size]);
169 std::string digest = Crypto::sha256digest(message);
170 int status = RSA_padding_add_PKCS1_PSS(rsa.get(), EM.get(),
reinterpret_cast<const unsigned char *
>(digest.c_str()),
173 LOG_ERROR <<
"RSA_padding_add_PKCS1_PSS failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
174 return std::string();
178 status = RSA_private_encrypt(RSA_size(rsa.get()), EM.get(), pSignature.get(), rsa.get(), RSA_NO_PADDING);
180 LOG_ERROR <<
"RSA_private_encrypt failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
181 return std::string();
183 std::string retval = std::string(
reinterpret_cast<char *
>(pSignature.get()), sign_size);
187 std::string Crypto::Sign(KeyType key_type, ENGINE *engine,
const std::string &private_key,
const std::string &message) {
188 if (key_type == KeyType::kED25519) {
189 return Crypto::ED25519Sign(boost::algorithm::unhex(private_key), message);
191 return Crypto::RSAPSSSign(engine, private_key, message);
194 std::string Crypto::ED25519Sign(
const std::string &private_key,
const std::string &message) {
195 std::array<unsigned char, crypto_sign_BYTES> sig{};
196 crypto_sign_detached(sig.data(),
nullptr,
reinterpret_cast<const unsigned char *
>(message.c_str()), message.size(),
197 reinterpret_cast<const unsigned char *
>(private_key.c_str()));
198 return std::string(
reinterpret_cast<char *
>(sig.data()), crypto_sign_BYTES);
201 bool Crypto::RSAPSSVerify(
const std::string &public_key,
const std::string &signature,
const std::string &message) {
202 StructGuard<RSA> rsa(
nullptr, RSA_free);
203 StructGuard<BIO> bio(BIO_new_mem_buf(
const_cast<char *
>(public_key.c_str()),
static_cast<int>(public_key.size())),
207 if (PEM_read_bio_RSA_PUBKEY(bio.get(), &r,
nullptr,
nullptr) ==
nullptr) {
208 LOG_ERROR <<
"PEM_read_bio_RSA_PUBKEY failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
214 #if AKTUALIZR_OPENSSL_PRE_11
215 RSA_set_method(rsa.get(), RSA_PKCS1_SSLeay());
217 RSA_set_method(rsa.get(), RSA_PKCS1_OpenSSL());
220 const auto size =
static_cast<unsigned int>(RSA_size(rsa.get()));
221 boost::scoped_array<unsigned char> pDecrypted(
new unsigned char[size]);
226 RSA_public_decrypt(
static_cast<int>(signature.size()),
reinterpret_cast<const unsigned char *
>(signature.c_str()),
227 pDecrypted.get(), rsa.get(), RSA_NO_PADDING);
229 LOG_ERROR <<
"RSA_public_decrypt failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
233 std::string digest = Crypto::sha256digest(message);
236 status = RSA_verify_PKCS1_PSS(rsa.get(),
reinterpret_cast<const unsigned char *
>(digest.c_str()), EVP_sha256(),
237 pDecrypted.get(), -2 );
241 bool Crypto::ED25519Verify(
const std::string &public_key,
const std::string &signature,
const std::string &message) {
242 if (public_key.size() < crypto_sign_PUBLICKEYBYTES || signature.size() < crypto_sign_BYTES) {
245 return crypto_sign_verify_detached(
reinterpret_cast<const unsigned char *
>(signature.c_str()),
246 reinterpret_cast<const unsigned char *
>(message.c_str()), message.size(),
247 reinterpret_cast<const unsigned char *
>(public_key.c_str())) == 0;
250 bool Crypto::parseP12(BIO *p12_bio,
const std::string &p12_password, std::string *out_pkey, std::string *out_cert,
251 std::string *out_ca) {
252 #if AKTUALIZR_OPENSSL_PRE_11
253 SSLeay_add_all_algorithms();
255 StructGuard<PKCS12> p12(d2i_PKCS12_bio(p12_bio,
nullptr), PKCS12_free);
256 if (p12 ==
nullptr) {
257 LOG_ERROR <<
"Could not read from " << p12_bio <<
" file pointer";
262 auto stackx509_free = [](STACK_OF(X509) * stack) {
263 sk_X509_pop_free(stack, X509_free);
266 StructGuard<EVP_PKEY> pkey(
nullptr, EVP_PKEY_free);
267 StructGuard<X509> x509_cert(
nullptr, X509_free);
268 StructGuard<STACK_OF(X509)> ca_certs(
nullptr, stackx509_free);
271 X509 *x509c =
nullptr;
272 STACK_OF(X509) *cacs =
nullptr;
273 if (PKCS12_parse(p12.get(), p12_password.c_str(), &pk, &x509c, &cacs) == 0) {
274 LOG_ERROR <<
"Could not parse file from " << p12_bio <<
" source pointer";
278 x509_cert.reset(x509c);
279 ca_certs.reset(cacs);
282 StructGuard<BIO> pkey_pem_sink(BIO_new(BIO_s_mem()), BIO_vfree);
283 if (pkey_pem_sink ==
nullptr) {
284 LOG_ERROR <<
"Could not open pkey buffer for writing";
287 PEM_write_bio_PrivateKey(pkey_pem_sink.get(), pkey.get(),
nullptr,
nullptr, 0,
nullptr,
nullptr);
290 auto pkey_len = BIO_get_mem_data(pkey_pem_sink.get(), &pkey_buf);
291 *out_pkey = std::string(pkey_buf,
static_cast<size_t>(pkey_len));
295 StructGuard<BIO> cert_sink(BIO_new(BIO_s_mem()), BIO_vfree);
296 if (cert_sink ==
nullptr) {
297 LOG_ERROR <<
"Could not open certificate buffer for writing";
300 PEM_write_bio_X509(cert_sink.get(), x509_cert.get());
304 StructGuard<BIO> ca_sink(BIO_new(BIO_s_mem()), BIO_vfree);
305 if (ca_sink ==
nullptr) {
306 LOG_ERROR <<
"Could not open ca buffer for writing";
309 X509 *ca_cert =
nullptr;
310 for (
int i = 0; i < sk_X509_num(ca_certs.get()); i++) {
311 ca_cert = sk_X509_value(ca_certs.get(), i);
312 PEM_write_bio_X509(ca_sink.get(), ca_cert);
313 PEM_write_bio_X509(cert_sink.get(), ca_cert);
316 ca_len =
static_cast<size_t>(BIO_get_mem_data(ca_sink.get(), &ca_buf));
317 *out_ca = std::string(ca_buf, ca_len);
320 cert_len =
static_cast<size_t>(BIO_get_mem_data(cert_sink.get(), &cert_buf));
321 *out_cert = std::string(cert_buf, cert_len);
326 std::string Crypto::extractSubjectCN(
const std::string &cert) {
327 StructGuard<BIO> bio(BIO_new_mem_buf(
const_cast<char *
>(cert.c_str()),
static_cast<int>(cert.size())), BIO_vfree);
328 StructGuard<X509> x(PEM_read_bio_X509(bio.get(),
nullptr,
nullptr,
nullptr), X509_free);
330 throw std::runtime_error(
"Could not parse certificate");
333 int len = X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName,
nullptr, 0);
335 throw std::runtime_error(
"Could not get CN from certificate");
337 boost::scoped_array<char> buf(
new char[len + 1]);
338 X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName, buf.get(), len + 1);
339 return std::string(buf.get());
342 StructGuard<EVP_PKEY> Crypto::generateRSAKeyPairEVP(KeyType key_type) {
345 case KeyType::kRSA2048:
348 case KeyType::kRSA3072:
351 case KeyType::kRSA4096:
355 return {
nullptr, EVP_PKEY_free};
358 return Crypto::generateRSAKeyPairEVP(bits);
361 StructGuard<EVP_PKEY> Crypto::generateRSAKeyPairEVP(
const int bits) {
363 throw std::runtime_error(
"RSA key size can't be smaller than 31 bits");
366 int ret = RAND_status();
370 throw std::runtime_error(
"Random generator has not been sufficiently seeded.");
375 StructGuard<BIGNUM> bne(BN_new(), BN_free);
376 if (BN_set_word(bne.get(), RSA_F4) != 1) {
377 throw std::runtime_error(std::string(
"BN_set_word failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
380 StructGuard<RSA> rsa(RSA_new(), RSA_free);
381 if (RSA_generate_key_ex(rsa.get(), bits, bne.get(),
nullptr) != 1) {
382 throw std::runtime_error(std::string(
"RSA_generate_key_ex failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
385 StructGuard<EVP_PKEY> pkey(EVP_PKEY_new(), EVP_PKEY_free);
386 if (pkey.get() ==
nullptr) {
387 throw std::runtime_error(std::string(
"EVP_PKEY_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
391 if (!EVP_PKEY_assign_RSA(pkey.get(), rsa.release())) {
392 throw std::runtime_error(std::string(
"EVP_PKEY_assign_RSA failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
407 StructGuard<EVP_PKEY> pkey = generateRSAKeyPairEVP(key_type);
408 if (pkey ==
nullptr) {
413 StructGuard<BIO> pubkey_sink(BIO_new(BIO_s_mem()), BIO_vfree);
414 if (pubkey_sink ==
nullptr) {
417 ret = PEM_write_bio_PUBKEY(pubkey_sink.get(), pkey.get());
421 auto pubkey_len = BIO_get_mem_data(pubkey_sink.get(), &pubkey_buf);
422 *public_key = std::string(pubkey_buf,
static_cast<size_t>(pubkey_len));
425 StructGuard<BIO> privkey_sink(BIO_new(BIO_s_mem()), BIO_vfree);
426 if (privkey_sink ==
nullptr) {
430 ret = PEM_write_bio_RSAPrivateKey(privkey_sink.get(),
static_cast<RSA *
>(EVP_PKEY_get0(pkey.get())),
nullptr,
nullptr,
431 0,
nullptr,
nullptr);
436 auto privkey_len = BIO_get_mem_data(privkey_sink.get(), &privkey_buf);
437 *private_key = std::string(privkey_buf,
static_cast<size_t>(privkey_len));
441 bool Crypto::generateEDKeyPair(std::string *public_key, std::string *private_key) {
442 std::array<unsigned char, crypto_sign_PUBLICKEYBYTES> pk{};
443 std::array<unsigned char, crypto_sign_SECRETKEYBYTES> sk{};
444 crypto_sign_keypair(pk.data(), sk.data());
445 *public_key = boost::algorithm::hex(std::string(
reinterpret_cast<char *
>(pk.data()), crypto_sign_PUBLICKEYBYTES));
447 *private_key = boost::algorithm::hex(std::string(
reinterpret_cast<char *
>(sk.data()), crypto_sign_SECRETKEYBYTES));
452 bool Crypto::generateKeyPair(KeyType key_type, std::string *public_key, std::string *private_key) {
453 if (key_type == KeyType::kED25519) {
454 return Crypto::generateEDKeyPair(public_key, private_key);
459 bool Crypto::IsRsaKeyType(KeyType type) {
461 case KeyType::kRSA2048:
462 case KeyType::kRSA3072:
463 case KeyType::kRSA4096:
470 KeyType Crypto::IdentifyRSAKeyType(
const std::string &public_key_pem) {
471 StructGuard<BIO> bufio(BIO_new_mem_buf(
reinterpret_cast<const void *
>(public_key_pem.c_str()),
472 static_cast<int>(public_key_pem.length())),
474 if (bufio.get() ==
nullptr) {
475 throw std::runtime_error(
"BIO_new_mem_buf failed");
477 StructGuard<::RSA> rsa(PEM_read_bio_RSA_PUBKEY(bufio.get(),
nullptr,
nullptr,
nullptr), RSA_free);
479 if (rsa.get() ==
nullptr) {
480 return KeyType::kUnknown;
483 int key_length = RSA_size(rsa.get()) * 8;
488 switch (key_length) {
490 return KeyType::kRSA2048;
492 return KeyType::kRSA3072;
494 return KeyType::kRSA4096;
496 LOG_WARNING <<
"Weird key length:" << key_length;
497 return KeyType::kUnknown;
501 StructGuard<X509> Crypto::generateCert(
const int rsa_bits,
const int cert_days,
const std::string &cert_c,
502 const std::string &cert_st,
const std::string &cert_o,
503 const std::string &cert_cn,
bool self_sign) {
505 StructGuard<X509> certificate(X509_new(), X509_free);
506 if (certificate.get() ==
nullptr) {
507 throw std::runtime_error(std::string(
"X509_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
510 X509_set_version(certificate.get(), 2);
513 std::random_device urandom;
514 std::uniform_int_distribution<> serial_dist(0, (1UL << 20) - 1);
515 ASN1_INTEGER_set(X509_get_serialNumber(certificate.get()), serial_dist(urandom));
519 StructGuard<X509_NAME> subj(X509_NAME_new(), X509_NAME_free);
520 if (subj.get() ==
nullptr) {
521 throw std::runtime_error(std::string(
"X509_NAME_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
524 if (!cert_c.empty()) {
525 if (X509_NAME_add_entry_by_txt(subj.get(),
"C", MBSTRING_ASC,
526 reinterpret_cast<const unsigned char *
>(cert_c.c_str()), -1, -1, 0) == 0) {
527 throw std::runtime_error(std::string(
"X509_NAME_add_entry_by_txt failed: ") +
528 ERR_error_string(ERR_get_error(),
nullptr));
532 if (!cert_st.empty()) {
533 if (X509_NAME_add_entry_by_txt(subj.get(),
"ST", MBSTRING_ASC,
534 reinterpret_cast<const unsigned char *
>(cert_st.c_str()), -1, -1, 0) == 0) {
535 throw std::runtime_error(std::string(
"X509_NAME_add_entry_by_txt failed: ") +
536 ERR_error_string(ERR_get_error(),
nullptr));
540 if (!cert_o.empty()) {
541 if (X509_NAME_add_entry_by_txt(subj.get(),
"O", MBSTRING_ASC,
542 reinterpret_cast<const unsigned char *
>(cert_o.c_str()), -1, -1, 0) == 0) {
543 throw std::runtime_error(std::string(
"X509_NAME_add_entry_by_txt failed: ") +
544 ERR_error_string(ERR_get_error(),
nullptr));
548 assert(!cert_cn.empty());
549 if (X509_NAME_add_entry_by_txt(subj.get(),
"CN", MBSTRING_ASC,
550 reinterpret_cast<const unsigned char *
>(cert_cn.c_str()), -1, -1, 0) == 0) {
551 throw std::runtime_error(std::string(
"X509_NAME_add_entry_by_txt failed: ") +
552 ERR_error_string(ERR_get_error(),
nullptr));
555 if (X509_set_subject_name(certificate.get(), subj.get()) == 0) {
556 throw std::runtime_error(std::string(
"X509_set_subject_name failed: ") +
557 ERR_error_string(ERR_get_error(),
nullptr));
561 StructGuard<EVP_PKEY> certificate_pkey(Crypto::generateRSAKeyPairEVP(rsa_bits));
563 if (X509_set_pubkey(certificate.get(), certificate_pkey.get()) == 0) {
564 throw std::runtime_error(std::string(
"X509_set_pubkey failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
568 if (X509_gmtime_adj(X509_get_notBefore(certificate.get()), 0) ==
nullptr) {
569 throw std::runtime_error(std::string(
"X509_gmtime_adj failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
572 if (X509_gmtime_adj(X509_get_notAfter(certificate.get()), 60L * 60L * 24L * cert_days) ==
nullptr) {
573 throw std::runtime_error(std::string(
"X509_gmtime_adj failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
578 const EVP_MD *cert_digest = EVP_sha256();
579 if (X509_sign(certificate.get(), certificate_pkey.get(), cert_digest) == 0) {
580 throw std::runtime_error(std::string(
"X509_sign failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
582 LOG_INFO <<
"Successfully self-signed the generated certificate. This should not be used in production!";
588 void Crypto::signCert(
const std::string &cacert_path,
const std::string &capkey_path, X509 *
const certificate) {
590 std::string cacert_contents = Utils::readFile(cacert_path);
591 StructGuard<BIO> bio_in_cacert(BIO_new_mem_buf(cacert_contents.c_str(),
static_cast<int>(cacert_contents.size())),
593 StructGuard<X509> ca_certificate(PEM_read_bio_X509(bio_in_cacert.get(),
nullptr,
nullptr,
nullptr), X509_free);
594 if (ca_certificate.get() ==
nullptr) {
595 throw std::runtime_error(std::string(
"Reading CA certificate failed: ") +
596 ERR_error_string(ERR_get_error(),
nullptr));
600 std::string capkey_contents = Utils::readFile(capkey_path);
601 StructGuard<BIO> bio_in_capkey(BIO_new_mem_buf(capkey_contents.c_str(),
static_cast<int>(capkey_contents.size())),
603 StructGuard<EVP_PKEY> ca_privkey(PEM_read_bio_PrivateKey(bio_in_capkey.get(),
nullptr,
nullptr,
nullptr),
605 if (ca_privkey.get() ==
nullptr) {
606 throw std::runtime_error(std::string(
"PEM_read_bio_PrivateKey failed: ") +
607 ERR_error_string(ERR_get_error(),
nullptr));
611 X509_NAME *ca_subj = X509_get_subject_name(ca_certificate.get());
612 if (ca_subj ==
nullptr) {
613 throw std::runtime_error(std::string(
"X509_get_subject_name failed: ") +
614 ERR_error_string(ERR_get_error(),
nullptr));
617 if (X509_set_issuer_name(certificate, ca_subj) == 0) {
618 throw std::runtime_error(std::string(
"X509_set_issuer_name failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
622 const EVP_MD *cert_digest = EVP_sha256();
623 if (X509_sign(certificate, ca_privkey.get(), cert_digest) == 0) {
624 throw std::runtime_error(std::string(
"X509_sign failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
628 void Crypto::serializeCert(std::string *pkey, std::string *cert, X509 *
const certificate) {
631 StructGuard<BIO> privkey_file(BIO_new(BIO_s_mem()), BIO_vfree);
632 if (privkey_file ==
nullptr) {
633 throw std::runtime_error(std::string(
"BIO_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
636 StructGuard<EVP_PKEY> certificate_pkey(X509_get_pubkey(certificate), EVP_PKEY_free);
637 if (certificate_pkey ==
nullptr) {
638 throw std::runtime_error(std::string(
"X509_get_pubkey failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
641 StructGuard<RSA> certificate_rsa(EVP_PKEY_get1_RSA(certificate_pkey.get()), RSA_free);
642 if (certificate_rsa ==
nullptr) {
643 throw std::runtime_error(std::string(
"EVP_PKEY_get1_RSA failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
647 PEM_write_bio_RSAPrivateKey(privkey_file.get(), certificate_rsa.get(),
nullptr,
nullptr, 0,
nullptr,
nullptr);
649 throw std::runtime_error(std::string(
"PEM_write_RSAPrivateKey failed: ") +
650 ERR_error_string(ERR_get_error(),
nullptr));
653 auto privkey_len = BIO_get_mem_data(privkey_file.get(), &privkey_buf);
654 *pkey = std::string(privkey_buf,
static_cast<size_t>(privkey_len));
658 StructGuard<BIO> cert_file(BIO_new(BIO_s_mem()), BIO_vfree);
659 if (cert_file ==
nullptr) {
660 throw std::runtime_error(std::string(
"BIO_new failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
662 ret = PEM_write_bio_X509(cert_file.get(), certificate);
664 throw std::runtime_error(std::string(
"PEM_write_bio_X509 failed: ") + ERR_error_string(ERR_get_error(),
nullptr));
667 auto cert_len = BIO_get_mem_data(cert_file.get(), &cert_buf);
668 *cert = std::string(cert_buf,
static_cast<size_t>(cert_len));
671 MultiPartHasher::Ptr MultiPartHasher::create(Hash::Type hash_type) {
673 case Hash::Type::kSha256: {
674 return std::make_shared<MultiPartSHA256Hasher>();
676 case Hash::Type::kSha512: {
677 return std::make_shared<MultiPartSHA512Hasher>();
680 LOG_ERROR <<
"Unsupported type of hashing: " << Hash::TypeString(hash_type);
686 Hash Hash::generate(Type type,
const std::string &
data) {
690 case Type::kSha256: {
691 hash = boost::algorithm::hex(Crypto::sha256digest(
data));
694 case Type::kSha512: {
695 hash = boost::algorithm::hex(Crypto::sha512digest(
data));
699 throw std::invalid_argument(
"Unsupported hash type");
703 return Hash(type, hash);
706 Hash::Hash(
const std::string &type,
const std::string &hash) : hash_(boost::algorithm::to_upper_copy(hash)) {
707 if (type ==
"sha512") {
708 type_ = Hash::Type::kSha512;
709 }
else if (type ==
"sha256") {
710 type_ = Hash::Type::kSha256;
712 type_ = Hash::Type::kUnknownAlgorithm;
716 Hash::Hash(Type type,
const std::string &hash) : type_(type), hash_(boost::algorithm::to_upper_copy(hash)) {}
718 bool Hash::operator==(
const Hash &other)
const {
return type_ == other.type_ && hash_ == other.hash_; }
720 std::string Hash::TypeString(Type type) {
731 std::string Hash::TypeString()
const {
return TypeString(type_); }
733 Hash::Type Hash::type()
const {
return type_; }
735 std::ostream &operator<<(std::ostream &os,
const Hash &h) {
736 os <<
"Hash: " << h.hash_;