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

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

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

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

OpenSSL

OpenSSLはSSL/TLSのプロトコルと一般的な暗号のライブラリを導入するオープンソースのソフトウェアのツールキットです。

暗号化

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

Q&A

解決済

2回答

7010閲覧

opensslコマンドで暗号化された文字列をJavaで復号したい

fishStory

総合スコア10

Java

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

OpenSSL

OpenSSLはSSL/TLSのプロトコルと一般的な暗号のライブラリを導入するオープンソースのソフトウェアのツールキットです。

暗号化

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

1グッド

1クリップ

投稿2020/02/14 12:06

編集2020/02/17 04:29

opensslコマンドで暗号化された文字列をJavaで復号したい

#前提・実現したいこと
PostgreSQLのDBに、Pythonツールで暗号化したパスワードが格納されています。
JavaでそのパスワードをDBから取得し、復号して平文に戻したいです。

Pythonツールでは以下、Linuxコマンドのopensslを使って暗号化しています。

Base64 =============================================================================== [root]# echo "hoge" | openssl enc -e -des -base64 -k "test" U2FsdGVkX196J+27IM+QRwos2qbm9tpu ===============================================================================

Linux上でコマンドを使用すれば複合できることは確認しています。

=============================================================================== [root]# echo "U2FsdGVkX196J+27IM+QRwos2qbm9tpu" | openssl enc -d -des -base64 -k "test" hoge ===============================================================================

#環境

  • Eclipse IDE for Enterprise Java Developers.

 Version: 2019-12 (4.14.0)

  • OS windows8(64bit)
  • JavaSE 1.8
  • Springboot

開発は上記Windows環境で実施していますが、最終的にはwarにしてLinuxで動かします。

#作成したJavaソース
以下が私が作成したJavaのソースになります。
暗号にはECBモード,CBCモードなどがあるようですが、OpenSSLで暗号化した場合どのモードを使用すればよいかもよくわかっていません。
以下ではECBを使用しています。

java

1package com.example.demo; 2 3import java.util.Base64; 4 5import javax.crypto.Cipher; 6import javax.crypto.spec.SecretKeySpec; 7 8public class test { 9 10 public static void main(String[] args) throws Exception { 11 12 //キー 13 String key = "test"; 14 //複号対象文字列 15 String enc = "2FsdGVkX196J+27IM+QRwos2qbm9tpu"; 16 17 18 byte[] enc_decode = Base64.getDecoder().decode(enc.getBytes()); 19 20 SecretKeySpec skey = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 21 22 Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 23 cipher.init(Cipher.DECRYPT_MODE, skey); 24 byte[] decrypted = cipher.doFinal(enc_decode); 25 26 System.out.println(decrypted); ←ここで「hoge」と出てほしい 27 } 28} 29 30 31

#実行結果
上記のソースを実行すると、エラーがでます。
Springbootのフレームワークを使用しており、Springスタータープロジェクトの配下に作成したクラスのためSpringBootアプリケーションから実行した結果です。

Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 4 bytes

at java.base/com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:90) at java.base/com.sun.crypto.provider.ElectronicCodeBook.init(ElectronicCodeBook.java:95) at java.base/com.sun.crypto.provider.CipherCore.init(CipherCore.java:591) at java.base/com.sun.crypto.provider.CipherCore.init(CipherCore.java:467) at java.base/com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:313) at java.base/javax.crypto.Cipher.implInit(Cipher.java:839) at java.base/javax.crypto.Cipher.chooseProvider(Cipher.java:901) at java.base/javax.crypto.Cipher.init(Cipher.java:1286) at java.base/javax.crypto.Cipher.init(Cipher.java:1223) at com.example.demo.test.main(test.java:23)

「Invalid AES key length:」をGoogle検索して関係ありそうな以下も試してみましたが、効果はありませんでした。

  • C:\pleiades\java\8\jre\lib\security\java.security
    → 「crypto.policy=unlimited」のコメントを外して有効にする

参考:ttps://itdogkuwaccho.hatenadiary.com/entry/2017/11/12/125140

以上、よろしくお願いします。

##2020/2/17追記

DES形式でソースを修正しました。

java

1 public static void main(String[] args) { 2 3 String key = "foobar00"; 4 String origin = "hoge"; 5 String enc = "U2FsdGVkX19eAkcLovbInztwfaMnjKwZ"; 6 7 8 try { 9 /* 10 * 鍵 11 */ 12 // 秘密鍵を準備 13 byte[] kagi = key.getBytes(); 14 DESKeySpec dk = new DESKeySpec(kagi); 15 Arrays.fill(kagi, (byte)0x00); // セキュリティ情報を上書きして削除 16 SecretKeyFactory kf = SecretKeyFactory.getInstance("DES"); 17 SecretKey sk = kf.generateSecret(dk); 18 19 20 Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); 21 cipher.init(Cipher.DECRYPT_MODE, sk); 22 Cipher c = Cipher.getInstance("DES"); 23 24 //暗号化されたStringをデコード 25 byte[] enc_decode = Base64.getDecoder().decode(enc.getBytes()); 26 27 //復号 28 byte[] output2 = c.doFinal(enc_decode); 29 30 31 // 表示 32 System.out.println("The string was "); 33 System.out.println(new String(output2)); 34 35 36 } catch (Exception e) { 37 e.printStackTrace(); 38 } 39 } 40

#実行結果
上記のソースを実行すると、下記エラーがでます。

javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.

at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975) at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056) at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853) at java.base/com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314) at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2202) at com.example.demo.test2.main(test2.java:133)
TN8001👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

注意 私は何もわかっていません。

GitHubを適当に探していたらこちらが見つかりました。
fgtrjhyu/openssl-des-decord-in-java: decode in java: echo -n "Hello,world" | openssl enc -des -a -k MyKey

例示の2つでは正しく取れているようです。

Java

1import java.nio.charset.Charset; 2import java.security.MessageDigest; 3import java.util.Base64; 4import java.util.Base64.Decoder; 5import javax.crypto.Cipher; 6import javax.crypto.spec.IvParameterSpec; 7import javax.crypto.spec.SecretKeySpec; 8 9class Main { 10 public static void main(String[] args) throws Exception { 11 String key = "test"; 12 String enc = "U2FsdGVkX196J+27IM+QRwos2qbm9tpu"; 13 String text = OpenSSLDecryptor.DES_MD5.decrypt(enc, key); 14 System.out.println(text); 15 16 key = "foobar00"; 17 enc = "U2FsdGVkX19eAkcLovbInztwfaMnjKwZ"; 18 text = OpenSSLDecryptor.DES_MD5.decrypt(enc, key); 19 System.out.println(text); 20 } 21} 22 23class OpenSSLDecryptor { 24 25 public static final OpenSSLDecryptor DES_MD5 = new OpenSSLDecryptor("DES", "MD5", 8); 26 private static final byte[] Salted__ = "Salted__".getBytes(); 27 28 public static byte[] decrypt(byte[] msg, byte[] pass, Cipher cip, String alg, MessageDigest md, int bs) throws Exception { 29 if (!eq(msg, 0, Salted__, 0, sizeof(Salted__))) { 30 throw new IllegalArgumentException("this ciphertext is not salted."); 31 } 32 md.reset(); 33 md.update(pass); 34 md.update(msg, Salted__.length, 8); 35 byte[] digest = md.digest(); 36 cip.init(Cipher.DECRYPT_MODE, new SecretKeySpec(digest, 0, bs, alg), new IvParameterSpec(digest, bs, bs)); 37 return cip.doFinal(msg, 16, sizeof(msg) - 16); 38 } 39 40 private static boolean eq(byte[] xs, int x, byte[] ys, int y, int len) { 41 return numeqs(xs, x, ys, y, len) == len; 42 } 43 44 private static int numeqs(byte[] xs, int x, byte[] ys, int y, int len) { 45 int i = 0; 46 final int lsz = sizeof(xs), rsz = sizeof(ys); 47 for (; (x < lsz) && (y < rsz) && (xs[x] == ys[y]) && (i < len); ++i, ++x, ++y) 48 ; 49 return i; 50 } 51 52 private static int sizeof(byte[] a) { 53 return a != null ? a.length : 0; 54 } 55 56 private final String alg; 57 private final int bs; 58 private final String md; 59 60 public OpenSSLDecryptor(String alg, String md, int bs) { 61 this.alg = alg; 62 this.md = md; 63 this.bs = bs; 64 } 65 66 public String decrypt(String message, String passphrase) throws Exception { 67 return decrypt(message, passphrase, Charset.defaultCharset()); 68 } 69 70 public String decrypt(String message, String passphrase, Charset cs) throws Exception { 71 Cipher cip = Cipher.getInstance(String.format("%s/CBC/PKCS5Padding", this.alg)); 72 MessageDigest md = MessageDigest.getInstance(this.md); 73 Decoder base64 = Base64.getDecoder(); 74 return new String(decrypt(base64.decode(message), passphrase.getBytes(cs), cip, this.alg, md, bs), cs); 75 } 76}

出力

hoge hoge

投稿2020/02/17 13:39

TN8001

総合スコア9244

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

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

fishStory

2020/02/18 09:02

回答ありがとうございます。 いただいたソースを使用したところ、無事復号することができました。 本当に感謝しています!!!
guest

0

試してないので回答はかけないんですが ご参考までに。

Invalid AES key length: 4 bytes

文字通り読むと、AES 鍵の長さが不正 ということですので 4バイト(32ビット)しかない キーの長さがよくないんでしょう。AES の 鍵長は128ビットと決まっています。

ただ、それよりも、DESで暗号化したものをAESで符号化していることに問題がありそうです。
DES暗号化と符号化のサンプルコードを検索してみて 試してください。

投稿2020/02/14 16:55

take88

総合スコア1351

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

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

fishStory

2020/02/17 04:26

回答ありがとうございます。確かにDESを指定しているのにAESで複号化しているのはおかしいかったです。調べてコードを書き直してみたのですが、「javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.」のエラーが出ます。 キーが不正だと怒られているようなのですが、暗号化されたStringをデコードしている箇所が間違っているのか、秘密鍵を準備しているところが間違っているのでしょうか。 作成しなおしたソースを追加で記載します。
take88

2020/02/17 15:44

エラーの原因はキーが合ってないんだと思います。 軽く調べてみましたが、色々と間違ってそうで、私の手には負えなそうなのがわかりました。すみませんが、力になれそうもありません。 openssl の暗号化の仕様ですが、出力されるデータは Salt 、IV のデータがヘッダーとして出力されてます。その後に、暗号化されたデータが続きます。そのデータがBASE64エンコードされてます。 Javaのプログラムで復号化するには、BASE64デコードした バイト列から、Slat、IV ヘッダーを読み取って、キー(バイト列)を生成して、その生成したキーを使って 複合する感じですが、どうやって 実現すればいいか わかりませんでした。 「-des」の場合は調べても分かりませんでしたが、「-aes-128-cbc」の場合はサンプルコードがあったので調べてみてください。 https://alpha.mixi.co.jp/entry/2007/10639/
fishStory

2020/02/18 09:01

回答ありがとうございます。 もう少し調べてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問