Commit 2a2e9467 authored by Alex Chau's avatar Alex Chau Committed by Commit Bot

Create ECPrivateKey from secret

- Derive ECPrivateKey from secret deterministically using
  EC_KEY_derive_from_secret
- Will be used for VapidKeyManager to generate a ECPrivateKey from
  256-bit secret from Chrome Sync, as illustrated in
  https://crrev.com/c/1848171

Bug: 1010968
Change-Id: Id2445ff802e9598ad3b454dc42972a6812713885
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1844961
Commit-Queue: Alex Chau <alexchau@chromium.org>
Reviewed-by: default avatarDavid Benjamin <davidben@chromium.org>
Reviewed-by: default avatarRichard Knoll <knollr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#705661}
parent 485a5f9a
...@@ -43,7 +43,7 @@ std::unique_ptr<ECPrivateKey> ECPrivateKey::Create() { ...@@ -43,7 +43,7 @@ std::unique_ptr<ECPrivateKey> ECPrivateKey::Create() {
// static // static
std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo( std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo(
const std::vector<uint8_t>& input) { base::span<const uint8_t> input) {
OpenSSLErrStackTracer err_tracer(FROM_HERE); OpenSSLErrStackTracer err_tracer(FROM_HERE);
CBS cbs; CBS cbs;
...@@ -59,7 +59,7 @@ std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo( ...@@ -59,7 +59,7 @@ std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo(
// static // static
std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
const std::vector<uint8_t>& encrypted_private_key_info) { base::span<const uint8_t> encrypted_private_key_info) {
OpenSSLErrStackTracer err_tracer(FROM_HERE); OpenSSLErrStackTracer err_tracer(FROM_HERE);
CBS cbs; CBS cbs;
...@@ -87,6 +87,28 @@ std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( ...@@ -87,6 +87,28 @@ std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
return result; return result;
} }
// static
std::unique_ptr<ECPrivateKey> ECPrivateKey::DeriveFromSecret(
base::span<const uint8_t> secret) {
bssl::UniquePtr<EC_GROUP> group(
EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
if (!group)
return nullptr;
bssl::UniquePtr<EC_KEY> ec_key(
EC_KEY_derive_from_secret(group.get(), secret.data(), secret.size()));
if (!ec_key)
return nullptr;
std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
result->key_.reset(EVP_PKEY_new());
if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_.get(), ec_key.get()))
return nullptr;
CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_id(result->key_.get()));
return result;
}
std::unique_ptr<ECPrivateKey> ECPrivateKey::Copy() const { std::unique_ptr<ECPrivateKey> ECPrivateKey::Copy() const {
std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey()); std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey());
copy->key_ = bssl::UpRef(key_); copy->key_ = bssl::UpRef(key_);
...@@ -135,7 +157,7 @@ bool ECPrivateKey::ExportEncryptedPrivateKey( ...@@ -135,7 +157,7 @@ bool ECPrivateKey::ExportEncryptedPrivateKey(
bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const { bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
OpenSSLErrStackTracer err_tracer(FROM_HERE); OpenSSLErrStackTracer err_tracer(FROM_HERE);
uint8_t *der; uint8_t* der;
size_t der_len; size_t der_len;
bssl::ScopedCBB cbb; bssl::ScopedCBB cbb;
if (!CBB_init(cbb.get(), 0) || if (!CBB_init(cbb.get(), 0) ||
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/containers/span.h"
#include "base/macros.h" #include "base/macros.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "crypto/crypto_export.h" #include "crypto/crypto_export.h"
...@@ -37,7 +38,7 @@ class CRYPTO_EXPORT ECPrivateKey { ...@@ -37,7 +38,7 @@ class CRYPTO_EXPORT ECPrivateKey {
// an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return
// nullptr if initialization fails. // nullptr if initialization fails.
static std::unique_ptr<ECPrivateKey> CreateFromPrivateKeyInfo( static std::unique_ptr<ECPrivateKey> CreateFromPrivateKeyInfo(
const std::vector<uint8_t>& input); base::span<const uint8_t> input);
// Creates a new instance by importing an existing key pair. // Creates a new instance by importing an existing key pair.
// The key pair is given as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo // The key pair is given as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo
...@@ -47,7 +48,13 @@ class CRYPTO_EXPORT ECPrivateKey { ...@@ -47,7 +48,13 @@ class CRYPTO_EXPORT ECPrivateKey {
// This function is deprecated. Use CreateFromPrivateKeyInfo for new code. // This function is deprecated. Use CreateFromPrivateKeyInfo for new code.
// See https://crbug.com/603319. // See https://crbug.com/603319.
static std::unique_ptr<ECPrivateKey> CreateFromEncryptedPrivateKeyInfo( static std::unique_ptr<ECPrivateKey> CreateFromEncryptedPrivateKeyInfo(
const std::vector<uint8_t>& encrypted_private_key_info); base::span<const uint8_t> encrypted_private_key_info);
// Creates a new instance by deriving private key from |secret|, and generates
// public key points accordingly. The created key will use the NIST P-256
// curve. This can return nullptr if initialization fails.
static std::unique_ptr<ECPrivateKey> DeriveFromSecret(
base::span<const uint8_t> secret);
// Returns a copy of the object. // Returns a copy of the object.
std::unique_ptr<ECPrivateKey> Copy() const; std::unique_ptr<ECPrivateKey> Copy() const;
...@@ -80,7 +87,6 @@ class CRYPTO_EXPORT ECPrivateKey { ...@@ -80,7 +87,6 @@ class CRYPTO_EXPORT ECPrivateKey {
DISALLOW_COPY_AND_ASSIGN(ECPrivateKey); DISALLOW_COPY_AND_ASSIGN(ECPrivateKey);
}; };
} // namespace crypto } // namespace crypto
#endif // CRYPTO_EC_PRIVATE_KEY_H_ #endif // CRYPTO_EC_PRIVATE_KEY_H_
...@@ -123,6 +123,70 @@ TEST(ECPrivateKeyUnitTest, CreateFromPrivateKeyInfo) { ...@@ -123,6 +123,70 @@ TEST(ECPrivateKeyUnitTest, CreateFromPrivateKeyInfo) {
raw_public_key); raw_public_key);
} }
TEST(ECPrivateKeyUnitTest, DeriveFromSecret) {
static const uint8_t kSecret[] = {
0x90, 0x48, 0x0a, 0x51, 0x77, 0xa3, 0x72, 0xfb, 0xba, 0x0f, 0x08,
0x5e, 0xc5, 0x6f, 0x8f, 0x6d, 0x1c, 0xaf, 0xa9, 0x8a, 0xdf, 0xa9,
0x7c, 0x38, 0x70, 0x47, 0xb9, 0x72, 0xcc, 0x5c, 0xaa, 0xc2,
};
static const uint8_t kPrivateKeyInfo[] = {
0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
0x0e, 0x87, 0xc8, 0x4d, 0x92, 0x14, 0x52, 0x93, 0x96, 0xad, 0x63, 0x9a,
0x6a, 0xa7, 0xeb, 0x56, 0x5c, 0xaf, 0xab, 0x69, 0x06, 0xd4, 0x37, 0xf8,
0x7d, 0xd7, 0x04, 0xa9, 0xec, 0x6e, 0x2e, 0x96, 0xa1, 0x44, 0x03, 0x42,
0x00, 0x04, 0xe2, 0xf5, 0x86, 0x4a, 0xf6, 0xe0, 0x7d, 0x19, 0x94, 0x2d,
0x54, 0x16, 0x58, 0x98, 0x62, 0x78, 0xf2, 0x8f, 0x30, 0x77, 0x93, 0x7d,
0x2c, 0x17, 0x29, 0xe5, 0x50, 0x42, 0xed, 0x8d, 0x6c, 0x31, 0x34, 0x16,
0x20, 0x4f, 0xcc, 0x50, 0x09, 0xaf, 0x8d, 0x56, 0x56, 0x73, 0xe3, 0xb9,
0x5a, 0x15, 0xbf, 0x73, 0x25, 0x91, 0xa0, 0xaf, 0x8f, 0x64, 0x19, 0xf4,
0x17, 0x8e, 0x7a, 0x05, 0x76, 0x23,
};
static const uint8_t kSubjectPublicKeyInfo[] = {
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00, 0x04, 0xe2, 0xf5, 0x86, 0x4a, 0xf6, 0xe0, 0x7d, 0x19, 0x94,
0x2d, 0x54, 0x16, 0x58, 0x98, 0x62, 0x78, 0xf2, 0x8f, 0x30, 0x77, 0x93,
0x7d, 0x2c, 0x17, 0x29, 0xe5, 0x50, 0x42, 0xed, 0x8d, 0x6c, 0x31, 0x34,
0x16, 0x20, 0x4f, 0xcc, 0x50, 0x09, 0xaf, 0x8d, 0x56, 0x56, 0x73, 0xe3,
0xb9, 0x5a, 0x15, 0xbf, 0x73, 0x25, 0x91, 0xa0, 0xaf, 0x8f, 0x64, 0x19,
0xf4, 0x17, 0x8e, 0x7a, 0x05, 0x76, 0x23,
};
static const uint8_t kRawPublicKey[] = {
0xe2, 0xf5, 0x86, 0x4a, 0xf6, 0xe0, 0x7d, 0x19, 0x94, 0x2d, 0x54,
0x16, 0x58, 0x98, 0x62, 0x78, 0xf2, 0x8f, 0x30, 0x77, 0x93, 0x7d,
0x2c, 0x17, 0x29, 0xe5, 0x50, 0x42, 0xed, 0x8d, 0x6c, 0x31, 0x34,
0x16, 0x20, 0x4f, 0xcc, 0x50, 0x09, 0xaf, 0x8d, 0x56, 0x56, 0x73,
0xe3, 0xb9, 0x5a, 0x15, 0xbf, 0x73, 0x25, 0x91, 0xa0, 0xaf, 0x8f,
0x64, 0x19, 0xf4, 0x17, 0x8e, 0x7a, 0x05, 0x76, 0x23,
};
std::unique_ptr<crypto::ECPrivateKey> key(
crypto::ECPrivateKey::DeriveFromSecret(kSecret));
ASSERT_TRUE(key);
std::vector<uint8_t> privkey;
EXPECT_TRUE(key->ExportPrivateKey(&privkey));
EXPECT_EQ(std::vector<uint8_t>(std::begin(kPrivateKeyInfo),
std::end(kPrivateKeyInfo)),
privkey);
std::vector<uint8_t> public_key;
ASSERT_TRUE(key->ExportPublicKey(&public_key));
EXPECT_EQ(std::vector<uint8_t>(std::begin(kSubjectPublicKeyInfo),
std::end(kSubjectPublicKeyInfo)),
public_key);
std::string raw_public_key;
ASSERT_TRUE(key->ExportRawPublicKey(&raw_public_key));
EXPECT_EQ(std::string(reinterpret_cast<const char*>(kRawPublicKey),
sizeof(kRawPublicKey)),
raw_public_key);
}
TEST(ECPrivateKeyUnitTest, RSAPrivateKeyInfo) { TEST(ECPrivateKeyUnitTest, RSAPrivateKeyInfo) {
static const uint8_t kPrivateKeyInfo[] = { static const uint8_t kPrivateKeyInfo[] = {
0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment