2013-08-17 49 views
1

我使用BouncyCastle API实现了Elliptic Curve Diffie Hellman加密。但是,似乎这个关键协议没有正常工作。它打印错误。BouncyCastle ECDH密钥协议失败

我在哪里做错了?谢谢。

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

回答

8

它确实工作正确,当我测试与Bouncy城​​堡1.49。但是,您正在使用错误的方法进行比较。

要打印出来的字节数组的内容,使用Arrays.toString

System.out.println(Arrays.toString(aSecret)); 
System.out.println(Arrays.toString(bSecret)); 
return MessageDigest.isEqual(aSecret, bSecret); 

编辑:OP让我解释什么是“时间常数比较”的意思,所以这里有云:时间常数比较需要花费相同的时间来运行,无论这两个字符串是否匹配。如果两个字符串不匹配,则非时间常数比较通常需要较少的时间来运行,并且运行时间取决于不匹配的位置:比较在找到第一个不匹配时停止。

是否需要时间常数比较取决于您是否有时间预测。也就是说,比较时间的长短会给攻击者提供有用的信息吗?

下面是一个定时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值,在第一个:之前)由攻击者控制,攻击者可以逐字节地调整它的值以查看拒绝每次需要多长时间。


在你的情况,你的字节数组(,您比较)从generateSecret()产生,这表明,我认为它不是攻击者控制。因此,从表面上看,似乎不需要时间常数比较。但我不是安全专家,所以我不确定。它是总是安全的(但如果比较的字符串很长,可能会很慢)使用时间常数比较,所以如果不确定,那就是我的建议。