无法使用公钥验证ECDSA签名

时间:2017-08-01 03:10:49

标签: groovy cryptography digital-signature bouncycastle ecdsa

为什么我的示例代码不会验证给定的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()
}

}

0 个答案:

没有答案