com.google.bitcoin.core
Class ECKey

java.lang.Object
  extended by com.google.bitcoin.core.ECKey
All Implemented Interfaces:
Serializable

public class ECKey
extends Object
implements Serializable

Represents an elliptic curve public and (optionally) private key, usable for digital signatures but not encryption. Creating a new ECKey with the empty constructor will generate a new random keypair. Other constructors can be used when you already have the public or private parts. If you create a key with only the public part, you can check signatures but not create them.

ECKey also provides access to Bitcoin-Qt compatible text message signing, as accessible via the UI or JSON-RPC. This is slightly different to signing raw bytes - if you want to sign your own data and it won't be exposed as text to people, you don't want to use this. If in doubt, ask on the mailing list.

The ECDSA algorithm supports key recovery in which a signature plus a couple of discriminator bits can be reversed to find the public key used to calculate it. This can be convenient when you have a message and a signature and want to find out who signed it, rather than requiring the user to provide the expected identity.

See Also:
Serialized Form

Nested Class Summary
static class ECKey.ECDSASignature
          Groups the two components that make up a signature, and provides a way to encode to DER form, which is how ECDSA signatures are represented when embedded in other data structures in the Bitcoin protocol.
 
Field Summary
static org.spongycastle.crypto.params.ECDomainParameters CURVE
          The parameters of the secp256k1 curve that Bitcoin uses.
static boolean FAKE_SIGNATURES
          If this global variable is set to true, sign() creates a dummy signature and verify() always returns true.
static BigInteger HALF_CURVE_ORDER
          Equal to CURVE.getN().shiftRight(1), used for canonicalising the S value of a signature.
 
Constructor Summary
ECKey()
          Generates an entirely new keypair.
ECKey(BigInteger privKey)
          Creates an ECKey given the private key only.
ECKey(BigInteger privKey, BigInteger pubKey)
          A constructor variant with BigInteger pubkey.
ECKey(BigInteger privKey, byte[] pubKey, boolean compressed)
          Creates an ECKey given either the private key only, the public key only, or both.
ECKey(byte[] privKeyBytes, byte[] pubKey)
          Creates an ECKey given only the private key bytes.
ECKey(EncryptedPrivateKey encryptedPrivateKey, byte[] pubKey, KeyCrypter keyCrypter)
          Create a new ECKey with an encrypted private key, a public key and a KeyCrypter.
 
Method Summary
 void clearPrivateKey()
          Clears all the ECKey private key contents from memory.
 ECKey decrypt(KeyCrypter keyCrypter, org.spongycastle.crypto.params.KeyParameter aesKey)
          Create a decrypted private key with the keyCrypter and AES key supplied.
 ECKey encrypt(KeyCrypter keyCrypter, org.spongycastle.crypto.params.KeyParameter aesKey)
          Create an encrypted private key with the keyCrypter and the AES key supplied.
static boolean encryptionIsReversible(ECKey originalKey, ECKey encryptedKey, KeyCrypter keyCrypter, org.spongycastle.crypto.params.KeyParameter aesKey)
          Check that it is possible to decrypt the key with the keyCrypter and that the original key is returned.
 boolean equals(Object o)
           
static ECKey fromASN1(byte[] asn1privkey)
          Construct an ECKey from an ASN.1 encoded private key.
 long getCreationTimeSeconds()
          Returns the creation time of this key or zero if the key was deserialized from a version that did not store that data.
 EncryptedPrivateKey getEncryptedPrivateKey()
           
 KeyCrypter getKeyCrypter()
           
 DumpedPrivateKey getPrivateKeyEncoded(NetworkParameters params)
          Exports the private key in the form used by the Satoshi client "dumpprivkey" and "importprivkey" commands.
 byte[] getPrivKeyBytes()
          Returns a 32 byte array containing the private key, or null if the key is encrypted or public only
 byte[] getPubKey()
          Gets the raw public key value.
 byte[] getPubKeyHash()
          Gets the hash160 form of the public key (as seen in addresses).
 int hashCode()
           
 boolean hasPrivKey()
           
 boolean isCompressed()
          Returns whether this key is using the compressed form or not.
 boolean isEncrypted()
          Indicates whether the private key is encrypted (true) or not (false).
 boolean isPubKeyCanonical()
          Returns true if this pubkey is canonical, i.e.
