20

I could not find any library that, given an hex value, returns true if the given string is a valid ether private key.

Any hints?

3 Answers 3

19

As mentioned by Peter, a private key is a random 256 bit blob. It is a common oversight that there're no restrictions.

It has to be valid for the secp256k1 curve, which means two conditions:

  • cannot be zero
  • must be less than the order of the curve (called n and has a value of ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141)

In Javascript you can use ethereumjs-wallet to do this verification: Wallet.fromPrivateKey(<yourkey>) will throw an exception on an invalid input.

Alternatively you can also use the privateKeyVerify() method from the underlying library secp256k1 or do it manually with the big number library of your choice.

4

You can also use ethers to check. Like this:

const ethers = require('ethers')

var pk = '0xcaed41dd92c1548cf7536c290e6a1871757fb5fea5721dea3a08c6d4abcd16cf'
let w = new ethers.Wallet(pk)

// Shorter than 32 bytes
pk = '0xcaed41dd92c1548cf7536c290e6a1871757fb5fea5721dea3a08c6d4abcd16'
w = new ethers.Wallet(pk)

// Incorrect hexidecimal string. Change last f to g. G is not hex 
pk = '0xcaed41dd92c1548cf7536c290e6a1871757fb5fea5721dea3a08c6d4abcd16cg'
w = new ethers.Wallet(pk)

The first case is ok and will succeed.

The second one will throw an error

  reason: 'exactly 32 bytes required',
  code: 'INVALID_ARGUMENT',

The third one will also throw an error:

  reason: 'invalid hexidecimal string',
  code: 'INVALID_ARGUMENT',

You can catch this error to validate your privateKey

pk = '0xcaed41dd92c1548cf7536c290e6a1871757fb5fea5721dea3a08c6d4abcd16cg'
try {
    w = new ethers.Wallet(pk)
}
catch (e) {
    console.log('Invalid private key.')
}
3

important: this answer refers to the public address, not private key, see comments.

Every hex string is a valid Ethereum address.

Currently there are no address checksums implemented, so all the 0x<40 hex digits here> are valid. We are considering adding basic ICAP in Geth 1.4.1 or Geth 1.5 to allow inserting additional information into an address that would prevent mistyping them, but until then as long as it's 40 hex characters, it's valid.

3
  • 1
    From your response it seems like you are talking about public addresses. Private keys seems to be 64 in length. Am I misreading it?
    – Advanced
    Commented Mar 3, 2016 at 15:22
  • 1
    Ah, indeed you are right, I missed the private part. Still, the answer is more or less the same. The raw private key is a simple 256 bit random binary blob. So if you want to validate the raw keys, everything is valid. However sending around the raw keys is extremely dangerous, so people tend to create key files and use those to transport the encrypted keys. The spec for that is in github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition . However to fully validate the content of the file you'd need the password to decrypt it + a client than can handle it. What's your use case? Commented Mar 4, 2016 at 8:50
  • Oki, maybe edit your reply so I can upvote. My usecase: scan a QR, return true if its a valid private key for ethereum. For unencrypted keys I achieved it with ` var patt = new RegExp(/^[a-f0-9]{64}$/i); var res = patt.test(privateKey);` For encrypted keys, well, depends on how they are encrypted. I asked also myetherwallet.com guys. What do you suggest? Is there a regex to detect it?
    – Advanced
    Commented Mar 4, 2016 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.