You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java SE自定义密钥加密字符串及文本文件读写解密方案求助

Java SE Implementation for Password-Based String Encryption/Decryption with File Persistence

Got it, let's tackle this problem step by step. You want a Java SE solution to encrypt a string with a custom password, save the encrypted text to a file, then later read it back and decrypt it. I'll use standard Java crypto libraries (no external dependencies) that follow modern security best practices—no sketchy custom algorithms here.

Core Approach

I’m using these components for a secure, robust implementation:

  • AES-GCM: Authenticated encryption that ensures both confidentiality and integrity (prevents tampering with the encrypted file)
  • PBKDF2WithHmacSHA256: Derives a secure encryption key from your password (never use the raw password as a key directly—this makes brute-force attacks way harder)
  • We’ll store all required decryption data in the file: salt, IV, ciphertext, and authentication tag (AES-GCM needs all these to decrypt safely)

Full Implementation Code

Create a utility class EncryptionUtils.java—it handles all the heavy lifting with clear comments:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;

public class EncryptionUtils {
    // Security configuration - adjust based on your needs
    private static final int AES_KEY_SIZE = 256; // 128 is also acceptable if 256 isn't allowed
    private static final int GCM_TAG_LENGTH = 128; // Bits, standard for GCM integrity checks
    private static final int PBKDF2_ITERATIONS = 65536; // Higher = slower, more secure
    private static final int SALT_LENGTH = 16; // Random salt for key derivation
    private static final int IV_LENGTH = 12; // Recommended IV length for GCM

    // Encrypt a string with a password and save to target file
    public static void encryptAndSave(String plaintext, String password, String filePath) throws Exception {
        // Generate random salt (unique per encryption)
        byte[] salt = new byte[SALT_LENGTH];
        new SecureRandom().nextBytes(salt);

        // Generate random IV (unique per encryption)
        byte[] iv = new byte[IV_LENGTH];
        new SecureRandom().nextBytes(iv);

        // Derive AES key from password using PBKDF2
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, PBKDF2_ITERATIONS, AES_KEY_SIZE);
        SecretKey tmpKey = factory.generateSecret(spec);
        SecretKey aesKey = new SecretKeySpec(tmpKey.getEncoded(), "AES");

        // Initialize AES-GCM cipher for encryption
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.ENCRYPT_MODE, aesKey, gcmSpec);

        // Encrypt the plaintext
        byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));

        // Encode all binary data to Base64 for safe text file storage
        String saltBase64 = Base64.getEncoder().encodeToString(salt);
        String ivBase64 = Base64.getEncoder().encodeToString(iv);
        String ciphertextBase64 = Base64.getEncoder().encodeToString(ciphertext);

        // Combine parts with a delimiter that won't appear in Base64
        String combinedData = saltBase64 + "|||" + ivBase64 + "|||" + ciphertextBase64;

        // Write to file
        Files.write(Paths.get(filePath), combinedData.getBytes(StandardCharsets.UTF_8));
    }

    // Read encrypted file and decrypt with password
    public static String loadAndDecrypt(String filePath, String password) throws Exception {
        // Read combined data from file
        String combinedData = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);

        // Split into individual components
        String[] parts = combinedData.split("\\|\\|\\|");
        if (parts.length != 3) {
            throw new IllegalArgumentException("Invalid encrypted file format—may be tampered with");
        }

        // Decode Base64 back to binary
        byte[] salt = Base64.getDecoder().decode(parts[0]);
        byte[] iv = Base64.getDecoder().decode(parts[1]);
        byte[] ciphertext = Base64.getDecoder().decode(parts[2]);

        // Derive the same AES key using password and stored salt
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, PBKDF2_ITERATIONS, AES_KEY_SIZE);
        SecretKey tmpKey = factory.generateSecret(spec);
        SecretKey aesKey = new SecretKeySpec(tmpKey.getEncoded(), "AES");

        // Initialize AES-GCM cipher for decryption
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.DECRYPT_MODE, aesKey, gcmSpec);

        // Decrypt and convert back to string
        byte[] plaintextBytes = cipher.doFinal(ciphertext);
        return new String(plaintextBytes, StandardCharsets.UTF_8);
    }

    // Example usage
    public static void main(String[] args) {
        String secretMessage = "This is my top-secret data that no one else should see!";
        String userPassword = "MyStrongCustomPassword123!";
        String encryptedFile = "secret_data.txt";

        try {
            // Encrypt and save
            encryptAndSave(secretMessage, userPassword, encryptedFile);
            System.out.println("Successfully encrypted and saved to: " + encryptedFile);

            // Decrypt and verify
            String decryptedMessage = loadAndDecrypt(encryptedFile, userPassword);
            System.out.println("Decrypted message: " + decryptedMessage);
        } catch (Exception e) {
            // In production, handle specific exceptions (e.g., wrong password = BadPaddingException)
            e.printStackTrace();
        }
    }
}

Key Best Practices & Notes

  • Never hardcode passwords: In real apps, fetch passwords from user input (console prompt, GUI, or secure vault) instead of hardcoding.
  • Error handling: The example uses a generic try-catch, but in production, handle specific exceptions like BadPaddingException (indicates wrong password or tampered file) to give meaningful feedback.
  • Security parameters: Adjust PBKDF2_ITERATIONS (higher = more secure but slower) and AES_KEY_SIZE based on your compliance needs. 65536 iterations and 256-bit AES are industry standard.
  • SecureRandom: Always use SecureRandom (cryptographically secure) for generating salts/IVs—never use Random for crypto operations.
  • File storage: We use Base64 to avoid binary data corruption in text files. For binary storage, you can write raw bytes directly (just ensure you read them in the correct order with fixed lengths).

How to Test

  1. Compile the class: javac EncryptionUtils.java
  2. Run it: java EncryptionUtils
  3. You’ll see secret_data.txt created, and the decrypted message printed to the console.
  4. Try using the wrong password in loadAndDecrypt—you’ll get a BadPaddingException (expected behavior for invalid credentials).

内容的提问来源于stack exchange,提问作者Samadhi Gunaratna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:24:40