static boolean isPubKeyCanonical(byte[] pubkey)
          Returns true if the given pubkey is canonical, i.e.
 boolean isPubKeyOnly()
           
static byte[] publicKeyFromPrivate(BigInteger privKey, boolean compressed)
          Returns public key bytes from the given private key.
static ECKey recoverFromSignature(int recId, ECKey.ECDSASignature sig, Sha256Hash message, boolean compressed)
          Given the components of a signature and a selector value, recover and return the public key that generated the signature according to the algorithm in SEC1v2 section 4.1.6.
 void setCreationTimeSeconds(long newCreationTimeSeconds)
          Sets the creation time of this key.
 ECKey.ECDSASignature sign(Sha256Hash input)
          Signs the given hash and returns the R and S components as BigIntegers.
 ECKey.ECDSASignature sign(Sha256Hash input, org.spongycastle.crypto.params.KeyParameter aesKey)
          Signs the given hash and returns the R and S components as BigIntegers.
static ECKey signedMessageToKey(String message, String signatureBase64)
          Given an arbitrary piece of text and a Bitcoin-format message signature encoded in base64, returns an ECKey containing the public key that was used to sign it.
 String signMessage(String message)
          Signs a text message using the standard Bitcoin messaging signing format and returns the signature as a base64 encoded string.
 String signMessage(String message, org.spongycastle.crypto.params.KeyParameter aesKey)
          Signs a text message using the standard Bitcoin messaging signing format and returns the signature as a base64 encoded string.
 Address toAddress(NetworkParameters params)
          Returns the address that corresponds to the public part of this ECKey.
 byte[] toASN1()
          Output this ECKey as an ASN.1 encoded private key, as understood by OpenSSL or used by the BitCoin reference implementation in its wallet storage format.
 String toString()
           
 String toStringWithPrivate()
          Produce a string rendering of the ECKey INCLUDING the private key.
 boolean verify(byte[] data, byte[] signature)
          Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key.
static boolean verify(byte[] data, byte[] signature, byte[] pub)
          Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key.
static boolean verify(byte[] data, ECKey.ECDSASignature signature, byte[] pub)
          Verifies the given ECDSA signature against the message bytes using the public key bytes.
 boolean verify(Sha256Hash sigHash, ECKey.ECDSASignature signature)
          Verifies the given R/S pair (signature) against a hash using the public key.
 void verifyMessage(String message, String signatureBase64)
          Convenience wrapper around signedMessageToKey(String, String).
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

CURVE

public static final org.spongycastle.crypto.params.ECDomainParameters CURVE
The parameters of the secp256k1 curve that Bitcoin uses.


HALF_CURVE_ORDER

public static final BigInteger HALF_CURVE_ORDER
Equal to CURVE.getN().shiftRight(1), used for canonicalising the S value of a signature. If you aren't sure what this is about, you can ignore it.


FAKE_SIGNATURES

public static boolean FAKE_SIGNATURES
If this global variable is set to true, sign() creates a dummy signature and verify() always returns true. This is intended to help accelerate unit tests that do a lot of signing/verifying, which in the debugger can be painfully slow.

Constructor Detail

ECKey

public ECKey()
Generates an entirely new keypair. Point compression is used so the resulting public key will be 33 bytes (32 for the co-ordinate and 1 byte to represent the y bit).


ECKey

public ECKey(BigInteger privKey)
Creates an ECKey given the private key only. The public key is calculated from it (this is slow)


ECKey

public ECKey(BigInteger privKey,
             BigInteger pubKey)
A constructor variant with BigInteger pubkey. See ECKey(BigInteger, byte[]).


ECKey

public ECKey(@Nullable
             byte[] privKeyBytes,
             @Nullable
             byte[] pubKey)
