-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is it possible to generate an invalid PrivateKey when no secret it passed? #390
Comments
Hey @charlie632 👋 Are you referring to using If you have a specific example using a 32 byte key, we can create a unit test for this case. |
Hey @csjones! Yeah, If the
Here I created a small test scenario: func testPrivateKeyWithInvalidKey() throws {
let invalidPrivateKey = "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142"
let privKeyBytes = [UInt8](Data(hexadecimalString: invalidPrivateKey)!)
let context = secp256k1.Context.rawRepresentation
let isValid = secp256k1_ec_seckey_verify(context, privKeyBytes) > 0
XCTAssert(!isValid)
} If you change the priv key hex to -- extension Data {
init?(hexadecimalString: String) {
let cleanString: String
if hexadecimalString.hasPrefix("0x") {
cleanString = String(hexadecimalString.dropFirst(2))
} else {
cleanString = hexadecimalString
}
guard cleanString.count % 2 == 0 else { return nil }
var bytes = [UInt8]()
var startIndex = cleanString.startIndex
while startIndex < cleanString.endIndex {
let endIndex = cleanString.index(startIndex, offsetBy: 2)
let hexSubstring = cleanString[startIndex..<endIndex]
if let byte = UInt8(hexSubstring, radix: 16) {
bytes.append(byte)
} else {
return nil
}
startIndex = endIndex
}
self.init(bytes: bytes)
}
} |
So, maybe in the initialization following the SecureBytes call, there could be a small check with a loop until it gets a valid sec_key |
It might be simpler if we tried testing like this: let privateBytes = try! "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142".bytes
XCTAssertThrowsError(try secp256k1.Signing.PrivateKey(dataRepresentation: privateBytes)) We can use |
yup, that is way simpler!. However, I think the issue still remains where if you don't pass a In my code, I did this just to be safe: while true {
guard let privateKey = try? secp256k1.Signing.PrivateKey() else {
continue
}
return privateKey
} Not sure if something like this can be implemented directly in the library |
I understand what you're saying now 😅 It makes sense to have the ability to constrain the entropy when using I'm not sure an infinite loop is the right solution for this package (but don't let me prevent you from using it in your package 😉 ) because it should be optimal and always provide a valid key in a single pass. Looking at I'll need to investigate this more but in the meantime share any ideas you might have because I would love to make the API closer to what Apple provides. |
After a little investigation, I learned that Apple implements looping logic on initialization similar to what you described. I take it back and now think we can explore this change further for the package 😁 |
Ohh, limiting the number of times it tries sounds like a good idea. Let me know if you need any help, I'm happy to help! |
Your help would be greatly appreciated! The first of the two functions could be changed to: @usableFromInline init(format: secp256k1.Format = .compressed) {
for _ in 0 ..< 10 {
let randomBytes = SecureBytes(count: secp256k1.ByteDetails.count)
if let privateKey = try? Self.PrivateKey(dataRepresentation: Data(randomBytes), format: format) {
self = privateKey
return
}
}
fatalError("Looped more than 10 times trying to generate a key")
} |
For creating a Key Agreement with Elliptic Curve Diffie Hellman, how can I use a base64 public key to obtain the sharedkey. Is it possible to do it? |
If I don't pass a secret to
secp256k1.Signing.PrivateKey
I get a random one. Checking the code to see its implementation, I see that it may be possible to generate an invalid key?https://github.com/GigaBitcoin/secp256k1.swift/blob/a69bc11b381207c1a774b8f1fb0de6e30c4f6490/Sources/zkp/secp256k1.swift#L154C1-L154C1
This will calculate a safe random number of 32 bytes, but I believe a couple of values may be invalid (see https://crypto.stackexchange.com/a/30272).
Not sure if down the line there are some checks to check the validity of this value or if when generating the PublicKey (in the same constructor) it will throw an error due to this reason.
The text was updated successfully, but these errors were encountered: