encrypt and decrypt property file value in java

后端 未结 4 798
执念已碎
执念已碎 2020-12-30 06:04

I am looking for a way to encrypt a password in a configuration file that is being read by a Java program. Currently, I read-in the password from the text file, but that lea

相关标签:
4条回答
  • 2020-12-30 06:50

    Here are some helpers to encrypt or decrypt using AES in Java:

    public static final String AES = "AES";
    
    /**
     * Encrypt a value and generate a keyfile.
     * If the keyfile is not found, then a new one will be created.
     * 
     * @throws GeneralSecurityException
     * @throws IOException if an I/O error occurs
     */
    public static String encrypt(String value, File keyFile)
            throws GeneralSecurityException, IOException {
        if (!keyFile.exists()) {
            KeyGenerator keyGen = KeyGenerator.getInstance(CryptoUtils.AES);
            keyGen.init(128);
            SecretKey sk = keyGen.generateKey();
            FileWriter fw = new FileWriter(keyFile);
            fw.write(byteArrayToHexString(sk.getEncoded()));
            fw.flush();
            fw.close();
        }
    
        SecretKeySpec sks = getSecretKeySpec(keyFile);
        Cipher cipher = Cipher.getInstance(CryptoUtils.AES);
        cipher.init(Cipher.ENCRYPT_MODE, sks, cipher.getParameters());
        byte[] encrypted = cipher.doFinal(value.getBytes());
        return byteArrayToHexString(encrypted);
    }
    
    /**
     * Decrypt a value.
     * 
     * @throws GeneralSecurityException
     * @throws IOException if an I/O error occurs
     */
    public static String decrypt(String message, File keyFile)
            throws GeneralSecurityException, IOException {
        SecretKeySpec sks = getSecretKeySpec(keyFile);
        Cipher cipher = Cipher.getInstance(CryptoUtils.AES);
        cipher.init(Cipher.DECRYPT_MODE, sks);
        byte[] decrypted = cipher.doFinal(hexStringToByteArray(message));
        return new String(decrypted);
    }
    
    private static SecretKeySpec getSecretKeySpec(File keyFile)
            throws NoSuchAlgorithmException, IOException {
        byte[] key = readKeyFile(keyFile);
        SecretKeySpec sks = new SecretKeySpec(key, CryptoUtils.AES);
        return sks;
    }
    
    private static byte[] readKeyFile(File keyFile)
            throws FileNotFoundException {
        Scanner scanner = new Scanner(keyFile).useDelimiter("\\Z");
        String keyValue = scanner.next();
        scanner.close();
        return hexStringToByteArray(keyValue);
    }
    
    private static String byteArrayToHexString(byte[] b) {
        StringBuffer sb = new StringBuffer(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            int v = b[i] & 0xff;
            if (v < 16) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(v));
        }
        return sb.toString().toUpperCase();
    }
    
    private static byte[] hexStringToByteArray(String s) {
        byte[] b = new byte[s.length() / 2];
        for (int i = 0; i < b.length; i++) {
            int index = i * 2;
            int v = Integer.parseInt(s.substring(index, index + 2), 16);
            b[i] = (byte) v;
        }
        return b;
    }
    

    Just call the appropiate method.

    0 讨论(0)
  • 2020-12-30 07:00

    Take a look at Jasypt. It has already done the heavy lifting for you. Specifically, the org.jasypt.encryption.pbe.StandardPBEStringEncryptor and org.jasypt.properties.PropertyValueEncryptionUtils classes.

    Create an encryptor:

    SimplePBEConfig config = new SimplePBEConfig(); 
    config.setAlgorithm("PBEWithMD5AndTripleDES");
    config.setKeyObtentionIterations(1000);
    config.setPassword("propertiesFilePassword");
    
    StandardPBEStringEncryptor encryptor = new org.jasypt.encryption.pbe.StandardPBEStringEncryptor();
    encryptor.setConfig(config);
    encryptor.initialize();
    

    Then use PropertyValueEncryptionUtils to encrypt / decrypt values:

    PropertyValueEncryptionUtils.encrypt(value, encryptor);
    PropertyValueEncryptionUtils.decrypt(encodedValue, encryptor)
    

    Note the encoded value will start with ENC( and end with ), so it's easy to tell if a property from a file is encrypted.

    Also, note that the password used for config.setPassword() is not the password you are encoding to store in the properties file. Instead, it is the password to encrypt / decrypt the value you are storing. What this password is and how to set it is up to you. I default to the fully qualified classname of whatever is reading the Properties file.

    Finally, if you are using Spring, Jasypt has an EncryptablePropertyPlaceholderConfigurer class that you can use to load the properties file and use ${foo} syntax in your Spring XML files to do variable substitution for things like DB passwords.

    0 讨论(0)
  • 2020-12-30 07:02

    I am having trouble with the string-->encrytped bytes-->string conversions.

    I'd stuff the byte array through a base64 en/decoder, this way you'll have to persist strings that contain nothing but chars within (a subset of) ASCII, which should limit your trouble. Have a look e.g. at commons codecs and replace your new String(decrypted) with a call to one of the static methods in the org.apache.commons.codec.binary.Base64 class.

    Besides that I think what you ultimately want to do is not strictly to "encrypt" the password but rather to store only a hash of the password, which was already discussed on SO.

    0 讨论(0)
  • 2020-12-30 07:03

    A really simple solution would be to use Base64 encoding, see the code snippet below :-

    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    ...
    
    private String encode(String str) {
        BASE64Encoder encoder = new BASE64Encoder();
        str = new String(encoder.encodeBuffer(str.getBytes()));
        return str;
    }
    
    private String decode(String str) {
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            str = new String(decoder.decodeBuffer(str));
        } catch (IOException e) {
            e.printStackTrace();
        }       
        return str;
    }
    
    ...
    
    0 讨论(0)
提交回复
热议问题