为什么我的示例代码不会验证给定的EC公钥,签名和消息,我的想法已经不多了。我已将签名转换为ASN.1格式,该格式为70字节,公钥为64字节加上未压缩字节(0x04)。我也尝试将消息转换为SHA256哈希,但这并没有奏效。
publicKey十六进制值用于构造具有prime256v1曲线的ECPublicKey。签名是base64解码然后格式化为ASN.1。我看不出我做错了什么。我正在跳跃,有人可以帮助或指出我正确的方向。提前谢谢!
@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()
}
}