質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

暗号化

ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

Q&A

解決済

1回答

2541閲覧

Rubyで暗号化してJavaで復号がしたい

yuri_program

総合スコア1

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

暗号化

ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

0グッド

0クリップ

投稿2021/11/15 07:29

編集2021/11/15 10:44

前提・実現したいこと

プログラミング初心者です。よろしくお願いします。
Rubyで暗号化して、Javaで復号するプログラムを作りたいのですが上手くいきません…
Javaで復号しようとすると、以下のエラーメッセージが出てしまい、困っています。

発生している問題・エラーメッセージ

Exception in thread "main" javax.crypto.AEADBadTagException: Tag mismatch! at com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:620) at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1116) at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1053) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853) at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) at javax.crypto.Cipher.doFinal(Cipher.java:2168) at decrypted2.main(decrypted2.java:25)

該当のソースコード

Ruby

1# 暗号化するRubyファイル 2 3require 'openssl' 4require 'base64' 5 6cipher = OpenSSL::Cipher.new('aes-256-gcm') 7cipher.encrypt 8iv = cipher.random_iv 9key = cipher.random_key 10auth_tag = 'authtag' 11cipher.auth_data = auth_tag 12plainText = 'my secret data' 13 14cipherText = cipher.update(plainText) + cipher.final 15 16# Javaに連携するデータを取得 17p Base64.strict_encode64(cipherText) # -> "NzCmNt2+BO9xBOkdD6g=" 18p Base64.strict_encode64(iv) # -> "1xF2aTB8KP9JW4Dl" 19p Base64.strict_encode64(cipher.auth_tag) # -> "m0m6f6XX6p+JxsfRtoa4DQ==" 20p Base64.strict_encode64(key) # -> "3O3oUShs7SYm92SJGBHY4iwUDppMQctXDWMMzmMYBnU="

Java

1// 復号するJavaファイル 2import java.util.Base64; 3import javax.crypto.*; 4import javax.crypto.spec.*; 5import java.util.Arrays; 6 7public class decrypted2 { 8 9 public static void main(String[] args) throws Exception { 10 byte[] cipherText = Base64.getDecoder().decode("NzCmNt2+BO9xBOkdD6g="); // encrypted data 11 byte[] myIv = Base64.getDecoder().decode("1xF2aTB8KP9JW4Dl"); // iv 12 byte[] auth_tag = Base64.getDecoder().decode("m0m6f6XX6p+JxsfRtoa4DQ=="); // auth_tag 13 int myTLen = 128; // auth_tagビット長(16バイト) 14 byte[] secretKey = Base64.getDecoder().decode("3O3oUShs7SYm92SJGBHY4iwUDppMQctXDWMMzmMYBnU"); // secretKey 15 SecretKeySpec myKey = new SecretKeySpec(secretKey, "AES"); 16 17 // 暗号化後文字列とauth_tagを連結する 18 byte[] ciTxt_tag = new byte[cipherText.length + auth_tag.length]; 19 System.arraycopy(auth_tag, 0, ciTxt_tag, 0, auth_tag.length); 20 System.arraycopy(cipherText, 0, ciTxt_tag, auth_tag.length, cipherText.length); 21 22 GCMParameterSpec myParams = new GCMParameterSpec(myTLen, myIv); 23 Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); 24 c.init(Cipher.DECRYPT_MODE, myKey, myParams); 25 26 byte[] recoveredText = c.doFinal(ciTxt_tag); 27 28 System.out.println("復号後の文字列: " + recoveredText); 29 } 30}

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ruby 2.5.0p0
java version "1.8.0_311"

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/11/15 07:57

「複合」では無く「復号」では・・・
jimbe

2021/11/15 08:00

コードはファイル毎に分けてそれぞれにマークダウン記法を適用してください。
yuri_program

2021/11/15 08:44

jimbeさん ご指摘ありがとうございます。 ・誤字を訂正しました ・コードをファイル毎に分けて、それぞれマークダウン記法としました
jimbe

2021/11/15 09:16

修正ありがとうございます。
jimbe

2021/11/15 09:45

暗号の各用語から分かっていないのですが(^^;スイマセン) コードの見た目(?) からして、 auth_tag 配列は myTLen 分のバイト数が必要なのではないでしょうか。元の文字列が短かった場合に残りのバイトに何が入るべきなのかは分からないのですが・・・。
jimbe

2021/11/15 10:32

ごめんなさい、 myTLen のコメントに惑わされてしまいました。 GCMParameterSpec の第一パラメータですのでバイトでなくビットでした。
yuri_program

2021/11/15 10:42

jimbeさん ありがとうございます。 すみません、16バイトですね。コメントが良くなかったです… 復号のときに、doFinalに暗号化後文字列とauth_tagを連結して渡しているのですが、 これが合っているのかよくわからないんです…う〜ん…
jimbe

2021/11/15 11:05

とりあえず java で Ruby と同じ暗号化が出来ればその復号化を書けるかと思って暗号化を試したりしているのですが、如何せん暗号の知識がどうにも^^;
yuri_program

2021/11/15 13:03

jimbeさん すみません、私もそんなに暗号化詳しくはなくて… auth_tag と auth_data は別物で、今回は auth_data を使っていないと考えてもらって、たぶん大丈夫だと思います。
jimbe

2021/11/15 13:09

しかし、 > cipher.auth_data = auth_tag とされていますけど・・・ cipher.auth_tag = auth_tag なのでしょうか。
yuri_program

2021/11/15 13:39

jimbeさん 申し訳ありません! jimbeさんが仰る通りでした… > cipher.auth_data = auth_tag これは間違いでした…回答頂いた方にコメントいたします。
jimbe

