【问题标题】:EDDSA Signature with Luna HSM using Java使用 Java 的 Luna HSM 的 EDDSA 签名
【发布时间】:2020-03-14 06:01:51
【问题描述】:

我正在尝试使用 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。我不确定我在这里缺少什么。 我在网上也找不到任何文件。

【问题讨论】:

    标签: java cryptography hsm gemalto ed25519


    【解决方案1】:

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

    所以步骤是:

    1. 解析ASN.1签名;
    2. 使用new BigInteger(byte[])构造函数转换为BigInteger值;
    3. 使用 I2OSP 将 r 和 s 值创建为字节数组(输出大小为 32 个八位字节);
    4. 连接 r 和 s 以创建 64 字节的签名。

    【讨论】:

    • 感谢您的回复,这对我帮助很大,我正在尝试使用 BouncyCastle 将 DER 格式转换为 ASN.1。一旦我设法做到了,我会发布代码
    • 我已经尝试了以下但似乎验证仍然失败。
    【解决方案2】:

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

            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);
    

    【讨论】:

    • 我看起来没问题,你如何验证签名?
    • @MaartenBodewes 非常感谢,我设法做到了,我正在发布更新的代码供其他人参考。原因是 LunaEDDSAParameterSpec 默认将 prehash 设置为 true,但我将其设置为 false,然后我能够获得与恒星(加密货币)验证所预期的相同的值。我不确定 EDDSA 的默认设置是什么。
    • @MaartenBodewes 我使用 stellar java 库来验证签名,并用验证更新了上面的代码
    • 代码更新了,现在可以运行了,是不是问题解决了?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2022-08-14
    • 1970-01-01
    • 1970-01-01
    • 2015-03-08
    • 2022-08-02
    相关资源
    最近更新 更多