Skip to content

Commit eefb078

Browse files
committed
feat: privateEncoding work in KeyObjectData
1 parent 854282e commit eefb078

File tree

1 file changed

+51
-22
lines changed

1 file changed

+51
-22
lines changed

packages/react-native-quick-crypto/cpp/keys/KeyObjectData.cpp

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,39 @@
11
#include "KeyObjectData.hpp"
2+
#include "Utils.hpp"
3+
#include <optional>
24

35
namespace margelo {
46

7+
using namespace margelo::nitro::crypto;
8+
9+
ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig GetPrivateKeyEncodingConfig(
10+
KFormatType format,
11+
KeyEncoding type) {
12+
auto pk_format = static_cast<ncrypto::EVPKeyPointer::PKFormatType>(format);
13+
auto pk_type = static_cast<ncrypto::EVPKeyPointer::PKEncodingType>(type);
14+
15+
auto config = ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig(false, pk_format, pk_type);
16+
return config;
17+
}
18+
19+
KeyObjectData TryParsePrivateKey(std::shared_ptr<ArrayBuffer> key, std::optional<KFormatType> format,
20+
std::optional<KeyEncoding> type,
21+
const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase) {
22+
auto config = GetPrivateKeyEncodingConfig(format.value(), type.value());
23+
auto buffer = ncrypto::Buffer<const unsigned char>{key->data(), key->size()};
24+
auto res = ncrypto::EVPKeyPointer::TryParsePrivateKey(config, buffer);
25+
if (res) {
26+
return KeyObjectData::CreateAsymmetric(KeyType::PRIVATE,
27+
std::move(res.value));
28+
}
29+
30+
if (res.error.value() == ncrypto::EVPKeyPointer::PKParseError::NEED_PASSPHRASE) {
31+
throw std::runtime_error("Passphrase required for encrypted key");
32+
} else {
33+
throw std::runtime_error("Failed to read private key");
34+
}
35+
}
36+
537
KeyObjectData::KeyObjectData(std::nullptr_t)
638
: key_type_(KeyType::SECRET) {}
739

@@ -55,41 +87,38 @@ KeyObjectData KeyObjectData::GetPublicOrPrivateKey(std::shared_ptr<ArrayBuffer>
5587
if (format.has_value() && format.value() == KFormatType::PEM) {
5688
// For PEM, we can easily determine whether it is a public or private key
5789
// by looking for the respective PEM tags.
58-
auto res = EVPKeyPointer::TryParsePublicKeyPEM(key);
90+
auto config = GetPrivateKeyEncodingConfig(format.value(), type.value());
91+
auto buffer = ncrypto::Buffer<const unsigned char>{key->data(), key->size()};
92+
auto res = ncrypto::EVPKeyPointer::TryParsePublicKeyPEM(buffer);
5993
if (res) {
6094
return CreateAsymmetric(KeyType::PUBLIC, std::move(res.value));
6195
}
6296

63-
if (res.error.value() == EVPKeyPointer::PKParseError::NOT_RECOGNIZED) {
64-
return TryParsePrivateKey(key, format, type, passphrase);
97+
if (res.error.has_value() && res.error.value() == ncrypto::EVPKeyPointer::PKParseError::NOT_RECOGNIZED) {
98+
if (passphrase.has_value()) {
99+
auto& passphrase_ptr = passphrase.value();
100+
config.passphrase = std::make_optional(ncrypto::DataPointer(passphrase_ptr->data(), passphrase_ptr->size()));
101+
}
102+
103+
auto private_res = ncrypto::EVPKeyPointer::TryParsePrivateKey(config, buffer);
104+
if (private_res) {
105+
return CreateAsymmetric(KeyType::PRIVATE, std::move(private_res.value));
106+
}
107+
// TODO: Handle private key parsing errors
65108
}
66109
throw std::runtime_error("Failed to read asymmetric key");
67110
}
111+
112+
throw std::runtime_error("Unsupported key format for GetPublicOrPrivateKey. Only PEM is supported.");
68113
}
69114

70115
KeyObjectData KeyObjectData::GetPrivateKey(std::shared_ptr<ArrayBuffer> key, std::optional<KFormatType> format,
71116
std::optional<KeyEncoding> type,
72117
const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase,
73118
bool isPublic) {
74-
throw std::runtime_error("Not yet implemented");
75-
}
76-
77-
KeyObjectData TryParsePrivateKey(std::shared_ptr<ArrayBuffer> key, std::optional<KFormatType> format,
78-
std::optional<KeyEncoding> type,
79-
const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase) {
80-
auto res = EVPKeyPointer::TryParsePrivateKey(config, buffer);
81-
if (res) {
82-
return KeyObjectData::CreateAsymmetric(KeyType::kKeyTypePrivate,
83-
std::move(res.value));
84-
}
85-
86-
if (res.error.value() == EVPKeyPointer::PKParseError::NEED_PASSPHRASE) {
87-
THROW_ERR_MISSING_PASSPHRASE(env, "Passphrase required for encrypted key");
88-
} else {
89-
ThrowCryptoError(
90-
env, res.openssl_error.value_or(0), "Failed to read private key");
91-
}
92-
return {};
119+
// TODO: Node's KeyObjectData::GetPrivateKeyFromJs checks for key "IsString" or "IsAnyBufferSource"
120+
// We have converted key to an ArrayBuffer - not sure if that's correct
121+
return TryParsePrivateKey(key, format, type, passphrase);
93122
}
94123

95124
} // namespace margelo

0 commit comments

Comments
 (0)