gpt4 book ai didi

java - ECC 数字签名代码中的不稳定行为

转载 作者:行者123 更新时间:2023-11-30 06:13:34 25 4
gpt4 key购买 nike

我正在尝试使用 SECP-256K1(比特币的 ECC 曲线)对某些数据进行 SHA256withECDSA 签名,代码如下。这些代码并不总是能正常工作,有时可能会相当不稳定。

我需要帮助稳定下面的代码。

签名者端生成ECC key 对的代码:

AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
parameters.init(new ECGenParameterSpec("secp256k1"));
ECParameterSpec ecParameterSpec = parameters.getParameterSpec(ECParameterSpec.class);
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
keyGen.initialize(ecParameterSpec);
KeyPair ecKeyPair = keyGen.generateKeyPair();
ECPublicKey deviceEcPub = (ECPublicKey) ecKeyPair.getPublic();
ECPrivateKey deviceEcPriv = (ECPrivateKey) ecKeyPair.getPrivate();

将ECC公钥转换为04<Public X Axis><Public Y Axis>按照比特币公钥规范的格式:

int cursor = 0;
byte[] devicePubKey = new byte[65];
devicePubKey[cursor] = (byte) 0x04;
cursor++;
System.arraycopy(deviceEcPub.getW().getAffineX().toByteArray(), 0, devicePubKey, cursor, 32);
cursor += 32;
System.arraycopy(deviceEcPub.getW().getAffineY().toByteArray(), 0, devicePubKey, cursor, 32);

在签名者端签署一些数据:

Signature sig = Signature.getInstance("SHA256withECDSA");
sig.initSign(deviceEcPriv);
sig.update(data, 0, data.length);
byte[] signature = sig.sign();

验证者端收到04<Public X Axis><Public Y Axis>编码公钥并将 X,Y 坐标转换为实际的 ECC 公钥以供使用:

byte[] x = new byte[32];
byte[] y = new byte[32];
// Skips the first byte containing the 0x04 byte and copies the rest
System.arraycopy(devicePubKey, 1, x, 0, 32);
System.arraycopy(devicePubKey, 33, y, 0, 32);

验证者使用 X 和 Y 坐标并重建 ECPublicKey:

AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
parameters.init(new ECGenParameterSpec("secp256k1"));
ECParameterSpec ecParameterSpec = parameters.getParameterSpec(ECParameterSpec.class);
ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(x), new BigInteger(y)), ecParameterSpec);
ECPublicKey publicKey = (ECPublicKey) KeyFactory.getInstance("EC").generatePublic(ecPublicKeySpec);

验证者对提供的数据和签名执行验证:

Signature sig = Signature.getInstance("SHA256withECDSA");
sig.initVerify(publicKey);
sig.update(data, offset, length);
return sig.verify(signature);

验证结果有时是True有时False看似随机的事件。

我想对上述代码提出建议,以确保它没有不稳定的行为。

最佳答案

好的,我注意到如果第一个字节以 0x00 开头,则 X 或 Y 的长度将为 33 个字节,因此我无法正确复制 X 或 Y 字节。

为了缓解上述情况,其中 X 和 Y 中的一个或两个的第一个字节可以是 0x00,我将读取 X 和 Y 的第一个字节,如果第一个字节是 0x00,我将跳过复制第一个字节并读取尽可能多的字节,直到完全复制 X 和 Y 的每个 32 个字节。

在某些情况下,X 和/或 Y 可能会小于 32 字节(即只有 31 字节长)

另一种方法是测量长度。如果长度超过 32,则跳过字节直到最后 32 个字节。如果长度小于32,则复制字节并将0x00字节放在字节数组的前面。

下面的代码显示了我提取公共(public) X 和 Y 值的重新实现。

int cursor = 0;
int copy = 0;

// Get X
byte[] X = deviceEcPub.getW().getAffineX().toByteArray();

// Evaluate length
if (X.length > 32) {
copy = 1;
System.arraycopy(X, copy, devicePubKey, cursor, 32);
} else if (X.length < 32) {
System.arraycopy(X, copy, devicePubKey, cursor + (32 - X.length), X.length);
} else {
System.arraycopy(X, copy, devicePubKey, cursor, 32);
}

// Increment cursor
cursor += 32;

// Reset copy offset status
copy = 0;

// Get Y
byte[] Y = deviceEcPub.getW().getAffineY().toByteArray();

// Evaluate length
if (Y.length > 32) {
copy = 1;
System.arraycopy(Y, copy, devicePubKey, cursor, 32);
} else if (Y.length < 32) {
System.arraycopy(Y, copy, devicePubKey, cursor + (32 - Y.length), Y.length);
} else {
System.arraycopy(Y, copy, devicePubKey, cursor, 32);
}

结果是签名验证变得稳定。

关于java - ECC 数字签名代码中的不稳定行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49745269/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com