Techioz Blog

Java で暗号化されたものを復号化する際の Ruby 暗号エラー

概要

別のプロバイダーから暗号化リクエストを受け取りました。そのプロバイダーは AES GCM No Padding を使用していました。 Rubyで復号化しようとすると、OpenSSL::Cipher::CipherError()というエラーが発生します。 Java では IV が 16 バイト (ゼロの配列) を受け入れているのに対し、Ruby では 12 バイトのみに制限されていることがわかりました。ここで何かが欠けています。事前のご協力に感謝いたします

Java のコード スニペット

SecretKey sessionKey = getSessionKey();
byte[] IV = new byte[16];
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(sessionKey.getEncoded(), "AES");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * 8, IV);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
byte[] encryptedText = cipher.doFinal(plaintext);
responseMap.put("data", Base64.getEncoder().encodeToString(encryptedText));

Ruby のコード スニペット

decrypted_key = "AES KEY"
decode_data = Base64.strict_decode64(params["data"])
cipher_text_with_auth_tag = decode_data.unpack("C*")
auth_tag = cipher_text_with_auth_tag.last(16).pack("C*")
cipher_text = cipher_text_with_auth_tag[0..-17].pack("c*")
decipher = OpenSSL::Cipher.new('AES-256-GCM')
decipher. decrypt
decipher.padding = 0
decipher.key = decrypted_key
decipher.iv =  "\x00" * 12
decipher.auth_data = ''
decipher.auth_tag = auth_tag
decrypted_data = decipher.update(cipher_text) + decipher.final

解決策

OpenSSL では異なる IV/ノンス長を使用できますが、最初に iv_len= を呼び出す必要があります。

次のようなものが機能するはずです:

decipher = OpenSSL::Cipher.new('AES-256-GCM')
decipher.decrypt
decipher.key = key

# Call iv_len= before iv=
decipher.iv_len = iv_len # e.g. 16 in your case
decipher.iv = iv

decipher.auth_data = ''
decipher.auth_tag = auth_tag

decrypted_data = decipher.update(encrypted_data) + decipher.final()