基于字节数组的 ECPublicKey 生成

ECPublicKey generation based on a byte array

我有一个 byte[] encodedKeyBytes,我想创建关联的 Public 密钥。

// spec for P-256 curve
ECParameterSpec params = ECNamedCurveTable.getParameterSpec("prime256v1");

ECPublicKeySpec pubKey = new ECPublicKeySpec(
            params.getCurve().decodePoint(encodedKeyBytes), params);
Exception in thread "main" java.lang.IllegalArgumentException: Invalid point encoding 0x-5c
  at org.bouncycastle.math.ec.ECCurve.decodePoint(Unknown Source)

下面是整个方法:

public PublicKey generatePublicKeyFrom(byte[] encodedKeyBytes)
        throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {

    // spec for P-256 curve
    ECParameterSpec params = ECNamedCurveTable.getParameterSpec("prime256v1");

    ECPublicKeySpec pubKey = new ECPublicKeySpec(
            params.getCurve().decodePoint(encodedKeyBytes), params);
    KeyFactory kf = KeyFactory.getInstance("ECDH", "BC");
    PublicKey pb = kf.generatePublic(pubKey));
    System.out.println("public key: " + pb;
    return pb;
}

我阅读了一些文档,似乎问题与数组字节的大小和格式有关。有什么方法可以根据实际字节数组生成 public 键,还是我必须实际检索用于创建该字节数组的参数?

字节数组由以下字节组成:

a401022001215820e4706de318a40d0bd8648b7907b0283f7445370241ff1fdd77f08d6a598be90222582079767fbe391223f61dcd5e980133a035b4918f6f9de41b3ceb8d801860df8859

给出 CBOR 编码:

A4                                      # map(4)
   01                                   # unsigned(1)
   02                                   # unsigned(2)
   20                                   # negative(0)
   01                                   # unsigned(1)
   21                                   # negative(1)
   58 20                                # bytes(32)
      E4706DE318A40D0BD8648B7907B0283F7445370241FF1FDD77F08D6A598BE902 # "\xE4pm\xE3\x18\xA4\r\v\xD8d\x8By\a\xB0(?tE7\x02A\xFF\x1F\xDDw\xF0\x8DjY\x8B\xE9\x02"
   22                                   # negative(2)
   58 20                                # bytes(32)
      79767FBE391223F61DCD5E980133A035B4918F6F9DE41B3CEB8D801860DF8859 # "yv\x7F\xBE9\x12#\xF6\x1D\xCD^\x98\x013\xA05\xB4\x91\x8Fo\x9D\xE4\e<\xEB\x8D\x80\x18`\xDF\x88Y"

谢谢!

Bouncy Castle 没有原生 CBOR 解码。

如果你给它一个 public 关键点,它会尝试解析一个 X9.62 格式的点,它以一个字节值为 0203 的压缩点开始04 表示未压缩的点。这种情况下的压缩意味着根据 EC 特定算法从 X 坐标计算 Y 坐标。

如果你想创建一个点来解压缩给出当前点,你首先必须使用 CBOR 库解析该点。然后你必须将 X 坐标和 Y 坐标粘在一起,并在它前面加上 04,这会给你:

04 E4706DE318A40D0BD8648B7907B0283F7445370241FF1FDD77F08D6A598BE902 79767FBE391223F61DCD5E980133A035B4918F6F9DE41B3CEB8D801860DF8859

当然,如果您能找到一个 COSE 图书馆,那您就更好了。似乎 be one 是由 COSE 工作组生成的,但对我来说似乎没有维护。

对于那些想知道如何从 COSE_Key_structure 创建 public 密钥的人:

public PublicKey generatePublicKeyFromECDH(byte[] encodedKeyBytes)
        throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
    ECParameterSpec params2 = ECNamedCurveTable.getParameterSpec("secp256r1");

    ECPointECDH ecPoint = null;
    ObjectMapper mapper = new ObjectMapper(new CBORFactory());
    try {
        ecPoint = mapper.readValue(encodedKeyBytes, ECPointECDH.class);
    } catch (IOException e) {
        e.printStackTrace();
    }

    ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(ecPoint.getEcPoint(), params2);
    KeyFactory kf = KeyFactory.getInstance("EC", "BC");
    PublicKey pb = kf.generatePublic(publicKeySpec);
    return pb;
}

这是映射器。

 public ECPointECDH deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    JsonNode node = p.readValueAsTree();

    byte[] x10 = node.get("-2").binaryValue();
    byte[] y10 = node.get("-3").binaryValue();

    String x = Utils.convertBytesToHex(x10);
    String y = Utils.convertBytesToHex(y10);

    ECNamedCurveParameterSpec params = ECNamedCurveTable.getParameterSpec("secp256r1");
    ECCurve curve = params.getCurve();

    ECPoint point = curve.decodePoint(Hex.decode("04" + x + y));

    return new ECPointECDH(point);
}