/
Crypto.java
187 lines (163 loc) · 5.62 KB
/
Crypto.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package play.libs;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import play.Play;
import play.exceptions.UnexpectedException;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Cryptography utils
*/
public class Crypto {
/**
* Define a hash type enumeration for strong-typing
*/
public enum HashType {
MD5("MD5"), SHA1("SHA-1"), SHA256("SHA-256"), SHA512("SHA-512");
private final String algorithm;
HashType(String algorithm) {
this.algorithm = algorithm;
}
@Override
public String toString() {
return this.algorithm;
}
}
/**
* Set-up MD5 as the default hashing algorithm
*/
private static final HashType DEFAULT_HASH_TYPE = HashType.MD5;
static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* Sign a message using the application secret key (HMAC-SHA1)
*
* @param message
* the message to sign
* @return The signed message
*/
public static String sign(String message) {
return sign(message, Play.secretKey.getBytes());
}
/**
* Sign a message with a key
*
* @param message
* The message to sign
* @param key
* The key to use
* @return The signed message (in hexadecimal)
*/
public static String sign(String message, byte[] key) {
if (key.length == 0) {
return message;
}
try {
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA1");
mac.init(signingKey);
byte[] messageBytes = message.getBytes(UTF_8);
byte[] result = mac.doFinal(messageBytes);
int len = result.length;
char[] hexChars = new char[len * 2];
for (int charIndex = 0, startIndex = 0; charIndex < hexChars.length;) {
int bite = result[startIndex++] & 0xff;
hexChars[charIndex++] = HEX_CHARS[bite >> 4];
hexChars[charIndex++] = HEX_CHARS[bite & 0xf];
}
return new String(hexChars);
} catch (Exception ex) {
throw new UnexpectedException(ex);
}
}
/**
* Create a password hash using the default hashing algorithm
*
* @param input
* The password
* @return The password hash
*/
public static String passwordHash(String input) {
return passwordHash(input, DEFAULT_HASH_TYPE);
}
/**
* Create a password hash using specific hashing algorithm
*
* @param input
* The password
* @param hashType
* The hashing algorithm
* @return The password hash
*/
public static String passwordHash(String input, HashType hashType) {
try {
MessageDigest m = MessageDigest.getInstance(hashType.toString());
byte[] out = m.digest(input.getBytes());
return new String(Base64.encodeBase64(out));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* Encrypt a String with the AES encryption standard using the application secret
*
* @param value
* The String to encrypt
* @return An hexadecimal encrypted string
*/
public static String encryptAES(String value) {
return encryptAES(value, Play.configuration.getProperty("application.secret").substring(0, 16));
}
/**
* Encrypt a String with the AES encryption standard. Private key must have a length of 16 bytes
*
* @param value
* The String to encrypt
* @param privateKey
* The key used to encrypt
* @return An hexadecimal encrypted string
*/
public static String encryptAES(String value, String privateKey) {
try {
byte[] raw = privateKey.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return Codec.byteToHexString(cipher.doFinal(value.getBytes()));
} catch (Exception ex) {
throw new UnexpectedException(ex);
}
}
/**
* Decrypt a String with the AES encryption standard using the application secret
*
* @param value
* An hexadecimal encrypted string
* @return The decrypted String
*/
public static String decryptAES(String value) {
return decryptAES(value, Play.configuration.getProperty("application.secret").substring(0, 16));
}
/**
* Decrypt a String with the AES encryption standard. Private key must have a length of 16 bytes
*
* @param value
* An hexadecimal encrypted string
* @param privateKey
* The key used to encrypt
* @return The decrypted String
*/
public static String decryptAES(String value, String privateKey) {
try {
byte[] raw = privateKey.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return new String(cipher.doFinal(Codec.hexStringToByte(value)));
} catch (Exception ex) {
throw new UnexpectedException(ex);
}
}
}