Creates an ECKey given only the private key bytes. This is the same as using the BigInteger constructor, but is more convenient if you are importing a key from elsewhere. The public key will be automatically derived from the private key.


ECKey

public ECKey(@Nullable
             EncryptedPrivateKey encryptedPrivateKey,
             @Nullable
             byte[] pubKey,
             KeyCrypter keyCrypter)
Create a new ECKey with an encrypted private key, a public key and a KeyCrypter.

Parameters:
encryptedPrivateKey - The private key, encrypted,
pubKey - The keys public key
keyCrypter - The KeyCrypter that will be used, with an AES key, to encrypt and decrypt the private key

ECKey

public ECKey(@Nullable
             BigInteger privKey,
             @Nullable
             byte[] pubKey,
             boolean compressed)
Creates an ECKey given either the private key only, the public key only, or both. If only the private key is supplied, the public key will be calculated from it (this is slow). If both are supplied, it's assumed the public key already correctly matches the public key. If only the public key is supplied, this ECKey cannot be used for signing.

Parameters:
compressed - If set to true and pubKey is null, the derived public key will be in compressed form.
Method Detail

fromASN1

public static ECKey fromASN1(byte[] asn1privkey)
Construct an ECKey from an ASN.1 encoded private key. These are produced by OpenSSL and stored by the Bitcoin reference implementation in its wallet. Note that this is slow because it requires an EC point multiply.


isPubKeyOnly

public boolean isPubKeyOnly()

hasPrivKey

public boolean hasPrivKey()

toASN1

public byte[] toASN1()
Output this ECKey as an ASN.1 encoded private key, as understood by OpenSSL or used by the BitCoin reference implementation in its wallet storage format.


publicKeyFromPrivate

public static byte[] publicKeyFromPrivate(BigInteger privKey,
                                          boolean compressed)
Returns public key bytes from the given private key. To convert a byte array into a BigInteger, use new BigInteger(1, bytes);


getPubKeyHash

public byte[] getPubKeyHash()
Gets the hash160 form of the public key (as seen in addresses).


getPubKey

public byte[] getPubKey()
Gets the raw public key value. This appears in transaction scriptSigs. Note that this is not the same as the pubKeyHash/address.


isCompressed

public boolean isCompressed()
Returns whether this key is using the compressed form or not. Compressed pubkeys are only 33 bytes, not 64.


toString

public String toString()
Overrides:
toString in class Object

toStringWithPrivate

public String toStringWithPrivate()
Produce a string rendering of the ECKey INCLUDING the private key. Unless you absolutely need the private key it is better for security reasons to just use toString().


toAddress

public Address toAddress(NetworkParameters params)
Returns the address that corresponds to the public part of this ECKey. Note that an address is derived from the RIPEMD-160 hash of the public key and is not the public key itself (which is too large to be convenient).


clearPrivateKey

public void clearPrivateKey()
Clears all the ECKey private key contents from memory. WARNING - this method irreversibly deletes the private key information. It turns the ECKEy into a watch only key.


sign

public ECKey.ECDSASignature sign(Sha256Hash input)
                          throws KeyCrypterException
Signs the given hash and returns the R and S components as BigIntegers. In the Bitcoin protocol, they are usually encoded using DER format, so you want toASN1() instead. However sometimes the independent components can be useful, for instance, if you're doing to do further EC maths on them.

Throws:
KeyCrypterException - if this ECKey doesn't have a private part.

sign

public ECKey.ECDSASignature sign(Sha256Hash input,
                                 @Nullable
                                 org.spongycastle.crypto.params.KeyParameter aesKey)
                          throws KeyCrypterException
Signs the given hash and returns the R and S components as BigIntegers. In the Bitcoin protocol, they are usually encoded using DER format, so you want ECKey.ECDSASignature.encodeToDER() instead. However sometimes the independent components can be useful, for instance, if you're doing to do further EC maths on them.

Parameters:
aesKey - The AES key to use for decryption of the private key. If null then no decryption is required.
Throws:
KeyCrypterException - if this ECKey doesn't have a private part.

