首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当使用来自X25519的测试向量时,RFC7748共享秘密是不正确的。

当使用来自X25519的测试向量时,RFC7748共享秘密是不正确的。
EN

Stack Overflow用户
提问于 2022-05-16 21:05:37
回答 2查看 196关注 0票数 1

当在java中使用RFC7748测试向量进行椭圆曲线diffie时,我无法得到预期的共享密钥。我能够用其他语言做到这一点。我使用openjdk 11和默认的Sun安全提供者。我找到了使用这些测试向量的官方测试。但是,即使我复制粘贴并运行它们,也无法获得预期的结果。例如,这里是使用相同向量的测试,如果复制粘贴并在本地运行,这些向量将失败。它使用了一些来自这里的实用函数,我也复制了这些函数。我知道我一定做错了什么,但我不知道到底是什么。这是我的代码:

代码语言:javascript
复制
public class main {
    public static BigInteger hexStringToBigInteger(boolean clearHighBit, String str) {
        BigInteger result = BigInteger.ZERO;
        for (int i = 0; i < str.length() / 2; i++) {
            int curVal = Character.digit(str.charAt(2 * i), 16);
            curVal <<= 4;
            curVal += Character.digit(str.charAt(2 * i + 1), 16);
            if (clearHighBit && i == str.length() / 2 - 1) {
                curVal &= 0x7F;
                result = result.add(BigInteger.valueOf(curVal).shiftLeft(8 * i));
            }
        }
        return result;
    }

    public static byte[] hexStringToByteArray(String str) {
        byte[] result = new byte[str.length() / 2];
        for (int i = 0; i < result.length; i++) {
            result[i] = (byte) Character.digit(str.charAt(2 * i), 16);
            result[i] <<= 4;
            result[i] += Character.digit(str.charAt(2 * i + 1), 16);
        }
        return result;
    }

    public static String byteArrayToHexString(byte[] arr) {
        StringBuilder result = new StringBuilder();
        for (byte curVal : arr) {
            result.append(Character.forDigit(curVal >> 4 & 0xF, 16));
            result.append(Character.forDigit(curVal & 0xF, 16));
        }
        return result.toString();
    }

    private static void runDiffieHellmanTest(String curveName, String a_pri,
                                             String b_pub, String result) throws Exception {

        NamedParameterSpec paramSpec = new NamedParameterSpec(curveName);
        KeyFactory kf = KeyFactory.getInstance("XDH");
        KeySpec privateSpec = new XECPrivateKeySpec(paramSpec, hexStringToByteArray(a_pri));
        PrivateKey privateKey = kf.generatePrivate(privateSpec);
        boolean clearHighBit = curveName.equals("X25519");
        KeySpec publicSpec = new XECPublicKeySpec(paramSpec, hexStringToBigInteger(clearHighBit, b_pub));
        PublicKey publicKey = kf.generatePublic(publicSpec);

        byte[] encodedPrivateKey = privateKey.getEncoded();
        System.out.println("Encoded private: " + byteArrayToHexString(encodedPrivateKey));
        byte[] encodedPublicKey = publicKey.getEncoded();
        System.out.println("Encoded public: " + byteArrayToHexString(encodedPublicKey));

        KeyAgreement ka = KeyAgreement.getInstance("XDH");
        ka.init(privateKey);
        ka.doPhase(publicKey, true);

        byte[] sharedSecret = ka.generateSecret();
        byte[] expectedResult = hexStringToByteArray(result);
        if (!Arrays.equals(sharedSecret, expectedResult)) {
            throw new RuntimeException("fail: expected=" + result + ", actual="
                    + byteArrayToHexString(sharedSecret));
        }
    }

    public static void main(String[] args) throws Exception {
        runDiffieHellmanTest(
                "X25519",
                "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
                "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
                "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-17 01:12:59

您在hexStringToBigInteger中错误地交换了两行

代码语言:javascript
复制
            if (clearHighBit && i == str.length() / 2 - 1) {
                curVal &= 0x7F;
                result = result.add(BigInteger.valueOf(curVal).shiftLeft(8 * i));
            }

相反,应:

代码语言:javascript
复制
            if (clearHighBit && i == str.length() / 2 - 1) {
                curVal &= 0x7F;
            }
            result = result.add(BigInteger.valueOf(curVal).shiftLeft(8 * i));
票数 0
EN

Stack Overflow用户

发布于 2022-05-17 11:16:47

我无法在Go和Java应用程序之间建立共享秘密,因此我尝试调试导致我阅读RFC7748并在X25519中进行X25519密钥交换的源代码的原因。因此,对于那些希望在Java和其他一些非Java应用程序之间执行X25519密钥交换的人来说,这里是主要的外卖。Java已经期望输入公钥是BigInteger,而不是字节数组。其他一些语言可能以big-endian格式将公钥作为字节数组返回。由于RFC7748规范,椭圆曲线上的一个点(即公钥字节数组)的X坐标必须是格式。因此,在输入到little-endian之前,只需反向输入公钥字节数组即可使其为BigInteger

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72265630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档