简体   繁体   English

加密 - SJCL(javascript)加密是否与OpenSSL兼容?

[英]Crypto - Is SJCL (javascript) encryption compatible with OpenSSL?

I am trying to decrypt some information that has been encrypted with the SJCL (Stanford Javascript Crypto Library) . 我试图解密一些用SJCL(Stanford Javascript Crypto Library)加密的信息 An example page is at http://bitwiseshiftleft.github.io/sjcl/demo/ . 示例页面位于http://bitwiseshiftleft.github.io/sjcl/demo/

If I encrypt some data, I have been unable to decrypt it using OpenSSL (version 1.0.1f). 如果我加密某些数据,我无法使用OpenSSL(版本1.0.1f)解密它 I have seen another question on stackoverflow asking about this - but that question and its answers didn't really help. 我在stackoverflow上看到了另一个问题,但是这个问题及其答案并没有真正帮助。

For instance, encrypting with a password of 'password', and a random salt of '6515636B 82C5AC56' with 10000 iterations of a 256 bit key size gives a Key of 'D8CCAA75 3E2983F0 3657AB3C 8A68A85A 9E9F1CAC 43DAB645 489CDE58 0A9EBDAE', which is exactly what I get with OpenSSL. 例如,使用密码“password”进行加密,并使用256位密钥大小的10000次迭代对“6515636B 82C5AC56”进行随机加密,得到“D8CCAA75 3E2983F0 3657AB3C 8A68A85A 9E9F1CAC 43DAB645 489CDE58 0A9EBDAE”的密钥,这正是我所知道的得到OpenSSL。 So far, so good. 到现在为止还挺好。

When I use SJCL with this key and an IV of '9F62544C 9D3FCAB2 DD0833DF 21CA80CF' to encrypt, say, the message 'mymessage', then I get the ciphertext : 当我使用带有此密钥的SJCL和'9F62544C 9D3FCAB2 DD0833DF 21CA80CF'的IV加密,例如,消息'mymessage'时,我得到密文

{"iv":"n2JUTJ0/yrLdCDPfIcqAzw==",
"v":1,
"iter":10000,
"ks":256,
"ts":64,
"mode":"ccm",
"adata":"",
"cipher":"aes",
"salt":"ZRVja4LFrFY=",
"ct":"FCuQWGYz3onE/lRt/7vCl5A="}

However, no matter how I modify or rewrite my OpenSSL C++ code, I cannot decrypt this data. 但是,无论我如何修改或重写我的OpenSSL C ++代码,我都无法解密这些数据。 I've googled and found a few code samples, but nothing that has actually worked. 我用Google搜索并找到了一些代码示例,但实际上并没有任何效果。 I'm aware that I need to use the CCM cipher mode in OpenSSL - but this mode is poorly documented. 我知道我需要在OpenSSL中使用CCM密码模式 - 但是这种模式记录很少。 Can anyone post some OpenSSL code to successfully decrypt this data? 任何人都可以发布一些OpenSSL代码来成功解密这些数据吗?

You can copy-paste the example at http://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption with a few changes. 您可以在http://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption上复制粘贴示例,只需进行一些更改。

First, you need to Base64 decode SJCL's data. 首先,您需要Base64解码SJCL的数据。 But you knew that. 但你知道的。

Second, you need to split the message into ct and tag. 其次,您需要将消息拆分为ct和tag。 In this case, ct is the first 9 bytes, and tag is the 8 bytes starting at ct[9]. 在这种情况下,ct是前9个字节,标签是从ct [9]开始的8个字节。

Third, you need to set the tag length to ts/8 = 8, and you need to set the IV length correctly. 第三,您需要将标签长度设置为ts / 8 = 8,并且需要正确设置IV长度。 If you set the IV too long in SJCL, it will truncate it to 15 - LOL (length of length), where LOL is between 2 and 4 (because SJCL enforces <2^32 bytes length), and is the number of bytes required to describe the length of the message. 如果在SJCL中将IV设置得太长,它会将其截断为15 - LOL(长度长度),其中LOL介于2和4之间(因为SJCL强制执行<2 ^ 32字节长度),并且是所需的字节数描述消息的长度。 This is 2 unless the message is at least 65536 bytes long, in which case it is 3, unless the message is at least 2^24 bytes long, in which case it is 4. Keep in mind that if you're decrypting, the ciphertext you are passed includes the tag but LOL must be computed from the message length, which does not include the tag. 这是2,除非消息长度至少为65536字节,在这种情况下它是3,除非消息长度至少为2 ^ 24字节,在这种情况下它是4.请记住,如果你正在解密,您传递的密文包含标记,但必须根据消息长度计算LOL,该长度不包括标记。

With those changes, it should work: 通过这些更改,它应该工作:

#include <openssl/evp.h>

void handleErrors() {
    abort();
}

int decryptccm(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad,
    int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv,
    unsigned char *plaintext)
{
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;
    int ret;

    /* Create and initialise the context */
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

    /* Initialise the decryption operation. */
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))
        handleErrors();

    int lol = 2;
    if (ciphertext_len >= 1<<16) lol++;
    if (ciphertext_len >= 1<<24) lol++;

    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, 15-lol, NULL))
        handleErrors();

    /* Set expected tag value. */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, 8, tag))
        handleErrors();

    /* Initialise key and IV */
    if(1 != EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();

    /* Provide the total ciphertext length
     */
    if(1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, ciphertext_len))
        handleErrors();

    /* Provide any AAD data. This can be called zero or more times as
     * required
     */
    if(1 != EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
        handleErrors();

    /* Provide the message to be decrypted, and obtain the plaintext output.
     * EVP_DecryptUpdate can be called multiple times if necessary
     */
    ret = EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);

    plaintext_len = len;

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    if(ret > 0)
    {
        /* Success */
        return plaintext_len;
    }
    else
    {
        /* Verify failed */
        return -1;
    }
}

int main(int argc, char **argv) {
    // base64-decoded from your example
    unsigned char iv[] = { 0x9F,0x62,0x54,0x4C,0x9D,0x3F,0xCA,0xB2,0xDD,0x08,0x33,0xDF,0x21,0xCA,0x80,0xCF };
    unsigned char ct[] = { 0x14,0x2B,0x90,0x58,0x66,0x33,0xDE,0x89,0xC4,0xFE,0x54,0x6D,0xFF,0xBB,0xC2,0x97,0x90 };
    unsigned char ky[] = { 0xD8,0xCC,0xAA,0x75 ,0x3E,0x29,0x83,0xF0 ,0x36,0x57,0xAB,0x3C ,0x8A,0x68,0xA8,0x5A ,0x9E,0x9F,0x1C,0xAC ,0x43,0xDA,0xB6,0x45 ,0x48,0x9C,0xDE,0x58 ,0x0A,0x9E,0xBD,0xAE };

    const unsigned char *message = (const unsigned char *)"mymessage";

    unsigned char plaintext[1000];

    int ret = decryptccm(ct, 9, "", 0, &ct[9], ky, iv, plaintext);

    plaintext[9] = 0;

    printf("%d,%s\n",ret,plaintext);

    return 0;
}

This program returns "9,mymessage" on my machine. 该程序在我的机器上返回“9,mymessage”。

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

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