我的目标是不使用
EVP
中的 OpenSSL
函数。我知道这是可能的,因为我基本上分解了数千行 C 代码来将密钥导出为独立的嵌入式程序,这并不容易。
但现在我想实际加密/解密数据。实际上,这两个函数是在
/crypto/aes/aesni-x86_64.s
中找到的汇编例程。我只是因为阅读更多代码而感到有点疲惫。我正在寻找仅使用 AES_256_CBC
密码或 AES_256_GCM
进行加密的直接函数。我在aes_gcm_encrypt
中找到了
crypto/modes/aesni-gcm-x86_64.s
此代码采用
in
中的字符串并将其加密为 tmp
,然后将其解密回 out
,但实际上并未正确解密。有任何想法吗?在使用实际的汇编功能之前我是否缺少其他例程?如果是这样,有人可以告诉我那是哪里吗?
#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>
int aesni_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
void aesni_cbc_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key, unsigned char *ivec, int enc);
int main()
{
int i;
unsigned char key[] = "\xE0\xE6\x0C\x86\xF1\x10\xF5\x3A\x4E\x65\x88\x79\x74\xB1\x4E\x3D\x06\x22\x9D\xB9\x4E\x26\x25\xBE\xD1\x18\x2B\x56\x73\xAB\x44\xF3";
unsigned char iv[] = "\x06\x22\x9D\xB9\x4E\x26\x25\xBE\xD1\x18\x2B\x56\x73\xAB\x44\xF3";
unsigned char in[] = "\x64\x6f\x20\x77\x68\x61\x74\x63\x68\x61\x20\x68\x61\x66\x74\x61";
unsigned char out[16];
unsigned char tmp[16];
// print plaintext
size_t blksz = 16;
for (i=0;i<blksz;i++)
printf("%02x ", in[i]);
puts("");
AES_KEY ks;
aesni_set_encrypt_key(key, 256, &ks);
aesni_cbc_encrypt(in, tmp, blksz, &ks, iv, 1); // 1 = encrypt
// print ciphertext
for (i=0;i<blksz;i++)
printf("%02x ", tmp[i]);
puts("");
// decrypt
aesni_set_decrypt_key(key, 256, &ks);
aesni_cbc_encrypt(tmp, out, blksz, &ks, iv, 0); // 0 = decrypt
// print decrypted plaintext
for (i=0;i<blksz;i++)
printf("%02x ", out[i]);
puts("");
return 0;
}
我将使用 Dave Thompson 的第一条评论来回答这个问题。
“该函数更新 IV(以允许链式操作),因此您使用不同的=错误的 IV 进行解密,从而给出错误的结果。您需要在解密之前重新初始化 IV,或者使用 IV 的副本而不是函数的原始 IV (PS:ivec 参数没有声明为 const 指针这一事实暗示了这一点。)”