使用java解密OpenSSL加密数据

时间:2016-10-12 16:39:09

标签: java c ssl encryption openssl

我正在尝试了解OpenSSL加密。对我的要求是解密使用以下代码加密的数据。它正在为接收器创建一个匿名ID。我需要收回身份证。

根据文档,我了解加密是使用EVP_EncryptFinal进行的。但是PKCS5_PBKDF2_HMAC_SHA1在做什么?

代码使用KEY和IV。

int create_anon_id(uint32_t recvr_id, uint32_t smartcard_id, const char *hw_id, unsigned char *anon_id)
{
    EVP_CIPHER_CTX ctx;
    unsigned char ibuf[sizeof(recvr_id) + sizeof(smartcard_id)] = {};
    unsigned char obuf[sizeof(ibuf) * 2] = {};
    int olen = sizeof(obuf);

    /* Convert to big endian. */
    recvr_id = bswap32(recvr_id);
    smartcard_id = bswap32(smartcard_id);
    hw_id = bswap32(hw_id);

    /* Fill input buffer with recvr_id | smartcard_id */
    memcpy(ibuf, &recvr_id, sizeof(recvr_id));
    memcpy(ibuf + sizeof(recvr_id), &smartcard_id, sizeof(smartcard_id));

    if (EVP_EncryptInit(&ctx, EVP_des_ede3_cbc(), KEY, IV) == 1)
    {
        if (EVP_EncryptUpdate(&ctx, obuf, &olen, ibuf, sizeof(ibuf)) == 1)
        {
            olen = sizeof(obuf) - olen;
            if (EVP_EncryptFinal(&ctx, obuf + sizeof(obuf) - olen, &olen) == 1)
            {
                return PKCS5_PBKDF2_HMAC_SHA1((const char *)obuf, olen, (unsigned char *)hw_id, HW_ID_SIZE, ROUNDS, ANON_ID_BIN_SIZE, anon_id);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

该代码非常差,但运气不好,一些错误被使用输入掩盖,输入恰好是一个三重DES数据块(64位或8字节)。如果编码正确,加密将由EVP_EncryptUpdateEVP_EncryptFinal完成;如所写的,未填充块的实际使用的唯一加密由Update完成。

anon_id中返回的值为 NOT(JUST)ENCRYPTED PKCS5_PBKDF2_HMAC[_SHA1]PBKDF2 algorithm的一个实现,并且在这里使用它实际上计算了

的缓慢哈希值
  • recvr_idsmartcard_id连接(更新:显然未交换),然后使用KEYIV加密三重DES,无论此代码中的内容如何, '密码'与

  • hw_id(更新:显然没有交换,因此'意外'类型有效)作为盐,

  • {li>

    ROUNDS(更新:10001)迭代的PRF = HMAC-SHA1

  • (更新)略微扩展到ANON_ID_BIN_SIZE(22)个字节。 (这需要额外的“传递”PBKDF2,这实际上会伤害安全;它会减慢防御者的速度而不会减慢攻击者的速度。)

具有良好PRF的

PBKDF2 (HMAC-SHA1是)是单向函数且无法反转,因为如果您知道或猜测密钥,则加密可以。如果很好地选择盐和迭代计数,它也被设计为<强力>暴力破坏。 32位盐绝对偏低,而且(更新)ROUNDS 10001有点偏低,但并不疯狂。

作为一个更好的案例(对于你作为攻击者)如果32位recvr_idsmartcard_id每个只包含16位熵,hw_id也是如此, ROUNDS是1000,这是rfc2898在世纪之交写的时候的推荐值,你必须尝试高达256万亿的可能性,典型的台式计算机可以在CPU中每秒做3万个,并且运气和技巧可能是GPU的千倍,因此大约需要3个月。

另一方面,如果32位输入是完全熵并且ROUNDS是1000000,那么仅使用计算机是不可能的。如果您花费数百万美元用于FPGA(甚至更好的ASIC),以及发电厂(或者您自己的水电大坝)的输出来运行它们,它仍然需要数百万年。

更新:使用ROUNDS 10001,您最有可能处于这些情况之间,但只是在很大程度上取决于输入的熵。

一般而言,这可能无法产生预期的结果。如果输出大小小于或甚至大致等于输入的熵,则会有冲突 - 产生所需输出的多个输入值(组合),可能是很多(数百万,这些投入的数十亿等。如果您需要 原始输入,而不仅仅是生成(伪造)已知输出的某些输入,您需要一些其他方法或标准来从可能的输入中进行选择那个暴力发现。 更新:输出22字节,最多96位熵,风险可忽略不计