Java の構成ファイルでパスワードを暗号化する
暗号化は、暗号化キー
と呼ばれるパラメータと組み合わせた暗号化アルゴリズムを使用して、プレーンテキスト情報を読み取り不可能な形式に変換するプロセスです。判読できない形式は、暗号文
形式としてよく知られています。復号化キー
を持っている人だけがデータを復号化し、元の平文を復元できます。
構成ファイル内のパスワードの暗号化の問題は、次の 2つのサブタスクに分けることができます。
- ファイルにあるプレーンテキストのパスワードを暗号化します。
- ファイルから読み込まれた暗号化されたパスワードを復号化します。
まず、src/conf/
パスに config.properties
ファイルという名前の構成ファイルを作成しましょう。
password = TestPassword123
次に、構成ファイルを読み取るために、Properties
クラスをインスタンス化します。コンストラクターを使用して、FileInputStream
クラスのインスタンスを作成できます。構成ファイルのパスを入力として受け取ります。これで、プロパティクラスのインスタンスを使用してプロパティをロードします。クラスにプロパティファイルをロードするには、load
メソッドを使用します。これにより、InputStreamReader
インスタンスがパラメータとして取得されます。この入力ストリームに不正な形式の Unicode エスケープシーケンスが含まれている場合は IllegalArgumentException
がスローされ、入力ストリームからの読み取り中にエラーが発生した場合は IOException
がスローされます。
プロパティが正常に読み込まれたら、getProperty()
メソッドを使用して、プロパティリストで指定されたキーを持つプロパティを検索します。プロパティが見つからない場合、メソッドは null
を返します。このような状況を処理するために外部チェックを行い、ファイルからパスワードが null であることが判明した場合は、IllegalArgumentException
をスローします。
salt
は、パスワード文字列に追加する任意のランダムな文字列で作成されます。
createSecretKey
は SecretKeySpec
キーを返すユーザー定義のメソッドであり、キーの使用はパスワードを暗号化および復号化することです。encrypt
メソッドと decrypt
メソッドが使用されます-Encryption
クラスで指定された定義済みの static
メソッド。
以下は、同じことを示すサンプルコードです。
package fileDataEncryption;
import static fileDataEncryption.Encryption.*;
import java.io.FileInputStream;
import java.util.Properties;
import javax.crypto.spec.SecretKeySpec;
public class ConfigFileEncryption {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
FileInputStream inputStream = new FileInputStream("src/conf/config.properties");
properties.load(inputStream);
String password = properties.getProperty("password");
if (password == null) {
throw new IllegalArgumentException("No such parameter present in config file");
}
byte[] salt = new String("12345678").getBytes();
int iterationCount = 40000;
int keyLength = 128;
SecretKeySpec key = createSecretKey(password.toCharArray(), salt, iterationCount, keyLength);
String originalPassword = password;
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);
}
}
Encryption
クラスのユーザー定義メソッドの詳細な説明は次のとおりです。
createSecretKey
は、password
、salt
、iterationCount
、keyLength
などのパラメーターを受け取る関数です。password
は、構成ファイル内の実際のパスワードです。暗号化では、salt
は、データ、パスワード、またはパスフレーズをハッシュする追加入力として使用するランダムデータです。salts
の使用は、ストレージ内のパスワードを保護することです。アルゴリズムが実行する必要のある反復回数として、iterationCount
変数を使用します。変数の値を小さくすると、起動時間が短縮されるため、テスト中に役立ちますが、ブルートフォース攻撃者にとっても簡単になります。keyLength
変数は、最終的に導出する必要のあるキーの長さです。使用したメソッドからスローされた例外をスローします。getInstance
メソッドは、最も優先されるプロバイダーから始めて、登録されたセキュリティプロバイダーのリストをトラバースします。要求された秘密鍵アルゴリズムの標準名を受け取り、新しいSecretKeyFactory
オブジェクトを返します。指定されたアルゴリズムが null の場合はNullPointerException
をスローし、指定されたアルゴリズムのSecretKeyFactorySpi
実装をサポートするプロバイダーがない場合はNoSuchAlgorithmException
をスローします。PBEKeySpec
は、可変キーサイズの PBE 暗号のPBEKey
を生成するために、パスワード、ソルト、反復回数、および派生キーの長さを受け取るクラスコンストラクターです。salt
がnull
の場合はNullPointerException
をスローし、salt が空の場合はIllegalArgumentException
をスローします。generateSecret
は、提供されたキー仕様またはキーマテリアルからSecretKey
オブジェクトを生成します。秘密鍵の指定が必要です。指定された仕様がこの秘密鍵ファクトリが分類された鍵値を生成するのに不適切な場合、InvalidKeySpecException
をスローします。
Encryption
クラスの encrypt
メソッドの詳細。
encrypt
メソッドは、暗号化するデータとキーの 2つのパラメーターを取ります。このメソッドは、その中の子メソッドからスローされた例外をスローします。getInstance
メソッドは、最も優先されるプロバイダーから始めて、登録されたセキュリティプロバイダーのリストをトラバースします。これは、変換の名前、つまり AES / CBC / PKCS5Padding を取ります。変更が null、空、無効な形式の場合はNoSuchAlgorithmException
をスローし、変更に使用できないパディングスキームが含まれている場合はNoSuchPaddingException
をスローします。init
メソッドは、操作モードの値に応じて、暗号化、復号化、キーの折り返し、またはキーのアンラップの 4つの操作のいずれかのために暗号
を初期化します。この場合、ENCRYPT_MODE
。このメソッドは、操作モードが無効な場合はUnsupportedOperationException
をスローし、指定されたキーが不適切な場合はInvalidKeyException
をスローします。getParameters
は、この暗号で使用されるパラメーターを返します。getParameterSpec
は、パラメータオブジェクトの仕様を返します。paramSpec
パラメータは、パラメータが返す必要のある仕様クラスを識別します。たとえば、パラメータがDSAParameterSpec
クラスのインスタンスで返される必要があることを示すのは、DSAParameterSpec.class
である可能性があります。doFinal
メソッドは、単一部分の作業でデータを暗号化または復号化するか、複数部分の操作を終了します。データは、暗号の初期化方法に応じて、暗号化または復号化されます。base64Encode
は、Base64
エンコードスキームを使用して、指定されたバイト配列を文字列にエンコードするプライベートメソッドです。decrypt
メソッドで使用される関数は、上記のメソッドと同様です。唯一の違いは、操作モードとして関数DECRYPT_MODE
で指定されたモード
に基づいて動作が異なることです。
package fileDataEncryption;
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 Encryption {
public 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");
}
public static String encrypt(String dataToEncrypt, 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(dataToEncrypt.getBytes("UTF-8"));
byte[] iv = ivParameterSpec.getIV();
return base64Encode(iv) + ":" + base64Encode(cryptoText);
}
private static String base64Encode(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
public 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);
}
}
以下は、構成ファイル内のパスワードを暗号化および復号化するために記述されたコードの出力です。
Original password: TestPassword123
Encrypted password: Hy7fbIwpyKgp0oileu+oLg==:WNRknMJz/8u8GmWlCZFPFA==
Decrypted password: TestPassword123
Rashmi is a professional Software Developer with hands on over varied tech stack. She has been working on Java, Springboot, Microservices, Typescript, MySQL, Graphql and more. She loves to spread knowledge via her writings. She is keen taking up new things and adopt in her career.
LinkedIn