Skip to content
This repository was archived by the owner on Oct 28, 2021. It is now read-only.

Commit 65f752e

Browse files
authored
Merge pull request #5535 from ethereum/compressed-public-key
Converting private key to compressed public key
2 parents e81961f + 310d885 commit 65f752e

File tree

3 files changed

+44
-13
lines changed

3 files changed

+44
-13
lines changed

libdevcrypto/Common.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ secp256k1_context const* getCtx()
5252
return s_ctx.get();
5353
}
5454

55+
template <std::size_t KeySize>
56+
bool toPublicKey(Secret const& _secret, unsigned _flags, array<byte, KeySize>& o_serializedPubkey)
57+
{
58+
auto* ctx = getCtx();
59+
secp256k1_pubkey rawPubkey;
60+
// Creation will fail if the secret key is invalid.
61+
if (!secp256k1_ec_pubkey_create(ctx, &rawPubkey, _secret.data()))
62+
return false;
63+
size_t serializedPubkeySize = o_serializedPubkey.size();
64+
secp256k1_ec_pubkey_serialize(
65+
ctx, o_serializedPubkey.data(), &serializedPubkeySize, &rawPubkey, _flags);
66+
assert(serializedPubkeySize == o_serializedPubkey.size());
67+
return true;
68+
}
5569
}
5670

5771
bool dev::SignatureStruct::isValid() const noexcept
@@ -64,24 +78,29 @@ bool dev::SignatureStruct::isValid() const noexcept
6478

6579
Public dev::toPublic(Secret const& _secret)
6680
{
67-
auto* ctx = getCtx();
68-
secp256k1_pubkey rawPubkey;
69-
// Creation will fail if the secret key is invalid.
70-
if (!secp256k1_ec_pubkey_create(ctx, &rawPubkey, _secret.data()))
71-
return {};
7281
std::array<byte, 65> serializedPubkey;
73-
size_t serializedPubkeySize = serializedPubkey.size();
74-
secp256k1_ec_pubkey_serialize(
75-
ctx, serializedPubkey.data(), &serializedPubkeySize,
76-
&rawPubkey, SECP256K1_EC_UNCOMPRESSED
77-
);
78-
assert(serializedPubkeySize == serializedPubkey.size());
82+
if (!toPublicKey(_secret, SECP256K1_EC_UNCOMPRESSED, serializedPubkey))
83+
return {};
84+
7985
// Expect single byte header of value 0x04 -- uncompressed public key.
8086
assert(serializedPubkey[0] == 0x04);
87+
8188
// Create the Public skipping the header.
8289
return Public{&serializedPubkey[1], Public::ConstructFromPointer};
8390
}
8491

92+
PublicCompressed dev::toPublicCompressed(Secret const& _secret)
93+
{
94+
PublicCompressed serializedPubkey;
95+
if (!toPublicKey(_secret, SECP256K1_EC_COMPRESSED, serializedPubkey.asArray()))
96+
return {};
97+
98+
// Expect single byte header of value 0x02 or 0x03 -- compressed public key.
99+
assert(serializedPubkey[0] == 0x02 || serializedPubkey[0] == 0x03);
100+
101+
return serializedPubkey;
102+
}
103+
85104
Address dev::toAddress(Public const& _public)
86105
{
87106
return right160(sha3(_public.ref()));

libdevcrypto/Common.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ using Secret = SecureFixedHash<32>;
3939
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
4040
using Public = h512;
4141

42+
/// A public key in compressed format: 33 bytes.
43+
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
44+
using PublicCompressed = FixedHash<33>;
45+
4246
/// A signature: 65 bytes: r: [0, 32), s: [32, 64), v: 64.
4347
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
4448
using Signature = h520;
@@ -64,6 +68,9 @@ using Secrets = std::vector<Secret>;
6468
/// Convert a secret key into the public key equivalent.
6569
Public toPublic(Secret const& _secret);
6670

71+
/// Convert a secret key into the public key in compressed format.
72+
PublicCompressed toPublicCompressed(Secret const& _secret);
73+
6774
/// Convert a public key to address.
6875
Address toAddress(Public const& _public);
6976

test/unittests/libdevcrypto/crypto.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,13 @@ BOOST_AUTO_TEST_CASE(keypairs)
111111
KeyPair p(Secret(fromHex("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4")));
112112
BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f")));
113113
BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075")));
114-
eth::Transaction t(1000, 0, 0, h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")), {}, 0, p.secret());
115-
auto rlp = t.rlp(eth::WithoutSignature);
114+
BOOST_REQUIRE(toPublicCompressed(p.secret()) ==
115+
PublicCompressed(fromHex(
116+
"0397466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce7")));
117+
118+
eth::Transaction t(
119+
1000, 0, 0, h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")), {}, 0, p.secret());
120+
auto rlp = t.rlp(eth::WithoutSignature);
116121
auto expectedRlp = "dc80808094944400f4b88ac9589a0f17ed4671da26bddb668b8203e880";
117122
BOOST_CHECK_EQUAL(toHex(rlp), expectedRlp);
118123
rlp = t.rlp(eth::WithSignature);

0 commit comments

Comments
 (0)