目的
RustでAES-256-CBCの暗号化と復号化をしてみます。試しにRubyで復号化してみます。
暗号化文字列の先頭には16byteのIVを格納しています。
Rustで暗号化復号化
Cargo.toml
aes = "0.7.5"
base64 = "0.13.0"
block-modes = "0.8.1"
bytebuffer = "0.2.1"
rand = "0.8.4"
main.rs
use aes::Aes256;
use block_modes::{BlockMode, Cbc};
use block_modes::block_padding::Pkcs7;
use rand::seq::SliceRandom;
type AesCbc = Cbc<Aes256, Pkcs7>;
// ランダム文字列の元
const BASE_STR: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// IV用にランダム文字列生成
fn gen_ascii_chars(size: usize) -> String {
let mut rng = &mut rand::thread_rng();
String::from_utf8(
BASE_STR.as_bytes()
.choose_multiple(&mut rng, size)
.cloned()
.collect()
).unwrap()
}
// 暗号化
fn encrypt(key: &str, data: &str) -> String {
let iv_str = gen_ascii_chars(16);
let iv = iv_str.as_bytes();
let cipher = AesCbc::new_from_slices(key.as_bytes(), iv).unwrap();
let ciphertext = cipher.encrypt_vec(data.as_bytes());
let mut buffer = bytebuffer::ByteBuffer::from_bytes(iv);
buffer.write_bytes(&ciphertext);
base64::encode(buffer.to_bytes())
}
// 復号化
fn decrypt(key: &str, data: &str) -> String {
let bytes = base64::decode(data).unwrap();
let cipher = AesCbc::new_from_slices(key.as_bytes(), &bytes[0..16]).unwrap();
String::from_utf8(cipher.decrypt_vec(&bytes[16..]).unwrap()).unwrap()
}
fn main() {
let plaintext = "予定表~①💖ハンカクだ";
let key = "01234567012345670123456701234567";
let enc = encrypt(key, plaintext);
println!("{}", enc);
let dec = decrypt(key, &enc);
assert_eq!(plaintext, dec);
println!("{}", dec);
}
Rubyで復号化
main.rb
require 'openssl'
require 'base64'
key = "01234567012345670123456701234567"
encrypted_text = ARGV[0]
encrypted_data = Base64.decode64(encrypted_text)
dec = OpenSSL::Cipher.new('AES-256-CBC')
dec.decrypt
dec.key = key
dec.iv = encrypted_data[0..15]
decrypted_data = dec.update(encrypted_data[16..]) + dec.final
decrypted_data.force_encoding("UTF-8")
puts decrypted_data
puts decrypted_data == "予定表~①💖ハンカクだ"