Can't get ECDSA signature to validate with public key

∥☆過路亽.° 提交于 2020-01-24 22:12:29

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!