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