Java BouncyCastle ECDH密钥协议失败

Java BouncyCastle ECDH密钥协议失败,java,bouncycastle,Java,Bouncycastle,我使用BouncyCastleAPI实现了椭圆曲线Diffie-Hellman加密。但是,关键协议似乎没有正常运作。它印的是假的 我哪里做错了?多谢各位 ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("B-571"); KeyPairGenerator g = KeyPairGenerator.getInstance("ECDH", "BC"); g.initialize(ecSpec, new Sec

我使用BouncyCastleAPI实现了椭圆曲线Diffie-Hellman加密。但是,关键协议似乎没有正常运作。它印的是假的

我哪里做错了?多谢各位

ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("B-571");

    KeyPairGenerator g = KeyPairGenerator.getInstance("ECDH", "BC");

    g.initialize(ecSpec, new SecureRandom());

    KeyPair aKeyPair = g.generateKeyPair();

    KeyAgreement aKeyAgree = KeyAgreement.getInstance("ECDH", "BC");

    aKeyAgree.init(aKeyPair.getPrivate());

     KeyPair bKeyPair = g.generateKeyPair();

    KeyAgreement bKeyAgree = KeyAgreement.getInstance("ECDH", "BC");

    bKeyAgree.init(bKeyPair.getPrivate());

    //
    // agreement
    //
    aKeyAgree.doPhase(bKeyPair.getPublic(), true);
    bKeyAgree.doPhase(aKeyPair.getPublic(), true);

    byte[] aSecret = aKeyAgree.generateSecret();
    byte[] bSecret = bKeyAgree.generateSecret();

    System.out.println(aSecret);
    System.out.println(bSecret);
    if (aSecret.equals(bSecret)){
        return true;
    } else { return false; }

当我使用Bouncy Castle 1.49进行测试时,它确实工作正常。但是,您使用了错误的方法进行比较

  • 如果需要时间常数比较,请使用
  • 如果不需要时间常数比较,请使用
要打印字节数组的内容,请使用:


编辑:OP要求我解释“时间常数比较”的含义,所以这里是这样的:时间常数比较需要相同的运行时间,无论两个字符串是否匹配。如果两个字符串不匹配,则非时间常数比较通常需要较少的时间运行,并且运行时取决于不匹配的位置:当发现第一个不匹配时,比较停止

您是否需要时间常数比较取决于您是否有计时oracle。也就是说,比较所用的时间长度是否会为攻击者提供有用的信息

下面是一个计时oracle的示例:假设您是一个向浏览器发送cookie的web服务器。您不希望用户篡改cookie,因此附加cookie内容的HMAC:

cookie_to_send = hmac(cookie) + ":" + cookie
现在,当浏览器将cookie发送回您时,您将重新计算HMAC,并查看它是否匹配:

mac, cookie = received_cookie.split(":")
compare(mac, hmac(cookie))
如果比较失败(
mac
hmac(cookie)
不匹配),则拒绝请求

在上面的
compare
操作中,这是一个非常非常重要的恒定时间比较。否则,攻击者可以查看服务器拒绝请求所用的时间,并利用该时间推断出预期的HMAC值。这是因为比较的一个组件(cookie中的HMAC值,在第一个
)之前)由攻击者控制,攻击者可以逐字节调整其值,以查看每次拒绝所需的时间


在您的例子中,您正在比较的字节数组是从
generateScret()
生成的,这向我表明它不是由攻击者控制的。因此,表面上看,似乎没有必要进行时间常数比较。但我不是安全专家,所以我不确定。使用时间常数比较总是安全的(但如果要比较的字符串很长,则速度可能会很慢),因此如果不确定,我建议这样做

mac, cookie = received_cookie.split(":")
compare(mac, hmac(cookie))