1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package davmail.util;
21
22 import davmail.Settings;
23
24 import javax.crypto.BadPaddingException;
25 import javax.crypto.Cipher;
26 import javax.crypto.SecretKey;
27 import javax.crypto.SecretKeyFactory;
28 import javax.crypto.spec.IvParameterSpec;
29 import javax.crypto.spec.PBEKeySpec;
30 import javax.crypto.spec.PBEParameterSpec;
31 import java.io.IOException;
32 import java.nio.charset.StandardCharsets;
33 import java.security.NoSuchAlgorithmException;
34 import java.security.spec.InvalidKeySpecException;
35
36
37
38
39
40 public class StringEncryptor {
41 static final String ALGO = "PBEWithHmacSHA256AndAES_128";
42 static final String DEFAULT_FINGERPRINT = "davmailgateway!&";
43
44 private final String password;
45
46 public StringEncryptor(String password) {
47 this.password = password;
48 }
49
50 public String encryptString(String value) throws IOException {
51 if (value == null) {
52 return null;
53 }
54 if (value.isEmpty()) {
55 return "";
56 }
57 try {
58 byte[] plaintext = value.getBytes(StandardCharsets.UTF_8);
59
60
61 Cipher enc = Cipher.getInstance(ALGO);
62 enc.init(Cipher.ENCRYPT_MODE, getSecretKey(), getPBEParameterSpec());
63 byte[] encrypted = enc.doFinal(plaintext);
64 return "{AES}" + IOUtil.encodeBase64AsString(encrypted);
65
66 } catch (Exception e) {
67 throw new IOException(e);
68 }
69 }
70
71 public String decryptString(String value) throws IOException {
72 if (value != null && value.startsWith("{AES}")) {
73 try {
74 byte[] encrypted = IOUtil.decodeBase64(value.substring(5));
75
76 Cipher dec = Cipher.getInstance(ALGO);
77 dec.init(Cipher.DECRYPT_MODE, getSecretKey(), getPBEParameterSpec());
78 byte[] decrypted = dec.doFinal(encrypted);
79 return new String(decrypted, StandardCharsets.UTF_8);
80
81 } catch (BadPaddingException e) {
82 throw new IOException("Unable to decrypt token, invalid password");
83 } catch (Exception e) {
84 throw new IOException(e);
85 }
86 } else {
87 return value;
88 }
89 }
90
91 private SecretKey getSecretKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
92 PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
93
94 SecretKeyFactory kf = SecretKeyFactory.getInstance(ALGO);
95 return kf.generateSecret(keySpec);
96 }
97
98 private PBEParameterSpec getPBEParameterSpec() {
99 byte[] bytes = Settings.getProperty("davmail.oauth.fingerprint", DEFAULT_FINGERPRINT).getBytes(StandardCharsets.UTF_8);
100 return new PBEParameterSpec(bytes, 10000, new IvParameterSpec(bytes));
101 }
102 }