I tried to recover public key from P256 signature. With 2 recovery id ( 0, 1 ), signature makes 2 public key. And I tried to verify signature with public key and verification was succeed all of 2 keys.
Isn’t it correct that only one of the two should succeed? Or is there some cryptographic knowledge I don't know about? Is it correct that both public keys succeed? I attach the data I used below.
original public key
asn1 der (hex) : 3059301306072a8648ce3d020106082a8648ce3d03010703420004761c025b761d7a7c6d4bfd8d944975915e3d4879a2fead6e4417bdfe5de0ac36f5730e0e8082a3a964bd1e503236b1356f086b08dc39cc24288c6ef563917c53
---
x (hex) : 761c025b761d7a7c6d4bfd8d944975915e3d4879a2fead6e4417bdfe5de0ac36
y (hex) : f5730e0e8082a3a964bd1e503236b1356f086b08dc39cc24288c6ef563917c53
Signature
raw message (hex) : 49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763050000000047e4a6a9816d7dd36ad0772e8738f9423d147ebf0253cc91c5a0def297d0decb
sha256 hashed message ( for signature recovery ) (hex) : fdb2e37b8fdc643c1c94e1a1abd1876966e8f17a2d63dd2e4acb7be2e680751a
signature asn1 der (hex) : 3046022100cf4f49499b70e7fcc76193478fedcba4735456d9ca3b4fda3feafe2c16e35b6d022100cb30d5bbbb42eca0fb4dd8b056df2e058db0b8dc63e2f52d137cb580688f4063
- r (hex) : cf4f49499b70e7fcc76193478fedcba4735456d9ca3b4fda3feafe2c16e35b6d
- s (hex) : cb30d5bbbb42eca0fb4dd8b056df2e058db0b8dc63e2f52d137cb580688f4063
Recovered Public Key
recovered public key with recovery id 0
hex : 04260e3fa4c347cccdcc12e86e2f1a543f679648a31d0b26484da39f75b16b0be06d8f8231e1f819368c6c0dc52a9e62a3e90095478ead3ba4ee62e84e90182862
- x (hex) : 260e3fa4c347cccdcc12e86e2f1a543f679648a31d0b26484da39f75b16b0be0
- y (hex) : 6d8f8231e1f819368c6c0dc52a9e62a3e90095478ead3ba4ee62e84e90182862
recovered public key with recovery id 1
hex : 04761c025b761d7a7c6d4bfd8d944975915e3d4879a2fead6e4417bdfe5de0ac36f5730e0e8082a3a964bd1e503236b1356f086b08dc39cc24288c6ef563917c53
- x (hex) : 761c025b761d7a7c6d4bfd8d944975915e3d4879a2fead6e4417bdfe5de0ac36
- y (hex) : f5730e0e8082a3a964bd1e503236b1356f086b08dc39cc24288c6ef563917c53
and all of two keys succeed to verify above signature(3046022100cf4f4....
).
In order to extract the correct public key from the signature, I obtained the public key corresponding to all recovery IDs (0 to 3, a total of 4), and verified the signature with these public keys to find a successful public key. However, both public keys successfully verified their signatures. I'm curious about this.
Below is the code where I experimented with this process.
import {secp256r1} from '@noble/curves/p256'
import sha256 from 'sha256';
async function test2() {
let pub = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdhwCW3YdenxtS_2NlEl1kV49SHmi_q1uRBe9_l3grDb1cw4OgIKjqWS9HlAyNrE1bwhrCNw5zCQojG71Y5F8Uw'
let hexPub = Buffer.from(pub, 'base64').toString('hex')
console.log(hexPub)
const mayBeX = '761c025b761d7a7c6d4bfd8d944975915e3d4879a2fead6e4417bdfe5de0ac36' // i want find this public key from signature ( assume i dont know recovery id )
const mayBeY = 'f5730e0e8082a3a964bd1e503236b1356f086b08dc39cc24288c6ef563917c53' // i want find this public key from signature ( assume i dont know recovery id )
const testChallengeHex = '49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763050000000047e4a6a9816d7dd36ad0772e8738f9423d147ebf0253cc91c5a0def297d0decb'
const testHexSig = '3046022100cf4f49499b70e7fcc76193478fedcba4735456d9ca3b4fda3feafe2c16e35b6d022100cb30d5bbbb42eca0fb4dd8b056df2e058db0b8dc63e2f52d137cb580688f4063'
const msgHash = sha256(Buffer.from(testChallengeHex, 'hex'));
let sigObj = secp256r1.Signature.fromDER(testHexSig)
console.log('signature')
console.log(sigObj.r.toString(16))
console.log(sigObj.s.toString(16))
sigObj = sigObj.addRecoveryBit(0)
console.log(`msgHash`)
console.log(msgHash)
console.log('----------------')
const recovered = sigObj.recoverPublicKey(msgHash);
console.log(`recovered`)
console.log(recovered.toHex(false))
console.log(recovered.toAffine().x.toString(16))
console.log(recovered.toAffine().y.toString(16))
console.log('----------------')
const verified = secp256r1.verify(sigObj, msgHash, recovered.toHex(false))
console.log(verified)
}
test2().catch(console.log)
Thank you for your interest in my problem.