2021/11/15 13:44

この修正で各結果文字列が変わったりはしないでしょうか。
yuri_program

2021/11/15 13:54

jimbeさん そうですね…変わってしまいます。 取得し直しました><
guest

回答1

0

ベストアンサー

※まだ回答になっていません。

2 Java暗号化アーキテクチャ(JCA)リファレンス・ガイド の「例2-2 GCMモードでAES Cipherを使用するサンプル・コード」を元に以下のコードで暗号化を試した所、

java

1 static void sampleGcmAesEnctipt() { 2 byte[] key = Base64.getDecoder().decode("3O3oUShs7SYm92SJGBHY4iwUDppMQctXDWMMzmMYBnU"); // secretKey 3 SecretKey myKey = new SecretKeySpec(key, "AES"); 4 5 byte[] plainText = "my secret data".getBytes(); 6 int myTLen = 128; 7 byte[] myIv = Base64.getDecoder().decode("1xF2aTB8KP9JW4Dl"); // iv 8 9 try { 10 GCMParameterSpec myParams = new GCMParameterSpec(myTLen, myIv); 11 Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); 12 c.init(Cipher.ENCRYPT_MODE, myKey, myParams); 13 14 byte[] cipherText = new byte[c.getOutputSize(plainText.length)]; 15 int actualOutputLen = c.doFinal(plainText, 0, plainText.length, cipherText); 16 17 System.out.println("actualOutputLen="+actualOutputLen); 18 System.out.println("cipherText="+Arrays.toString(cipherText)); 19 System.out.println("base64="+new String(Base64.getEncoder().encode(cipherText))); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 }

結果

plain

1actualOutputLen=30 2cipherText=[55, 48, -90, 54, -35, -66, 4, -17, 113, 4, -23, 29, 15, -88, -68, 4, 45, 13, -83, 4, 79, -118, 106, 35, -22, -33, 32, -64, -28, -78] 3base64=NzCmNt2+BO9xBOkdD6i8BC0NrQRPimoj6t8gwOSy

となりまして、base64 の前のほうは

p Base64.strict_encode64(cipherText) # -> "NzCmNt2+BO9xBOkdD6g="

とほぼ同じになりました。
auth のデータを(まだ)渡していないはずですが、続く部分は何でしょう。

投稿2021/11/15 11:56

jimbe

総合スコア12648

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuri_program

2021/11/15 13:16

jimbeさん ありがとうございますっ! たぶんですけど、Javaの方は続く部分が auth_tag かもしれません… dofinalの説明をみたら、暗号化の際は認証タグが追加されると書いてありました(※) Javaの方は勝手に auth_tag が付いてくるのでしょうか… ※こちらです。 https://docs.oracle.com/javase/jp/8/docs/api/javax/crypto/Cipher.html Rubyの方は auth_tag が付かないみたいなので、連結してJavaに渡してみましたがダメでした…
jimbe

2021/11/15 13:42

byte[] auth_tag = Base64.getDecoder().decode("m0m6f6XX6p+JxsfRtoa4DQ=="); // auth_tag を c.updateAAD(auth_tag); として暗号化・base64化してみたのですが、 actualOutputLen=30 cipherText=[55, 48, -90, 54, -35, -66, 4, -17, 113, 4, -23, 29, 15, -88, 97, 65, -67, -38, 71, 55, 76, -16, 2, -115, -5, 115, -103, -112, -3, -13] base64=NzCmNt2+BO9xBOkdD6hhQb3aRzdM8AKN+3OZkP3z で、後半が auth_tag なのか分かりません。どうも違うような…^^;;;
yuri_program

2021/11/15 13:45

jimbeさん jimbeさんのお陰でJavaで復号することができました。 私のコードですが、2箇所間違いがありました… 1つ目のRubyの方ですが、 > auth_tag = 'authtag' > cipher.auth_data = auth_tag これは誤りでした。auth_tag と勘違いして auth_dataを設定?していました。 なので、コメントアウトしました。 # auth_tag = 'authtag' # cipher.auth_data = auth_tag 2つ目のJavaの方ですが、 > System.arraycopy(auth_tag, 0, ciTxt_tag, 0, auth_tag.length); > System.arraycopy(cipherText, 0, ciTxt_tag, auth_tag.length, cipherText.length); 順番が違いました… 暗号化後の文字列 + auth_tag となるように修正しました。 System.arraycopy(cipherText, 0, ciTxt_tag, 0, cipherText.length); System.arraycopy(auth_tag, 0, ciTxt_tag, cipherText.length, auth_tag.length); これで、Rubyで暗号化して、Javaで復号することができました! 本当にありがとうございます。 ベストアンサーとさせていただきます。
jimbe

2021/11/15 13:50

おー、おめでとうございます。 ということは・・・? 暗号化には(見た目) auth が全く関与しないのに java では何か付いているということに?
yuri_program

2021/11/15 13:59

jimbeさん そうなんです…たぶん、この暗号モード?(aes-256-gcm)だと auth_tag は勝手に付くみたいです。 Rubyも付いているみたいで、cipher.auth_tag を呼ぶと、付いている auth_tag が取れたので それをJavaに渡して、暗号化後の文字列と連結して復号してあげると認証されるみたいです。 暗号復号に関しては、理解が浅くてすみません… jimbeさんのお陰で、本当に助かりました。 ありがとうございます!
jimbe

2021/11/15 14:06

いや、私も全然ですので・・・ま、まぁ、なんとかなったということで今から深堀すると大変そうなので、また機会ありましたら^^;;; おつかれさまでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問