verify

public static boolean verify(byte[] data,
                             ECKey.ECDSASignature signature,
                             byte[] pub)

Verifies the given ECDSA signature against the message bytes using the public key bytes.

When using native ECDSA verification, data must be 32 bytes, and no element may be larger than 520 bytes.

Parameters:
data - Hash of the data to verify.
signature - ASN.1 encoded signature.
pub - The public key bytes to use.

verify

public static boolean verify(byte[] data,
                             byte[] signature,
                             byte[] pub)
Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key.

Parameters:
data - Hash of the data to verify.
signature - ASN.1 encoded signature.
pub - The public key bytes to use.

verify

public boolean verify(byte[] data,
                      byte[] signature)
Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key.

Parameters:
data - Hash of the data to verify.
signature - ASN.1 encoded signature.

verify

public boolean verify(Sha256Hash sigHash,
                      ECKey.ECDSASignature signature)
Verifies the given R/S pair (signature) against a hash using the public key.


isPubKeyCanonical

public boolean isPubKeyCanonical()
Returns true if this pubkey is canonical, i.e. the correct length taking into account compression.


isPubKeyCanonical

public static boolean isPubKeyCanonical(byte[] pubkey)
Returns true if the given pubkey is canonical, i.e. the correct length taking into account compression.


signMessage

public String signMessage(String message)
                   throws KeyCrypterException
Signs a text message using the standard Bitcoin messaging signing format and returns the signature as a base64 encoded string.

Throws:
IllegalStateException - if this ECKey does not have the private part.
KeyCrypterException - if this ECKey is encrypted and no AESKey is provided or it does not decrypt the ECKey.

signMessage

public String signMessage(String message,
                          @Nullable
                          org.spongycastle.crypto.params.KeyParameter aesKey)
                   throws KeyCrypterException
Signs a text message using the standard Bitcoin messaging signing format and returns the signature as a base64 encoded string.

Throws:
IllegalStateException - if this ECKey does not have the private part.
KeyCrypterException - if this ECKey is encrypted and no AESKey is provided or it does not decrypt the ECKey.

signedMessageToKey

public static ECKey signedMessageToKey(String message,
                                       String signatureBase64)
                                throws SignatureException
Given an arbitrary piece of text and a Bitcoin-format message signature encoded in base64, returns an ECKey containing the public key that was used to sign it. This can then be compared to the expected public key to determine if the signature was correct. These sorts of signatures are compatible with the Bitcoin-Qt/bitcoind format generated by signmessage/verifymessage RPCs and GUI menu options. They are intended for humans to verify their communications with each other, hence the base64 format and the fact that the input is text.

Parameters:
message - Some piece of human readable text.
signatureBase64 - The Bitcoin-format message signature in base64
Throws:
SignatureException - If the public key could not be recovered or if there was a signature format error.

verifyMessage

public void verifyMessage(String message,
                          String signatureBase64)
                   throws SignatureException
Convenience wrapper around signedMessageToKey(String, String). If the key derived from the signature is not the same as this one, throws a SignatureException.

Throws:
SignatureException

recoverFromSignature

@Nullable
public static ECKey recoverFromSignature(int recId,
                                                  ECKey.ECDSASignature sig,
                                                  Sha256Hash message,
                                                  boolean compressed)

Given the components of a signature and a selector value, recover and return the public key that generated the signature according to the algorithm in SEC1v2 section 4.1.6.

The recId is an index from 0 to 3 which indicates which of the 4 possible keys is the correct one. Because the key recovery operation yields multiple potential keys, the correct key must either be stored alongside the signature, or you must be willing to try each recId in turn until you find one that outputs the key you are expecting.

If this method returns null it means recovery was not possible and recId should be iterated.

Given the above two points, a correct usage of this method is inside a for loop from 0 to 3, and if the output is null OR a key that is not the one you expect, you try again with the next recId.

