LoginSignup
7
4

RustとRubyでAES-256-CBCの暗号化・復号化をする

Last updated at Posted at 2023-06-05

目的

以前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
7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4