使用java解密OpenSSL加密数据

使用java解密OpenSSL加密数据,java,c,ssl,encryption,openssl,Java,C,Ssl,Encryption,Openssl,我试图理解OpenSSL加密。我的要求是使用下面的代码对加密的数据进行解密。它正在为接收方创建匿名ID。我需要把收到的身份证拿回来 根据文档,我了解到加密正在使用EVP\u EncryptFinal进行。但是PKCS5\u PBKDF2\u HMAC\u SHA1在做什么 代码使用的是KEY和IV int create_anon_id(uint32_t recvr_id, uint32_t smartcard_id, const char *hw_id, unsigned char *anon_

我试图理解OpenSSL加密。我的要求是使用下面的代码对加密的数据进行解密。它正在为接收方创建匿名ID。我需要把收到的身份证拿回来

根据文档,我了解到加密正在使用
EVP\u EncryptFinal
进行。但是PKCS5\u PBKDF2\u HMAC\u 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);
            }
        }
    }
}

这段代码相当糟糕,尽管运气不好,一些错误通过使用正好是一个三重DES数据块(64位或8字节)的输入来掩盖。如果编码正确,则加密将由
EVP_EncryptUpdate
EVP_EncryptFinal
执行;如前所述,未添加块的唯一实际使用的加密由
Update
完成

但是
anon_id
中返回的值是而不是(仅仅)加密的
PKCS5_PBKDF2_HMAC[\u SHA1]
是的一个实现,在这里使用它计算

  • recvr\u id
    smartcard\u id
    (更新:显然未交换)连接,然后使用
    密钥
    IV
    加密三重DES,无论此代码中包含哪些内容,如

  • hw_id
    (更新:显然没有交换,因此“意外”输入有效)作为salt

  • 对于
    轮次
    (更新:10001)迭代,PRF=HMAC-SHA1

  • (更新)略微扩展到
    ANON\u ID\u BIN\u SIZE
    (22)字节。(这需要额外的“通过”PBKDF2,这实际上会损害安全性;它会减慢防御者的速度而不会减慢攻击者的速度。)

PBKDF2具有适当的PRF(HMAC-SHA1是)是一种单向函数,不能反转,因为如果知道或猜测密钥,加密也可以。如果salt和迭代计数选择得当,它的设计成本也会降低。32位的盐肯定是偏低的,而(更新)10001轮有点偏低,但并不疯狂

作为一个更好的例子(对于攻击者来说),如果32位的
recvr\u id
smartcard\u id
都只包含16位熵,
hw\u id
,并且
ROUNDS
为1000,这是在世纪之交编写rfc2898时的建议值,你必须尝试多达256万亿的可能性,一台典型的台式计算机在CPU上每秒可以运行3万次,如果运气和技能好的话,可能是GPU的1000倍,所以这将需要大约3个月的时间

另一方面,如果32位输入是完全熵的,并且
轮数
为1000000,那么仅用一台计算机是不可能的。如果你有几百万美元花在FPGA(或者更好的ASIC)上,还有发电厂(或者你自己的水电站)的产量来运行它们,那还需要几百万年的时间

更新:对于第10001轮,您很可能处于这两种情况之间,但具体位置在很大程度上取决于输入的熵

总的来说,这可能不会产生预期的结果。如果输出大小小于甚至大致等于输入的熵,则会发生碰撞——产生所需输出的多个输入值(组合),可能是大量(数百万、数十亿等)此类输入。如果您需要原始输入,而不仅仅是生成(伪造)已知输出的某个输入,那么您将需要一些其他方法或条件来从bruteforcing找到的可能输入中进行选择。
更新:对于熵最多为96位的输出22字节,代码非常差的风险可以忽略不计,尽管运气不好,一些错误通过使用正好是一个三重DES数据块(64位或8字节)的输入来掩盖。如果编码正确,则加密将由
EVP_EncryptUpdate
EVP_EncryptFinal
执行;如前所述,未添加块的唯一实际使用的加密由
Update
完成

但是
anon_id
中返回的值是而不是(仅仅)加密的
PKCS5_PBKDF2_HMAC[\u SHA1]
是的一个实现,在这里使用它计算

  • recvr\u id
    smartcard\u id
    (更新:显然未交换)连接,然后使用
    密钥
    IV
    加密三重DES,无论此代码中包含哪些内容,如

  • hw_id
    (更新:显然没有交换,因此“意外”输入有效)作为salt

  • 对于
    轮次
    (更新:10001)迭代,PRF=HMAC-SHA1

  • (更新)略微扩展到
    ANON\u ID\u BIN\u SIZE
    (22)字节。(这需要额外的“通过”PBKDF2,这实际上会损害安全性;它会减慢防御者的速度而不会减慢攻击者的速度。)

PBKDF2具有适当的PRF(HMAC-SHA1是)是一种单向函数,不能反转,因为如果知道或猜测密钥,加密也可以。如果salt和迭代计数选择得当,它的设计成本也会降低。32位的盐肯定是偏低的,而(更新)10001轮有点偏低,但并不疯狂

作为一个更好的例子(对于攻击者来说),如果32位的
recvr\u id
smartcard\u id
都只包含16位熵,
hw\u id
,并且
ROUNDS
为1000,这是在世纪之交编写rfc2898时的建议值,你必须尝试多达256万亿的可能性,一台典型的台式计算机在CPU上每秒可以运行3万次,如果运气好和技术好的话,可能是GPU的1000倍,所以大约需要3个月的时间