1

我正在尝试使用 Luna HSM(Gemalto) 实现 EDDSA 签名

Signature signature = null;
signature = Signature.getInstance("EDDSA", "LunaProvider");
PrivateKey privateKey = getPrivateByAlias(privateKeyLabel);
signature.initSign(privateKey);
signature.update(payload);
byte[] byteArray = signature.sign();

但是在签名之后,byteArray 的大小变成了 71,但是 EDDSA 签名大小按照规范是 64。我不确定我在这里缺少什么。我在网上也找不到任何文件。

4

2 回答 2

1

这正是 X9.63 兼容签名所期望的大小,它由两个有符号大端整数的 DER 编码组成。如果你想要一个 64 字节的签名,那么你应该使用下面的解释来转换里面的 2 个整数。可以在此处找到 I2OSP 和 OS2IP 的 Java 实现。

所以步骤是:

  1. 解析 ASN.1 签名;
  2. 使用构造函数转换为BigInteger值;new BigInteger(byte[])
  3. 使用 I2OSP 将 r 和 s 值创建为字节数组(32 个八位字节输出大小);
  4. 连接 r 和 s 以创建 64 字节签名。
于 2020-03-14T13:27:17.483 回答
0

我已尝试如下但验证失败(代码已更新,现在可以使用)

        Signature signature = Signature.getInstance("SHA512withEDDSA", "LunaProvider");
        signature.setParameter(new LunaEDDSAParameterSpec(false));
        signature.initSign(privateKey);
        signature.update(payload);
        byte[] byteArray = signature.sign();

        ASN1InputStream decoder = new ASN1InputStream(byteArray);
        DERSequence seq = (DERSequence) decoder.readObject();
        DERInteger r = (DERInteger) seq.getObjectAt(0);
        DERInteger s = (DERInteger) seq.getObjectAt(1);
        LOGGER.info("R: {}", r.getValue());
        LOGGER.info("S: {}", s.getValue());
        decoder.close();

        byte[] rByte = i2osp(r.getValue(), 32);
        byte[] sByte = i2osp(s.getValue(), 32);

        byte[] concat = Bytes.concat(rByte, sByte);

        return concat;

不确定这是正确的做法

使用 stellar java 库进行验证

        PublicKey publicKey = getPublicByAlias(publicKeyLabel);
        LunaPublicKeyEC lunaPublicKeyEC = (LunaPublicKeyEC) publicKey;
        byte[] pubKeySub = Arrays.copyOfRange(lunaPublicKeyEC.getP(), 2, lunaPublicKeyEC.getP().length);
        org.stellar.sdk.KeyPair keyPair = org.stellar.sdk.KeyPair.fromPublicKey(pubKeySub);
        boolean verified = keyPair.verify(payload, signatureByte);
于 2020-03-16T02:37:56.257 回答