简体   繁体   English

使用java解密OpenSSL加密数据

[英]Decrypt OpenSSL encrypted data using java

I am trying to understand OpenSSL encryption. 我试图了解OpenSSL加密。 The requirement for me is to decrypt the data encrypted using the below code. 对我的要求是解密使用以下代码加密的数据。 It is creating an anonymous ID for receiver. 它正在为接收器创建一个匿名ID。 I need to get received ID back. 我需要收回身份证。

Based on the documentation I understood encryption is happening using EVP_EncryptFinal . 根据文档,我了解使用EVP_EncryptFinal加密。 But what is PKCS5_PBKDF2_HMAC_SHA1 doing ? 但是什么是PKCS5_PBKDF2_HMAC_SHA1呢?

The code is using KEY and IV. 代码使用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);
            }
        }
    }
}

That code is quite poor, although by bad luck some of the errors are masked by using an input which is exactly one triple-DES data block (64 bits or 8 bytes). 该代码相当差,尽管运气不好,一些错误被使用输入掩盖,输入恰好是一个三重DES数据块(64位或8字节)。 If coded correctly the encryption would be done by both EVP_EncryptUpdate and EVP_EncryptFinal ; 如果编码正确,加密将由EVP_EncryptUpdateEVP_EncryptFinal ; as written the only encryption actually used, of the unpadded block, is done by Update . 如所写的,未填充块的实际使用的唯一加密是由Update完成的。

But the value returned in anon_id is NOT (JUST) ENCRYPTED . 但是anon_id返回的值不是(JUST)ENCRYPTED PKCS5_PBKDF2_HMAC[_SHA1] is an implementation of the PBKDF2 algorithm and as used here it computes essentially a slow hash of PKCS5_PBKDF2_HMAC[_SHA1]PBKDF2算法的一个实现,并且在这里使用它实际上计算了一个缓慢的哈希值

  • recvr_id concatenated with smartcard_id (update: apparently not swapped) then triple-DES encrypted with KEY and IV whatever those are in this code, as the 'passphrase' with recvr_idsmartcard_id连接(更新:显然没有交换)然后使用KEYIV加密三重DES,无论这些代码是什么,作为'passphrase'与

  • hw_id (update: apparently not swapped, and thus 'accidentally' type-valid) as the salt, hw_id (更新:显然没有交换,因此'意外'类型有效)作为盐,

  • and PRF = HMAC-SHA1 for ROUNDS (update: 10001) iterations 和PRF = HMAC-SHA1用于ROUNDS (更新:10001)迭代

  • (update) expanded slightly to ANON_ID_BIN_SIZE (22) bytes. (更新)略微扩展到ANON_ID_BIN_SIZE (22)字节。 (This requires an extra 'pass' of PBKDF2 which actually hurts security; it slows the defender without slowing the attacker.) (这需要额外的“传递”PBKDF2,这实际上会伤害安全;它会减慢防御者的速度而不会减慢攻击者的速度。)

PBKDF2 with a decent PRF (HMAC-SHA1 is) is a one-way function and cannot be reversed , as encryption can if you know or guess the key. 具有合适PRF(HMAC-SHA1)的PBKDF2 是单向函数,不能反转 ,因为如果您知道或猜测密钥,加密就可以。 It is also designed to be costly to bruteforce if the salt and iteration count are chosen well. 如果选择好盐和迭代次数,它的设计成本也很高 32-bits of salt is definitely on the low side, and (update) ROUNDS 10001 is somewhat on the low side but not crazy. 32位的盐肯定是偏低的,而且(更新)ROUNDS 10001有点偏低,但并不疯狂。

As a better-case example (for you as attacker) if the 32-bit recvr_id and smartcard_id each contain only 16-bits of entropy, and so does hw_id , and ROUNDS was 1000 which was the recommended value when rfc2898 was written at the turn of the century, you'd have to try up to 256 trillion possibilities and a typical desktop computer can do maybe 30 thousand per second in CPU, and with some luck and skill maybe a thousand times that in GPU, so that will take about 3 months. 作为一个更好的例子(对于你作为攻击者)如果32位recvr_idsmartcard_id每个只包含16位熵,那么hw_id也是如此,并且ROUNDS是1000,这是在转弯处写入rfc2898时的推荐值在本世纪,你必须尝试高达256万亿的可能性,典型的台式电脑每秒可以在CPU中运行3万,而运气和技能可能是GPU的千倍,因此需要大约3个月。

On the other hand, if the 32-bit inputs are fully entropic and ROUNDS was 1000000, it is impossible with just a computer. 另一方面,如果32位输入是完全熵并且ROUNDS是1000000,那么仅使用计算机是不可能的。 If you have a few million dollars to spend on FPGAs (or even better ASICs), and the output of a power plant (or maybe your own hydroelectric dam) to run them, it will still take many millions of years. 如果你花费数百万美元用于FPGA(甚至更好的ASIC),以及发电厂(或者你自己的水电大坝)的输出来运行它们,它仍然需要数百万年。

Update: with ROUNDS 10001 you are most likely in between these situations, but just where depends strongly on the entropy of the inputs. 更新:使用ROUNDS 10001,您最有可能处于这些情况之间,但只是在很大程度上取决于输入的熵。

And in general this may not produce the desired result anyway. 并且通常这可能无论如何都不会产生期望的结果。 If the output size is less than or even roughly equal to the entropy of the inputs, there will be collisions -- multiple input values (combinations) that produce the desired output, possibly a great many (millions, billions, etc) of such inputs. 如果输出大小小于或甚至大致等于输入的熵,则会发生冲突 - 产生所需输出的多个输入值(组合),可能是这些输入的大量(数百万,数十亿等) 。 If you need the original input, rather than merely some input that produces (forges) a known output, you'll need some other method or criteria to select among the possible inputs that bruteforcing finds. 如果需要原始输入,而不是仅仅一些输入,其产生(伪造)已知的输出,就需要一些其它方法或标准的穷举的发现可能的输入中进行选择。 Update: for output 22 bytes with at most 96 bits entropy, this risk is negligible . 更新:对于输出22字节,最多96位熵,这种风险可以忽略不计

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM