OpenSSLを使った暗号化
- 本記事に記載のOpenSSLはバージョンが古いです
- v1.1.1dのAPIについてはこちらの記事をどうぞ
OpenSSLを使ってAESで暗号化。
暗号化
#include <openssl/evp.h> EVP_CIPHER_CTX ctx = {}; EVP_CIPHER_CTX_init(&ctx); // 暗号化の設定で、EVP_aes_128_ecb等いろいろ const unsigned char iv[16] = {}; EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv); // ブロックサイズで割り切れる部分の処理 int outl = 0; EVP_EncryptUpdate(&ctx, encrypted, &outl, data, data_size); // 最後のブロックの処理で、PKCSパディングされる。 int pad = 0; EVP_EncryptFinal_ex(&ctx, encrypted + outl, &pad); EVP_CIPHER_CTX_cleanup(&ctx);
AESはブロック暗号で、16バイトづつ処理される。
16の倍数分はEVP_EncryptUpdate
で処理されて、パディングを含んだ最後の部分はEVP_EncryptFinal_ex
で処理される。
OpenSSLはPKCSでパディングする。PKCSのパディング処理は足りないバイトの値で足りない分を埋めるんだけど、足りないバイトが0(データサイズが16の倍数)の場合は、1ブロックまるまるパディングが追加されるので、暗号化データのサイズには注意が必要になる。
復号化
EVP_CIPHER_CTX ctx = {}; EVP_CIPHER_CTX_init(&ctx); // 暗号化の設定 const unsigned char iv[16] = {}; EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv); // ブロックサイズで割り切れる部分の処理 int outl = 0; EVP_DecryptUpdate(&ctx, decrypted, &outl, data, data_size); // 最後のブロックの処理で、PKCSパディングのサイズを返す // パディングのデータは処理されないので、後処理は自分で行う int last = 0; EVP_DecryptFinal_ex(&ctx, decrypted + outl, &last); memset(decrypted + outl + last, 0, decrypted_size - outl - last); // remove padding EVP_CIPHER_CTX_cleanup(&ctx);
復号もEVP_DecryptUpdate
とEVP_DecryptFinal_ex
に分かれていて、EVP_DecryptFinal_ex
はパディングの値を返す。ただ、サイズを返すだけでデータ自体は処理されないので適宜処理してやる。