Rubyで暗号化したデータをJavaで復号化、またその逆を行ってみた。
今回はAES128ビットの暗号化モードCBC、パディングはPKCS#5で実施。
まずRuby側のコード。
require 'openssl' require 'base64' class CryptUtil def self.encrypt(pass, value) enc = OpenSSL::Cipher.new('aes-128-cbc') # 暗号化or復号化どちらを行うかセット(今回は暗号化)、復号化の場合はdecrypt enc.encrypt # ivを生成 iv = OpenSSL::Random.random_bytes(16) # 暗号化する際のキー文字列をセット enc.key = pass # ivをセット enc.iv = iv crypted = "" crypted << enc.update(value) # 暗号化 crypted << enc.final # 暗号化した文字列と暗号化に使用したivをBase64エンコードして返却 return Base64.b64encode(crypted), Base64.b64encode(iv) end def self.decrypt(pass, encrypted, iv) dec = OpenSSL::Cipher.new('aes-128-cbc') # 暗号化する際のキー文字列をセット dec.key = pass # Base64エンコードされたivをデコードしてセット dec.iv = Base64.decode64(iv) unless iv.nil? dec.decrypt plain_text = "" plain_text << dec.update(Base64.decode64(encrypted)) plain_text << dec.final return plain_text end end
Cipherを使用する際にkey,ivメソッドで暗号化する際のキーとiv(初期ベクトル)を指定するようにしているのは、ivがわからないと復号化できないため。通常、暗号化する際はCipher#pkcs5_keyivgenを使用する。ただpkcs5_keyivgenは内部でivを生成するんだけど、そのivを取得する仕組みが無いため、今回は↑みたいにkey,ivメソッドでそれぞれキーとivを指定した。
続いてJava側の実装。
public class CryptUtil { /** * 暗号化 * @param src 暗号化対象の文字列 * @param key 暗号化に使用する文字列(128bit) * @param iv 暗号化に使用する初期ベクトル(Base64エンコードされた値) */ public static String encrypt(String src, String key, String iv) { try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); Key skey = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec param = new IvParameterSpec(decodeBase64(iv)); cipher.init(Cipher.ENCRYPT_MODE, skey, param); return encodeBase64(cipher.doFinal(src.getBytes())); } catch (Exception e) { throw new RuntimeException(e); } } /** * 復号化 * @param src 復号化対象の文字列(Base64デコードされた状態) * @param key 暗号化の際に使用した文字列(128bit) * @param iv 暗号化で使用した初期ベクトル(Base64エンコードされた値) */ public static String decrypt(byte[] src, String key, String iv) { try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); Key skey = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec param = new IvParameterSpec(decodeBase64(iv)); cipher.init(Cipher.DECRYPT_MODE, skey, param); return new String(cipher.doFinal(src)); } catch (Exception e) { throw new RuntimeException(e); } } private static byte[] decodeBase64(String value) throws Exception { return new BASE64Decoder().decodeBuffer(value); } private static String encodeBase64(byte[] value) throws Exception { return new BASE64Encoder().encodeBuffer(value); } }