目的
以前RustでAES-256-CBC暗号化という記事を書きましたが、base64やaesなどのライブラリが新しくなったので書き直してみました。
前の記事ではRustで暗号化、復号化、Rubyで復号化でしたがRubyの暗号化も追加しました。
お互いで暗号化・復号化が正しく動作することを確認しました。
ivは暗号化した文字列の先頭16byteに配置しています。
コード
Cargo.toml
[package]
name = "crypt"
version = "0.1.0"
edition = "2021"
[dependencies]
aes = "0.8.2"
base64 = "0.21.2"
bytebuffer = "2.1.1"
cbc = { version = "0.1.2", features = ["std"] }
rand = "0.8.5"
main.rs
use aes::cipher::{KeyIvInit, block_padding::Pkcs7, BlockEncryptMut, BlockDecryptMut};
use base64::{Engine as _, engine::general_purpose};
use bytebuffer::ByteBuffer;
use rand::{distributions::{Alphanumeric, DistString}};
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
// 暗号化
fn encrypt(key: &str, data: &str) -> String {
let mut rng = rand::thread_rng();
let iv_str = Alphanumeric.sample_string(&mut rng, 16);
let iv = iv_str.as_bytes();
let cipher = Aes256CbcEnc::new(key.as_bytes().into(), iv.into())
.encrypt_padded_vec_mut::<Pkcs7>(data.as_bytes());
let mut buffer = ByteBuffer::from_bytes(iv);
buffer.write_bytes(&cipher);
general_purpose::STANDARD.encode(buffer.as_bytes())
}
// 復号化
fn decrypt(key: &str, data: &str) -> String {
let bytes = general_purpose::STANDARD.decode(data).unwrap();
let res = Aes256CbcDec::new(key.as_bytes().into(), bytes[0..16].into())
.decrypt_padded_vec_mut::<Pkcs7>(&bytes[16..])
.unwrap();
String::from_utf8(res).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);
let args: Vec<String> = std::env::args().collect();
if args.len() > 1 {
println!("{}", args[1]);
let dec = decrypt(key, &args[1]);
assert_eq!(plaintext, dec);
println!("{}", dec);
}
}
main.rb
require 'base64'
require 'openssl'
key = "01234567012345670123456701234567"
plain_text = "予定表~①💖ハンカクだ"
# 暗号化
def encrypt(key, data)
engine = OpenSSL::Cipher.new('AES-256-CBC')
engine.encrypt
engine.key = key
iv = engine.random_iv
res = engine.update(data) + engine.final
Base64.encode64(iv + res).gsub(/\n/, '')
end
# 複合化
def decrypt(key, data)
data = Base64.decode64(data)
engine = OpenSSL::Cipher.new('AES-256-CBC')
engine.decrypt
engine.key = key
engine.iv = data[0..15]
res = engine.update(data[16..]) + engine.final
res.force_encoding("UTF-8")
end
encrypted_data = encrypt(key, plain_text)
puts encrypted_data
decrypted_data = decrypt(key, encrypted_data)
puts decrypted_data
puts decrypted_data == plain_text
if ARGV.size() > 0
decrypted_data = decrypt(key, ARGV[0])
puts decrypted_data
puts decrypted_data == plain_text
end