Parameters:
recId - Which possible key to recover.
sig - the R and S components of the signature, wrapped.
message - Hash of the data that was signed.
compressed - Whether or not the original pubkey was compressed.
Returns:
An ECKey containing only the public part, or null if recovery wasn't possible.

getPrivKeyBytes

@Nullable
public byte[] getPrivKeyBytes()
Returns a 32 byte array containing the private key, or null if the key is encrypted or public only


getPrivateKeyEncoded

public DumpedPrivateKey getPrivateKeyEncoded(NetworkParameters params)
Exports the private key in the form used by the Satoshi client "dumpprivkey" and "importprivkey" commands. Use the VersionedChecksummedBytes.toString() method to get the string.

Parameters:
params - The network this key is intended for use on.
Returns:
Private key bytes as a DumpedPrivateKey.
Throws:
IllegalStateException - if the private key is not available.

getCreationTimeSeconds

public long getCreationTimeSeconds()
Returns the creation time of this key or zero if the key was deserialized from a version that did not store that data.


setCreationTimeSeconds

public void setCreationTimeSeconds(long newCreationTimeSeconds)
Sets the creation time of this key. Zero is a convention to mean "unavailable". This method can be useful when you have a raw key you are importing from somewhere else.


equals

public boolean equals(Object o)
Overrides:
equals in class Object

hashCode

public int hashCode()
Overrides:
hashCode in class Object

encrypt

public ECKey encrypt(KeyCrypter keyCrypter,
                     org.spongycastle.crypto.params.KeyParameter aesKey)
              throws KeyCrypterException
Create an encrypted private key with the keyCrypter and the AES key supplied. This method returns a new encrypted key and leaves the original unchanged. To be secure you need to clear the original, unencrypted private key bytes.

Parameters:
keyCrypter - The keyCrypter that specifies exactly how the encrypted bytes are created.
aesKey - The KeyParameter with the AES encryption key (usually constructed with keyCrypter#deriveKey and cached as it is slow to create).
Returns:
encryptedKey
Throws:
KeyCrypterException

decrypt

public ECKey decrypt(KeyCrypter keyCrypter,
                     org.spongycastle.crypto.params.KeyParameter aesKey)
              throws KeyCrypterException
Create a decrypted private key with the keyCrypter and AES key supplied. Note that if the aesKey is wrong, this has some chance of throwing KeyCrypterException due to the corrupted padding that will result, but it can also just yield a garbage key.

Parameters:
keyCrypter - The keyCrypter that specifies exactly how the decrypted bytes are created.
aesKey - The KeyParameter with the AES encryption key (usually constructed with keyCrypter#deriveKey and cached).
Returns:
unencryptedKey
Throws:
KeyCrypterException

encryptionIsReversible

public static boolean encryptionIsReversible(ECKey originalKey,
                                             ECKey encryptedKey,
                                             KeyCrypter keyCrypter,
                                             org.spongycastle.crypto.params.KeyParameter aesKey)
Check that it is possible to decrypt the key with the keyCrypter and that the original key is returned. Because it is a critical failure if the private keys cannot be decrypted successfully (resulting of loss of all bitcoins controlled by the private key) you can use this method to check when you *encrypt* a wallet that it can definitely be decrypted successfully. See Wallet.encrypt(KeyCrypter keyCrypter, KeyParameter aesKey) for example usage.

Returns:
true if the encrypted key can be decrypted back to the original key successfully.

isEncrypted

public boolean isEncrypted()
Indicates whether the private key is encrypted (true) or not (false). A private key is deemed to be encrypted when there is both a KeyCrypter and the encryptedPrivateKey is non-zero.


getEncryptedPrivateKey

@Nullable
public EncryptedPrivateKey getEncryptedPrivateKey()
Returns:
The encryptedPrivateKey (containing the encrypted private key bytes and initialisation vector) for this ECKey, or null if the ECKey is not encrypted.

getKeyCrypter

public KeyCrypter getKeyCrypter()
Returns:
The KeyCrypter that was used to encrypt to encrypt this ECKey. You need this to decrypt the ECKey.


Copyright © 2014. All rights reserved.