首页 > 解决方案 > 在 PHP 中加密,在 C 中解密

问题描述

我想在 PHP 中加密一个字符串,然后在 C 中解密它。我被困在解密部分。

(PHP)我首先加密字符串:

function encrypt($plaintext, $key) {
    $iv = 'aaaaaaaaaaaaaaaa';

    $ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv);

    return $ciphertext;
}

echo encrypt('This is a test', 'test');
// output: 7q�7h_��8� ��L

(C) 然后我想解密它,我使用tiny-AES-c库作为函数:

int test_decrypt_cbc(void) {
    uint8_t key[] = "test";
    uint8_t iv[]  = "aaaaaaaaaaaaaaaa";
    uint8_t str[] = "7q�7h_��8� ��L";

    printf("%s", str);

    printf("\n Decrypted buffer\n");

    struct AES_ctx ctx;
    AES_init_ctx_iv(&ctx, key, iv);
    AES_CBC_decrypt_buffer(&ctx, str, sizeof(str));
    
    printf("%s", str);

    printf("\n");
    return 1;
}

这输出:

7q�7h_��8� ��L
 Decrypted buffer
?L??Ɵ??m??Dˍ?'?&??c?W

它应该输出“这是一个测试”。

我怎样才能解决这个问题?

标签: phpccryptographyaes

解决方案


  • 在 PHP 代码中,使用了 AES-256。tiny-AES-c默认仅支持 AES-128。为了支持 AES-256,必须在 aes.h 中定义相应的常量,即//#define AES256 1必须在此处注释该行。

  • PHP 默认使用 PKCS7 填充。应在 C 代码中删除填充。

  • PHP 隐式地将具有零值的过短键填充到指定长度。由于 PHP 代码中指定了 AES-256-CBC,因此重点测试扩展如下:

    test\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
    

    在 C 代码中,必须使用此扩展键(另请参见 @r3mainer 的注释)。

  • 为了在两个代码之间传输密文,必须使用合适的编码,例如 Base64 或十六进制(另请参见 @Ôrel 的注释)。对于后者,bin2hex可以应用于PHP代码中的密文。可以在此处找到 C 中的十六进制解码示例。

  • 一个可能的 C 实现是:

    // Pad the key with zero values
    uint8_t key[] = "test\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    
    uint8_t iv[] = "aaaaaaaaaaaaaaaa";
    uint8_t ciphertextHex[] = "3771e837685ff5d4173801900de6e14c";
    
    // Hex decode (e.g. https://stackoverflow.com/a/3409211/9014097)
    uint8_t ciphertext[sizeof(ciphertextHex) / 2], * pos = ciphertextHex;
    for (size_t count = 0; count < sizeof ciphertext / sizeof * ciphertext; count++) {
        sscanf((const char*)pos, "%2hhx", &ciphertext[count]);
        pos += 2;
    }
    
    // Decrypt
    struct AES_ctx ctx;
    AES_init_ctx_iv(&ctx, key, iv);
    AES_CBC_decrypt_buffer(&ctx, ciphertext, sizeof(ciphertext));
    
    // Remove the PKCS7 padding
    uint8_t ciphertextLength = sizeof(ciphertext);
    uint8_t numberOfPaddingBytes = ciphertext[ciphertextLength - 1];
    ciphertext[ciphertextLength - numberOfPaddingBytes] = 0;
    
    printf("%s", ciphertext);
    

推荐阅读