Is the following a valid bitcoin private key? - FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE

1

1

In secp256k1 (Bitcoin's elliptic curve) it is defined that valid private keys may range from 1 to FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 - 1. (https://crypto.stackexchange.com/questions/30269/are-all-possible-ec-private-keys-valid)

However I created an EC Keypair with the private key being FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE imported it into bitcoin core and sent a small amount of btc to the corresponding bitcoin address. I was able to spend these coins. Does that mean that bitcoin does not follow this restriction and any combination of 256 bits is a valid private key for bitcoin? Or might it be a bug that could get fixed in future?

I'm currently myself deriving bitcoin private keys/addresses from a seed and importing them via json-rpc. I saw that implementations of e.g. BouncyCastle check whether an EC is in that forbidden range. I currently don't do that but I also think that even if bitcoin wouldn't accept such keys the probability of deriving a private key in that forbidden range is too low to justify the additional implementation complexity (at least in my case). Is that problematic?

Update - Here's how I created the private key:

byte[] privKeyBytes = {1,1,1,1,1,1,1,1,...,1,1,1,0};
byte[] version = { (byte) 128 }
byte[] privateBytesPlusVersion = MyUtils.concatenateByteArrays(version, privKeyBytes);
byte[] versionPrivateAndCompressed = MyUtils.concatenateByteArrays(privateBytesPlusVersion,
            COMPRESS_BYTE);
byte[] checksum = getChecksum(versionPrivateAndCompressed);
byte[] versionPrivateCompressedAndChecksum = MyUtils.concatenateByteArrays(versionPrivateAndCompressed,
            checksum);
String privKeyDump = Base58.encode(versionPrivateCompressedAndChecksum);

The Base58 class is from BitcoinJ. I then imported this string via json-rpc with importprivkey

Update2 - As Pieter Wuille pointed out I had an error as privKeyBytes {1,1,1,...,1} is not 'FFFFF...FFF'. I tried to import such a private key again and bitcoins rpc interface answered with an error: "Private key outside allowed range". I'm still tempted to not check for this range as the probability of me generating something with 120 1 bits at the beginning seems low enough to discard that case.

tobi

Posted 2017-06-09T16:01:43.570

Reputation: 138

1How did you create and import that private key?Pieter Wuille 2017-06-09T17:31:08.427

Thing is the way it was imported may have considered it a little endian 256 bit number, that would lead to FEFFFFFF .... which is lower than the maximum.Gopoi 2017-06-09T17:47:32.243

@PieterWuille I updated my question with information about how I created/imported the private keytobi 2017-06-09T21:14:53.070

@Gopoi I see, but I think I also tried it with all FFFFs and it works. Will try it again tomorrowtobi 2017-06-09T21:16:01.297

2Shouldn't privkeybytes be {255,255,255,...}?Pieter Wuille 2017-06-09T22:30:44.697

@PieterWuille: Java byte is signed (two's-complement), so 255 is not permitted; -1 is, and (byte)255 is the same as -1 but in this context clearer. It is treated as unsigned in some contexts, including bitcoin and crypto, by masking with &0xFF.dave_thompson_085 2017-06-09T23:31:08.990

why not to use byte[] privKeyBytes ={0xFF,0xFF,0xFF,0xFF,....,0x00}Badr Bellaj 2017-06-09T23:32:28.337

The code you pasted is {1,1,1,1,...} not {-1,-1,-1,...}.Pieter Wuille 2017-06-10T00:00:27.673

Can you share the address you generated?Pieter Wuille 2017-06-10T00:00:40.613

@PieterWuille you're totally right and I'm quite sure I did not use {1,1,1,..,1} It was just temporary test code that I don't have anymore so I recalled from my memory. I'll right now play it through again and update my posttobi 2017-06-10T12:21:03.717

@PieterWuille alright, I tried it again and this time bitcoind answered with "Private key outside allowed range". So probably I also did that wrong the first time I tried it. Do you see a problem with me still not checking that case? When I maybe generate a couple thousand private keys a day it seems not really realistic to generate one with FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFF at the beginningtobi 2017-06-10T14:13:10.360

well.. I'm checking the range now anyway.tobi 2017-06-10T15:34:43.783

Accidentally hitting one of those numbers outside of the range is about as hard as solving the ECDLP problem (what you'd need to do if you wanted to steal coins with just the public key). That's only the case for secp256k1; other curves may have a ln order that's far further from a power of 2.Pieter Wuille 2017-06-11T17:13:15.980

Answers

1

since the group is cyclic with order N, then this key will be equal to 0x14551231950b75fc4402da1732fc9bebd (your key modulo N)

>>> hex(N)
'0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
>>> y=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
>>> multiply(y)
(101611976893179986611445456504760352678020054910766426941542489291446644113297, 62728409327141118228093362610154100530630533850909349244575637074165425046447)
>>> y%N
432420386565659656852420866394968145597
>>> multiply(y%N)
(101611976893179986611445456504760352678020054910766426941542489291446644113297, 62728409327141118228093362610154100530630533850909349244575637074165425046447)
>>> hex(y%N)
'0x14551231950b75fc4402da1732fc9bebd'

vbujym

Posted 2017-06-09T16:01:43.570

Reputation: 11