You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Investigation of the code in key.cpp has revealed a bug in the code that:
Makes it not possible to create uncompressed keys
Makes the conversion from compressed to uncompressed keys impossible
The issue is in the class CKey, which binds directly to OpenSSL for handling private keys.
First, we have to emphasize that a private key is just an integer while a public key is a point on the elliptic curve. The notion of a compressed private key only means that the corresponding public key is going to appear compressed. Following up from Bitcoin definition:
uncompressed: 0x80 + [32-byte secret] + [4 bytes of Hash() of previous 33 bytes], base58 encoded
compressed: 0x80 + [32-byte secret] + 0x01 + [4 bytes of Hash() previous 34 bytes], base58 encoded
neblio uses 0xb5 instead of 0x80
And we notice here there's compression is just a flag. The relation of this with the following issue is still unclear. OpenSSL seems to privde a way to use a key as compressed/uncompressed EC_KEY_set_conv_form. We should mention that Bitcoin Core doesn't use this method anymore.
Taking a look at the method that creates a new key and the method that does the conversion in the current state:
void CKey::MakeNewKey(bool fCompressed)
{
if (!EC_KEY_generate_key(pkey))
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
if (fCompressed)
SetCompressedPubKey();
fSet = true;
}
The interface of MakeNewKey() looks correct as it takes a boolean that decides whether the key is compressed or not. First observation is that this boolean is not passed to SetCompressedKey, which makes it always take the default value true. Second observation is that SetCompressedKey seems to ignore the parameter fCompressed when setting the member variable fCompressedPubKey. Finally, all this works because no call in the whole code is made with SetCompressedPubKey(false), except in script.cpp, which in turn is not used anywhere.
Investigation of the code in
key.cpp
has revealed a bug in the code that:The issue is in the class
CKey
, which binds directly to OpenSSL for handling private keys.First, we have to emphasize that a private key is just an integer while a public key is a point on the elliptic curve. The notion of a compressed private key only means that the corresponding public key is going to appear compressed. Following up from Bitcoin definition:
uncompressed: 0x80 + [32-byte secret] + [4 bytes of Hash() of previous 33 bytes], base58 encoded
compressed: 0x80 + [32-byte secret] + 0x01 + [4 bytes of Hash() previous 34 bytes], base58 encoded
neblio uses 0xb5 instead of 0x80
And we notice here there's compression is just a flag. The relation of this with the following issue is still unclear. OpenSSL seems to privde a way to use a key as compressed/uncompressed
EC_KEY_set_conv_form
. We should mention that Bitcoin Core doesn't use this method anymore.Taking a look at the method that creates a new key and the method that does the conversion in the current state:
The interface of
MakeNewKey()
looks correct as it takes a boolean that decides whether the key is compressed or not. First observation is that this boolean is not passed toSetCompressedKey
, which makes it always take the default valuetrue
. Second observation is thatSetCompressedKey
seems to ignore the parameterfCompressed
when setting the member variablefCompressedPubKey
. Finally, all this works because no call in the whole code is made withSetCompressedPubKey(false)
, except inscript.cpp
, which in turn is not used anywhere.Related:
https://en.bitcoin.it/wiki/List_of_address_prefixes
https://en.bitcoin.it/wiki/Wallet_import_format
https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_set_conv_form.html
https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_new.html
The text was updated successfully, but these errors were encountered: