[解決済み] 設定ファイルのパスワードを暗号化しますか?[クローズド]
質問
設定ファイルからサーバ情報を読み込むプログラムがあるのですが、その設定ファイルのパスワードを暗号化し、プログラムで読み込んで復号化したいのですが、可能でしょうか?
必要なもの
- ファイルに格納される平文のパスワードを暗号化する。
- ファイルから読み込んだ暗号化されたパスワードを自プログラムから復号する。
これを行う方法について、何か推奨されるものはありますか?私は自分自身のアルゴリズムを書くことを考えていましたが、それはひどく安全でないと感じます。
どのように解決するのですか?
簡単な方法としては、JavaのPassword Based Encryptionを使用することです。これは、パスワードを使用してテキストを暗号化および復号化することができます。
これは基本的に、初期化された
javax.crypto.Cipher
をアルゴリズムで初期化することです。
"AES/CBC/PKCS5Padding"
からキーを取得し
javax.crypto.SecretKeyFactory
を使って
"PBKDF2WithHmacSHA512"
というアルゴリズムがあります。
以下はコード例です (安全性の低い MD5 ベースの変種を置き換えるために更新されています)。
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class ProtectedConfigFile {
public static void main(String[] args) throws Exception {
String password = System.getProperty("password");
if (password == null) {
throw new IllegalArgumentException("Run with -Dpassword=<password>");
}
// The salt (probably) can be stored along with the encrypted data
byte[] salt = new String("12345678").getBytes();
// Decreasing this speeds down startup time and can be useful during testing, but it also makes it easier for brute force attackers
int iterationCount = 40000;
// Other values give me java.security.InvalidKeyException: Illegal key size or default parameters
int keyLength = 128;
SecretKeySpec key = createSecretKey(password.toCharArray(),
salt, iterationCount, keyLength);
String originalPassword = "secret";
System.out.println("Original password: " + originalPassword);
String encryptedPassword = encrypt(originalPassword, key);
System.out.println("Encrypted password: " + encryptedPassword);
String decryptedPassword = decrypt(encryptedPassword, key);
System.out.println("Decrypted password: " + decryptedPassword);
}
private static SecretKeySpec createSecretKey(char[] password, byte[] salt, int iterationCount, int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
SecretKey keyTmp = keyFactory.generateSecret(keySpec);
return new SecretKeySpec(keyTmp.getEncoded(), "AES");
}
private static String encrypt(String property, SecretKeySpec key) throws GeneralSecurityException, UnsupportedEncodingException {
Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
pbeCipher.init(Cipher.ENCRYPT_MODE, key);
AlgorithmParameters parameters = pbeCipher.getParameters();
IvParameterSpec ivParameterSpec = parameters.getParameterSpec(IvParameterSpec.class);
byte[] cryptoText = pbeCipher.doFinal(property.getBytes("UTF-8"));
byte[] iv = ivParameterSpec.getIV();
return base64Encode(iv) + ":" + base64Encode(cryptoText);
}
private static String base64Encode(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
private static String decrypt(String string, SecretKeySpec key) throws GeneralSecurityException, IOException {
String iv = string.split(":")[0];
String property = string.split(":")[1];
Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
pbeCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(base64Decode(iv)));
return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
}
private static byte[] base64Decode(String property) throws IOException {
return Base64.getDecoder().decode(property);
}
}
一つ問題が残っています。パスワードを暗号化するために使用するパスワードはどこに保存すればよいのでしょうか。ソース ファイルに保存して難読化することもできますが、再びそれを見つけるのはそれほど難しくありません。あるいは、Javaプロセスを開始するときにシステムプロパティとして与えることもできます(
-DpropertyProtectionPassword=...
).
KeyStore を使用する場合も同じ問題が残りますが、これもパスワードで保護されています。基本的に、どこかに1つのマスターパスワードを持っている必要があり、それを保護するのはかなり困難です。
関連
-
Java エラー報告 スレッド "main" での例外 java.util.NoSuchElementException
-
java の例外が発生しました java
-
をインスタンス化することができません。
-
eclipseにプロジェクトをインポートした後、Editorにmain typeが含まれない問題
-
Spring boot runs with Error creating bean with name 'entityManagerFactory' defined in class path resource
-
VMの初期化中にエラーが発生しました java/lang/NoClassDefFoundError: java/lang/Object
-
このラインで複数のマーカーを解決する方法
-
[解決済み] 後で平文を取り出すためのユーザーパスワードの保管について、倫理的にどのように取り組むべきでしょうか?
-
[解決済み】JSP 2を使用して、JSPファイル内のJavaコードを回避するにはどうすればよいですか?
-
[解決済み] 双方向の暗号化 検索可能なパスワードを保存したい
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
スタイルが読み込まれず、ブラウザコンソールでエラーが報告される。リソースはスタイルシートとして解釈されますが、MIMEタイプtext/htmlで転送されます。
-
スレッド "main "での例外をEclipseで解決 java.lang.Error: 未解決のコンパイル問題、コンパイラとパッケージの不整合
-
undefinedeclipse エラー。この行に複数のアノテーションが見つかりました: - 文字列を型解決に解決できない
-
Javaクラスローダーにソースコードから潜り込む
-
this()の呼び出しはコンストラクタ本体の最初の文でなければならない 例外解決と原因分析
-
エラーの解決方法 jarfile XXX.jarにアクセスできません。
-
Spring BootのテストメソッドFailed to load ApplicationContextの問題を解決する
-
javaでクラスを作成すると、enclosing classでないように見える
-
SocketTimeoutExceptionの解決方法です。読み込みがタイムアウトした
-
SocketTimeoutExceptionです。読み込みがタイムアウトしました