7 #include <boost/algorithm/hex.hpp> 8 #include <boost/scoped_array.hpp> 11 #include "logging/logging.h" 12 #include "openssl_compat.h" 13 #include "utilities/utils.h" 15 PublicKey::PublicKey(
const boost::filesystem::path &path) : value_(
Utils::readFile(path)) {
16 type_ = Crypto::IdentifyRSAKeyType(value_);
19 PublicKey::PublicKey(Json::Value uptane_json) {
20 if (!uptane_json[
"keytype"].isString()) {
21 type_ = KeyType::kUnknown;
24 if (!uptane_json[
"keyval"].isObject()) {
25 type_ = KeyType::kUnknown;
29 if (!uptane_json[
"keyval"][
"public"].isString()) {
30 type_ = KeyType::kUnknown;
34 std::string keytype = uptane_json[
"keytype"].asString();
35 std::string keyvalue = uptane_json[
"keyval"][
"public"].asString();
37 std::transform(keytype.begin(), keytype.end(), keytype.begin(), ::tolower);
40 if (keytype ==
"ed25519") {
41 type = KeyType::kED25519;
42 }
else if (keytype ==
"rsa") {
43 type = Crypto::IdentifyRSAKeyType(keyvalue);
44 if (type == KeyType::kUnknown) {
45 LOG_WARNING <<
"Couldn't identify length of RSA key";
48 type = KeyType::kUnknown;
54 PublicKey::PublicKey(
const std::string &value, KeyType type) : value_(value), type_(type) {
55 if (Crypto::IsRsaKeyType(type)) {
56 if (type != Crypto::IdentifyRSAKeyType(value)) {
57 std::logic_error(
"RSA key length is incorrect");
64 case KeyType::kED25519:
65 return Crypto::ED25519Verify(boost::algorithm::unhex(value_), Utils::fromBase64(signature), message);
66 case KeyType::kRSA2048:
67 case KeyType::kRSA3072:
68 case KeyType::kRSA4096:
69 return Crypto::RSAPSSVerify(value_, Utils::fromBase64(signature), message);
75 bool PublicKey::operator==(
const PublicKey &rhs)
const {
return value_ == rhs.value_ && type_ == rhs.type_; }
79 case KeyType::kRSA2048:
80 case KeyType::kRSA3072:
81 case KeyType::kRSA4096:
82 res[
"keytype"] =
"RSA";
84 case KeyType::kED25519:
85 res[
"keytype"] =
"ED25519";
87 case KeyType::kUnknown:
88 res[
"keytype"] =
"unknown";
91 throw std::range_error(
"Unknown key type in PublicKey::ToUptane");
93 res[
"keyval"][
"public"] = value_;
97 std::string PublicKey::KeyId()
const {
98 std::string key_content = value_;
100 boost::algorithm::trim_right_if(key_content, boost::algorithm::is_any_of(
"\n"));
101 std::string keyid = boost::algorithm::hex(Crypto::sha256digest(Utils::jsonToCanonicalStr(Json::Value(key_content))));
102 std::transform(keyid.begin(), keyid.end(), keyid.begin(), ::tolower);
106 std::string Crypto::sha256digest(
const std::string &text) {
107 std::array<unsigned char, crypto_hash_sha256_BYTES> sha256_hash{};
108 crypto_hash_sha256(sha256_hash.data(),
reinterpret_cast<const unsigned char *
>(text.c_str()), text.size());
109 return std::string(reinterpret_cast<char *>(sha256_hash.data()), crypto_hash_sha256_BYTES);
112 std::string Crypto::sha512digest(
const std::string &text) {
113 std::array<unsigned char, crypto_hash_sha512_BYTES> sha512_hash{};
114 crypto_hash_sha512(sha512_hash.data(),
reinterpret_cast<const unsigned char *
>(text.c_str()), text.size());
115 return std::string(reinterpret_cast<char *>(sha512_hash.data()), crypto_hash_sha512_BYTES);
118 std::string Crypto::RSAPSSSign(ENGINE *engine,
const std::string &private_key,
const std::string &message) {
119 StructGuard<EVP_PKEY> key(
nullptr, EVP_PKEY_free);
120 StructGuard<RSA> rsa(
nullptr, RSA_free);
121 if (engine !=
nullptr) {
123 key.reset(ENGINE_load_private_key(engine, private_key.c_str(),
nullptr,
nullptr));
125 if (key ==
nullptr) {
126 LOG_ERROR <<
"ENGINE_load_private_key failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
127 return std::string();
130 rsa.reset(EVP_PKEY_get1_RSA(key.get()));
131 if (rsa ==
nullptr) {
132 LOG_ERROR <<
"EVP_PKEY_get1_RSA failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
133 return std::string();
136 StructGuard<BIO> bio(BIO_new_mem_buf(const_cast<char *>(private_key.c_str()), static_cast<int>(private_key.size())),
138 key.reset(PEM_read_bio_PrivateKey(bio.get(),
nullptr,
nullptr,
nullptr));
139 if (key !=
nullptr) {
140 rsa.reset(EVP_PKEY_get1_RSA(key.get()));
143 if (rsa ==
nullptr) {
144 LOG_ERROR <<
"PEM_read_bio_PrivateKey failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
145 return std::string();
148 #if AKTUALIZR_OPENSSL_PRE_11 149 RSA_set_method(rsa.get(), RSA_PKCS1_SSLeay());
151 RSA_set_method(rsa.get(), RSA_PKCS1_OpenSSL());
155 const auto sign_size =
static_cast<unsigned int>(RSA_size(rsa.get()));
156 boost::scoped_array<unsigned char> EM(
new unsigned char[sign_size]);
157 boost::scoped_array<unsigned char> pSignature(
new unsigned char[sign_size]);
159 std::string digest = Crypto::sha256digest(message);
160 int status = RSA_padding_add_PKCS1_PSS(rsa.get(), EM.get(),
reinterpret_cast<const unsigned char *
>(digest.c_str()),
163 LOG_ERROR <<
"RSA_padding_add_PKCS1_PSS failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
164 return std::string();
168 status = RSA_private_encrypt(RSA_size(rsa.get()), EM.get(), pSignature.get(), rsa.get(), RSA_NO_PADDING);
170 LOG_ERROR <<
"RSA_private_encrypt failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
171 return std::string();
173 std::string retval = std::string(reinterpret_cast<char *>(pSignature.get()), sign_size);
177 std::string Crypto::Sign(KeyType key_type, ENGINE *engine,
const std::string &private_key,
const std::string &message) {
178 if (key_type == KeyType::kED25519) {
179 return Crypto::ED25519Sign(boost::algorithm::unhex(private_key), message);
181 return Crypto::RSAPSSSign(engine, private_key, message);
184 std::string Crypto::ED25519Sign(
const std::string &private_key,
const std::string &message) {
185 std::array<unsigned char, crypto_sign_BYTES> sig{};
186 crypto_sign_detached(sig.data(),
nullptr,
reinterpret_cast<const unsigned char *
>(message.c_str()), message.size(),
187 reinterpret_cast<const unsigned char *
>(private_key.c_str()));
188 return std::string(reinterpret_cast<char *>(sig.data()), crypto_sign_BYTES);
191 bool Crypto::RSAPSSVerify(
const std::string &public_key,
const std::string &signature,
const std::string &message) {
192 StructGuard<RSA> rsa(
nullptr, RSA_free);
193 StructGuard<BIO> bio(BIO_new_mem_buf(const_cast<char *>(public_key.c_str()), static_cast<int>(public_key.size())),
197 if (PEM_read_bio_RSA_PUBKEY(bio.get(), &r,
nullptr,
nullptr) ==
nullptr) {
198 LOG_ERROR <<
"PEM_read_bio_RSA_PUBKEY failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
204 #if AKTUALIZR_OPENSSL_PRE_11 205 RSA_set_method(rsa.get(), RSA_PKCS1_SSLeay());
207 RSA_set_method(rsa.get(), RSA_PKCS1_OpenSSL());
210 const auto size =
static_cast<unsigned int>(RSA_size(rsa.get()));
211 boost::scoped_array<unsigned char> pDecrypted(
new unsigned char[size]);
216 RSA_public_decrypt(static_cast<int>(signature.size()), reinterpret_cast<const unsigned char *>(signature.c_str()),
217 pDecrypted.get(), rsa.get(), RSA_NO_PADDING);
219 LOG_ERROR <<
"RSA_public_decrypt failed with error " << ERR_error_string(ERR_get_error(),
nullptr);
223 std::string digest = Crypto::sha256digest(message);
226 status = RSA_verify_PKCS1_PSS(rsa.get(),
reinterpret_cast<const unsigned char *
>(digest.c_str()), EVP_sha256(),
227 pDecrypted.get(), -2 );
231 bool Crypto::ED25519Verify(
const std::string &public_key,
const std::string &signature,
const std::string &message) {
232 if (public_key.size() < crypto_sign_PUBLICKEYBYTES || signature.size() < crypto_sign_BYTES) {
235 return crypto_sign_verify_detached(reinterpret_cast<const unsigned char *>(signature.c_str()),
236 reinterpret_cast<const unsigned char *>(message.c_str()), message.size(),
237 reinterpret_cast<const unsigned char *
>(public_key.c_str())) == 0;
240 bool Crypto::parseP12(BIO *p12_bio,
const std::string &p12_password, std::string *out_pkey, std::string *out_cert,
241 std::string *out_ca) {
242 #if AKTUALIZR_OPENSSL_PRE_11 243 SSLeay_add_all_algorithms();
245 StructGuard<PKCS12> p12(d2i_PKCS12_bio(p12_bio,
nullptr), PKCS12_free);
246 if (p12 ==
nullptr) {
247 LOG_ERROR <<
"Could not read from " << p12_bio <<
" file pointer";
252 auto stackx509_free = [](STACK_OF(X509) * stack) {
253 sk_X509_pop_free(stack, X509_free);
256 StructGuard<EVP_PKEY> pkey(
nullptr, EVP_PKEY_free);
257 StructGuard<X509> x509_cert(
nullptr, X509_free);
258 StructGuard<STACK_OF(X509)> ca_certs(
nullptr, stackx509_free);
261 X509 *x509c =
nullptr;
262 STACK_OF(X509) *cacs =
nullptr;
263 if (PKCS12_parse(p12.get(), p12_password.c_str(), &pk, &x509c, &cacs) == 0) {
264 LOG_ERROR <<
"Could not parse file from " << p12_bio <<
" source pointer";
268 x509_cert.reset(x509c);
269 ca_certs.reset(cacs);
272 StructGuard<BIO> pkey_pem_sink(BIO_new(BIO_s_mem()), BIO_vfree);
273 if (pkey_pem_sink ==
nullptr) {
274 LOG_ERROR <<
"Could not open pkey buffer for writing";
277 PEM_write_bio_PrivateKey(pkey_pem_sink.get(), pkey.get(),
nullptr,
nullptr, 0,
nullptr,
nullptr);
280 auto pkey_len = BIO_get_mem_data(pkey_pem_sink.get(), &pkey_buf);
281 *out_pkey = std::string(pkey_buf, static_cast<size_t>(pkey_len));
285 StructGuard<BIO> cert_sink(BIO_new(BIO_s_mem()), BIO_vfree);
286 if (cert_sink ==
nullptr) {
287 LOG_ERROR <<
"Could not open certificate buffer for writing";
290 PEM_write_bio_X509(cert_sink.get(), x509_cert.get());
294 StructGuard<BIO> ca_sink(BIO_new(BIO_s_mem()), BIO_vfree);
295 if (ca_sink ==
nullptr) {
296 LOG_ERROR <<
"Could not open ca buffer for writing";
299 X509 *ca_cert =
nullptr;
300 for (
int i = 0; i < sk_X509_num(ca_certs.get()); i++) {
301 ca_cert = sk_X509_value(ca_certs.get(), i);
302 PEM_write_bio_X509(ca_sink.get(), ca_cert);
303 PEM_write_bio_X509(cert_sink.get(), ca_cert);
306 ca_len =
static_cast<size_t>(BIO_get_mem_data(ca_sink.get(), &ca_buf));
307 *out_ca = std::string(ca_buf, ca_len);
310 cert_len =
static_cast<size_t>(BIO_get_mem_data(cert_sink.get(), &cert_buf));
311 *out_cert = std::string(cert_buf, cert_len);
316 bool Crypto::extractSubjectCN(
const std::string &cert, std::string *cn) {
317 StructGuard<BIO> bio(BIO_new_mem_buf(const_cast<char *>(cert.c_str()), static_cast<int>(cert.size())), BIO_vfree);
318 StructGuard<X509> x(PEM_read_bio_X509(bio.get(),
nullptr,
nullptr,
nullptr), X509_free);
323 int len = X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName,
nullptr, 0);
327 boost::scoped_array<char> buf(
new char[len + 1]);
328 X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName, buf.get(), len + 1);
329 *cn = 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};
355 return {
nullptr, EVP_PKEY_free};
359 StructGuard<BIGNUM> bne(BN_new(), BN_free);
360 ret = BN_set_word(bne.get(), RSA_F4);
362 return {
nullptr, EVP_PKEY_free};
364 StructGuard<RSA> rsa(RSA_new(), RSA_free);
365 ret = RSA_generate_key_ex(rsa.get(), bits,
369 return {
nullptr, EVP_PKEY_free};
372 StructGuard<EVP_PKEY> pkey(EVP_PKEY_new(), EVP_PKEY_free);
374 EVP_PKEY_assign_RSA(pkey.get(), rsa.release());
388 StructGuard<EVP_PKEY> pkey = generateRSAKeyPairEVP(key_type);
389 if (pkey ==
nullptr) {
394 StructGuard<BIO> pubkey_sink(BIO_new(BIO_s_mem()), BIO_vfree);
395 if (pubkey_sink ==
nullptr) {
398 ret = PEM_write_bio_PUBKEY(pubkey_sink.get(), pkey.get());
402 auto pubkey_len = BIO_get_mem_data(pubkey_sink.get(), &pubkey_buf);
403 *public_key = std::string(pubkey_buf, static_cast<size_t>(pubkey_len));
406 StructGuard<BIO> privkey_sink(BIO_new(BIO_s_mem()), BIO_vfree);
407 if (privkey_sink ==
nullptr) {
411 ret = PEM_write_bio_RSAPrivateKey(privkey_sink.get(),
static_cast<RSA *
>(EVP_PKEY_get0(pkey.get())),
nullptr,
nullptr,
412 0,
nullptr,
nullptr);
417 auto privkey_len = BIO_get_mem_data(privkey_sink.get(), &privkey_buf);
418 *private_key = std::string(privkey_buf, static_cast<size_t>(privkey_len));
422 bool Crypto::generateEDKeyPair(std::string *public_key, std::string *private_key) {
423 std::array<unsigned char, crypto_sign_PUBLICKEYBYTES> pk{};
424 std::array<unsigned char, crypto_sign_SECRETKEYBYTES> sk{};
425 crypto_sign_keypair(pk.data(), sk.data());
426 *public_key = boost::algorithm::hex(std::string(reinterpret_cast<char *>(pk.data()), crypto_sign_PUBLICKEYBYTES));
428 *private_key = boost::algorithm::hex(std::string(reinterpret_cast<char *>(sk.data()), crypto_sign_SECRETKEYBYTES));
433 bool Crypto::generateKeyPair(KeyType key_type, std::string *public_key, std::string *private_key) {
434 if (key_type == KeyType::kED25519) {
435 return Crypto::generateEDKeyPair(public_key, private_key);
440 bool Crypto::IsRsaKeyType(KeyType type) {
442 case KeyType::kRSA2048:
443 case KeyType::kRSA3072:
444 case KeyType::kRSA4096:
450 KeyType Crypto::IdentifyRSAKeyType(
const std::string &public_key_pem) {
451 StructGuard<BIO> bufio(BIO_new_mem_buf(reinterpret_cast<const void *>(public_key_pem.c_str()),
452 static_cast<int>(public_key_pem.length())),
454 if (bufio.get() ==
nullptr) {
455 throw std::runtime_error(
"BIO_new_mem_buf failed");
457 StructGuard<::RSA> rsa(PEM_read_bio_RSA_PUBKEY(bufio.get(),
nullptr,
nullptr,
nullptr), RSA_free);
459 if (rsa.get() ==
nullptr) {
460 return KeyType::kUnknown;
463 int key_length = RSA_size(rsa.get()) * 8;
468 switch (key_length) {
470 return KeyType::kRSA2048;
472 return KeyType::kRSA3072;
474 return KeyType::kRSA4096;
476 LOG_WARNING <<
"Weird key length:" << key_length;
477 return KeyType::kUnknown;
481 MultiPartHasher::Ptr MultiPartHasher::create(Hash::Type hash_type) {
483 case Hash::Type::kSha256: {
484 return std::make_shared<MultiPartSHA256Hasher>();
486 case Hash::Type::kSha512: {
487 return std::make_shared<MultiPartSHA512Hasher>();
490 LOG_ERROR <<
"Unsupported type of hashing: " << Hash::TypeString(hash_type);
496 Hash Hash::generate(Type type,
const std::string &
data) {
500 case Type::kSha256: {
501 hash = boost::algorithm::hex(Crypto::sha256digest(data));
504 case Type::kSha512: {
505 hash = boost::algorithm::hex(Crypto::sha512digest(data));
509 throw std::invalid_argument(
"Unsupported hash type");
513 return Hash(type, hash);
516 Hash::Hash(
const std::string &type,
const std::string &hash) : hash_(boost::algorithm::to_upper_copy(hash)) {
517 if (type ==
"sha512") {
518 type_ = Hash::Type::kSha512;
519 }
else if (type ==
"sha256") {
520 type_ = Hash::Type::kSha256;
522 type_ = Hash::Type::kUnknownAlgorithm;
526 Hash::Hash(Type type,
const std::string &hash) : type_(type), hash_(boost::algorithm::to_upper_copy(hash)) {}
528 bool Hash::operator==(
const Hash &other)
const {
return type_ == other.type_ && hash_ == other.hash_; }
530 std::string Hash::TypeString(Type type) {
541 std::string Hash::TypeString()
const {
return TypeString(type_); }
543 Hash::Type Hash::type()
const {
return type_; }
545 std::ostream &operator<<(std::ostream &os,
const Hash &h) {
546 os <<
"Hash: " << h.hash_;
Json::Value ToUptane() const
Uptane Json representation of this public key.
bool VerifySignature(const std::string &signature, const std::string &message) const
Verify a signature using this public key.
The Hash class The hash of a file or Uptane metadata.
static bool generateRSAKeyPair(KeyType key_type, std::string *public_key, std::string *private_key)
Generate a RSA keypair.