gpt4 book ai didi

ECC 公钥的 Java 紧凑表示

转载 作者:搜寻专家 更新时间:2023-11-01 01:25:55 25 4
gpt4 key购买 nike

java.security.PublicKey#getEncoded() 返回 key 的 X509 表示,与原始 ECC 值相比,在 ECC 的情况下增加了大量开销。

我希望能够以最紧凑的表示形式(即尽可能小的字节 block )将 PublicKey 转换为字节数组(反之亦然)。

key 类型(ECC)和具体的曲线类型是预先知道的,因此不需要对它们的信息进行编码。

解决方案可以使用 Java API、BouncyCaSTLe 或任何其他自定义代码/库(只要许可证不暗示需要开源将使用它的专有代码)。

最佳答案

此功能也存在于 Bouncy CaSTLe 中,但我将展示如何仅使用 Java 完成此功能,以防有人需要它:

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.util.Arrays;

public class Curvy {

private static final byte UNCOMPRESSED_POINT_INDICATOR = 0x04;

public static ECPublicKey fromUncompressedPoint(
final byte[] uncompressedPoint, final ECParameterSpec params)
throws Exception {

int offset = 0;
if (uncompressedPoint[offset++] != UNCOMPRESSED_POINT_INDICATOR) {
throw new IllegalArgumentException(
"Invalid uncompressedPoint encoding, no uncompressed point indicator");
}

int keySizeBytes = (params.getOrder().bitLength() + Byte.SIZE - 1)
/ Byte.SIZE;

if (uncompressedPoint.length != 1 + 2 * keySizeBytes) {
throw new IllegalArgumentException(
"Invalid uncompressedPoint encoding, not the correct size");
}

final BigInteger x = new BigInteger(1, Arrays.copyOfRange(
uncompressedPoint, offset, offset + keySizeBytes));
offset += keySizeBytes;
final BigInteger y = new BigInteger(1, Arrays.copyOfRange(
uncompressedPoint, offset, offset + keySizeBytes));
final ECPoint w = new ECPoint(x, y);
final ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(w, params);
final KeyFactory keyFactory = KeyFactory.getInstance("EC");
return (ECPublicKey) keyFactory.generatePublic(ecPublicKeySpec);
}

public static byte[] toUncompressedPoint(final ECPublicKey publicKey) {

int keySizeBytes = (publicKey.getParams().getOrder().bitLength() + Byte.SIZE - 1)
/ Byte.SIZE;

final byte[] uncompressedPoint = new byte[1 + 2 * keySizeBytes];
int offset = 0;
uncompressedPoint[offset++] = 0x04;

final byte[] x = publicKey.getW().getAffineX().toByteArray();
if (x.length <= keySizeBytes) {
System.arraycopy(x, 0, uncompressedPoint, offset + keySizeBytes
- x.length, x.length);
} else if (x.length == keySizeBytes + 1 && x[0] == 0) {
System.arraycopy(x, 1, uncompressedPoint, offset, keySizeBytes);
} else {
throw new IllegalStateException("x value is too large");
}
offset += keySizeBytes;

final byte[] y = publicKey.getW().getAffineY().toByteArray();
if (y.length <= keySizeBytes) {
System.arraycopy(y, 0, uncompressedPoint, offset + keySizeBytes
- y.length, y.length);
} else if (y.length == keySizeBytes + 1 && y[0] == 0) {
System.arraycopy(y, 1, uncompressedPoint, offset, keySizeBytes);
} else {
throw new IllegalStateException("y value is too large");
}

return uncompressedPoint;
}

public static void main(final String[] args) throws Exception {

// just for testing

final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(163);

for (int i = 0; i < 1_000; i++) {
final KeyPair ecKeyPair = kpg.generateKeyPair();

final ECPublicKey ecPublicKey = (ECPublicKey) ecKeyPair.getPublic();
final ECPublicKey retrievedEcPublicKey = fromUncompressedPoint(
toUncompressedPoint(ecPublicKey), ecPublicKey.getParams());
if (!Arrays.equals(retrievedEcPublicKey.getEncoded(),
ecPublicKey.getEncoded())) {
throw new IllegalArgumentException("Whoops");
}
}
}
}

关于ECC 公钥的 Java 紧凑表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28172710/

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