带有HSM的ECDSA标志并在Java / Kotlin中进行验证

问题描述 投票:1回答:1

我有一个公共密钥和一个使用CryptokiEx从HSM生成的签名,我需要用Java验证签名,但是这样做有些困难。

签名已在HSM中签名

byte[] signature = null;
LongRef signLen = new LongRef();

CryptokiEx.C_SignInit(hSession, signMech, hPrivateKey);

/* determine the length of the signature */
CryptokiEx.C_Sign(hSession, hash, hashLen, null, signLen);

signature = new byte[(int) signLen.value];

CryptokiEx.C_Sign(hSession, hash, hashLen, signature, signLen);

输出

public key: 030F92CF7082006E46ADBB7C51AD12435110595C59C45518E35C794AD6578D4FEE
private key: 00BF9044CED80C5E358F3673C998417A564E52B8837C21FD5DA6DFA8E506983B03
signature: 7531DDE88945CC2431F69C237B7A5A52D042E44CFBE9FF2AC8C821E6EC507EC0ABC6AD1909A7C571E1C504261AEE5B92B3061D9AD7F921738C79806584CFD358
message hash: 68656c6c6f20776f726c64

构建公钥

fun constructPublicKey(compressedPKStr: String) :ECPublicKey {
    var publicKeyStr = compressedToUncompressed(compressedPKStr).toHex()
    publicKeyStr = publicKeyStr.substring(2)
    val kf: KeyFactory = KeyFactory.getInstance("EC")
    val pubKeyX = publicKeyStr.substring(0, publicKeyStr.length / 2)
    val pubKeyY = publicKeyStr.substring(publicKeyStr.length / 2)
    val x: ByteArray = pubKeyX.hexToByteArray()
    val y: ByteArray = pubKeyY.hexToByteArray()
    val w = ECPoint(BigInteger(1, x), BigInteger(1, y))
    return kf.generatePublic(ECPublicKeySpec(w, ecParameterSpecForCurve("secp256k1"))) as ECPublicKey
}

@Throws(NoSuchAlgorithmException::class, InvalidParameterSpecException::class)
fun ecParameterSpecForCurve(curveName: String?): ECParameterSpec {
    val params = AlgorithmParameters.getInstance("EC")
    params.init(ECGenParameterSpec(curveName))
    return params.getParameterSpec(ECParameterSpec::class.java)
}

fun compressedToUncompressed(compressedPKStr: String) :ByteArray {
    val compKey = compressedPKStr.hexToByteArray()
    var SPEC = ECNamedCurveTable.getParameterSpec("secp256k1")
    val point = SPEC.curve.decodePoint(compKey)
    val x: ByteArray = point.xCoord.encoded
    val y: ByteArray = point.yCoord.encoded
    // concat 0x04, x, and y, make sure x and y has 32-bytes:
    // 0x04 to indicate uncompressed PK
    return concat(byteArrayOf(0x04), x, y)
}

签名已转换为ASN.1 DER格式

@Throws(NumberFormatException::class)
fun byteToBin(byte: Byte): String {
    val number = java.lang.Byte.toUnsignedInt(byte)
    val s2 = String.format("%8s", Integer.toBinaryString(number)).replace(' ', '0')
    return s2
}

fun constructSignature(signatureStr: String) :ByteArray {
    val signatureR = signatureStr.substring(0, signatureStr.length / 2)
    val signatureS = signatureStr.substring(signatureStr.length / 2)
    var signatureRData = signatureR.hexToByteArray()
    val firstRByteBin = byteToBin(signatureRData[0])
    if (firstRByteBin.first() == '1') {
        signatureRData = concat(byteArrayOf(0x00), signatureRData)
    }
    var signatureSData = signatureS.hexToByteArray()
    val firstSByteBin = byteToBin(signatureSData[0])
    if (firstSByteBin.first() == '1') {
        signatureSData = concat(byteArrayOf(0x00), signatureSData)
    }
    val b2 = signatureRData.size
    val b3 = signatureSData.size
    val b1 = b2 + b3 + 4
    return concat(byteArrayOf(0x30, b1.toByte(), 0x02, b2.toByte()), signatureRData, byteArrayOf(0x02, b3.toByte()), signatureSData)
}

验证签名,但结果为假

val testBytes = "68656c6c6f20776f726c64".hexToByteArray()

val publicKeyStr = "030F92CF7082006E46ADBB7C51AD12435110595C59C45518E35C794AD6578D4FEE"
val publicKey = constructPublicKey(publicKeyStr)

val signatureStr = "7531DDE88945CC2431F69C237B7A5A52D042E44CFBE9FF2AC8C821E6EC507EC0ABC6AD1909A7C571E1C504261AEE5B92B3061D9AD7F921738C79806584CFD358"
val signatureData = constructSignature(signatureStr)

val signature: Signature = Signature.getInstance("SHA256withECDSA")

signature.initVerify(publicKey)

signature.update(testBytes)

signature.verify(signatureData)

你知道我错了吗?

java kotlin signature public-key ecdsa
1个回答
0
投票

我弄清楚哪里出了问题。签名前需要使用SHA256对消息进行散列]

MessageDigest digest = null;
try {
    digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
    System.out.println("Something is wrong");
}
byte[] hash = digest.digest(dataBytes);

CryptokiEx.C_Sign(hSession, hash, hashLen, signature, signLen);
© www.soinside.com 2019 - 2024. All rights reserved.