问题
I'm running out of ideas as to why my sample code won't verify the given EC public key, signature and message. I've converted the signature to ASN.1 format which is 70 bytes and the public key is 64 bytes plus uncompressed byte (0x04). I've also tried converting the message to SHA256 hash but that didn't work as well.
The publicKey hex value is used to construct a ECPublicKey with prime256v1 curve. The signature is base64 decoded then formatted to ASN.1. I don't see what I could be doing wrong. I'm hopping someone can help or point me in the right direction. Thanks in advance!
@Grapes([
@Grab('org.bouncycastle:bcprov-jdk15on:1.56')
])
import java.security.Security
import java.nio.charset.StandardCharsets
import java.security.Signature
import org.bouncycastle.jce.provider.BouncyCastleProvider
import javax.xml.bind.DatatypeConverter
import java.security.KeyFactory
import java.security.spec.ECPoint
import java.security.spec.ECPublicKeySpec
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec
import org.bouncycastle.jce.spec.ECNamedCurveSpec
import org.bouncycastle.jce.ECNamedCurveTable
import org.bouncycastle.jce.ECPointUtil
import org.bouncycastle.jce.interfaces.ECPublicKey
class SignatureVerification {
public static void main(String[] args) {
println "Validating sig.."
// def message = "e602b20fb84e459fa0c004dc9ee7aeab"
// SHA256 value of random
def message = "BF9C28751070582E7AEDE5163B043A20D3D7798DBD4EDCF69C5F234271401203"
def pubKeyHex = "040418A90C4DCA3522967A7E59DD019C4A100CF732E462FDFF4E13DEA94BAC918FC8220181CD3224141DEDAE15828EAC4CB6FA6872A8063C93C0652C1446FAB31A"
def sigString = "rTc2W5CXSYWZbVRpB+nrj1/wcsEHd1mLcWIKpuzKXI4krZb9pYqzRS34uFa0pIFIrEyT75j+3Neq2iW6lBVZnw"
Security.insertProviderAt(new BouncyCastleProvider(), 1)
byte[] byteKey = DatatypeConverter.parseHexBinary(pubKeyHex)
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("prime256v1")
KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider())
ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN())
ECPoint point = ECPointUtil.decodePoint(params.getCurve(), byteKey)
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params)
ECPublicKey pk = (ECPublicKey) kf.generatePublic(pubKeySpec)
println pk.toString()
Signature sig = Signature.getInstance("SHA256withECDSA", new BouncyCastleProvider())
sig.initVerify(pk)
sig.update(DatatypeConverter.parseHexBinary(message))
byte[] decodedSig = Base64.decoder.decode(sigString)
boolean verify = sig.verify(getASN1FormatForSignature(decodedSig))
if (verify) {
println "Success!!"
} else {
println "Failed!!"
}
}
static byte[] getASN1FormatForSignature(byte[] sig) {
// Format: 0x30 0x44 0x02 0x20 (vr) 0x02 0x20 (vs)
// Where vr is the first 32 bytes, vs is the last 32 bytes of signature
ByteArrayOutputStream asn1Format = new ByteArrayOutputStream()
if (sig.length != 64) {
println "Decoded signature length is not 64 bytes $sig"
return asn1Format.toByteArray()
}
asn1Format.write(DatatypeConverter.parseHexBinary("30440220"))
asn1Format.write(sig, 0, 32)
asn1Format.write(DatatypeConverter.parseHexBinary("0220"))
asn1Format.write(sig, 32, 32)
return asn1Format.toByteArray()
}
}
来源:https://stackoverflow.com/questions/45428339/cant-get-ecdsa-signature-to-validate-with-public-key