25
25
import org .slf4j .Logger ;
26
26
import org .slf4j .LoggerFactory ;
27
27
28
+ import javax .crypto .Mac ;
29
+ import javax .crypto .spec .SecretKeySpec ;
30
+
28
31
import java .io .BufferedReader ;
29
32
import java .io .FileReader ;
30
33
import java .io .IOException ;
31
34
import java .lang .reflect .InvocationTargetException ;
35
+ import java .security .InvalidKeyException ;
32
36
import java .security .MessageDigest ;
33
37
import java .security .NoSuchAlgorithmException ;
38
+ import java .security .SecureRandom ;
34
39
import java .util .Arrays ;
35
40
import java .util .Objects ;
36
41
@@ -46,6 +51,12 @@ public class EncryptUtils {
46
51
47
52
private static volatile EncryptParameter encryptParam ;
48
53
54
+ private static final String HMAC_ALGORITHM = "HmacSHA256" ;
55
+ private static final int ITERATION_COUNT = 1024 ;
56
+ private static final int SALT_LENGTH = 16 ;
57
+ private static final int INT_SIZE = 4 ;
58
+ private static final int dkLen = 16 ;
59
+
49
60
public static String getNormalKeyStr () {
50
61
if (normalKeyStr == null ) {
51
62
synchronized (EncryptUtils .class ) {
@@ -106,6 +117,96 @@ public static String getEncryptKeyFromPath(String path) {
106
117
}
107
118
}
108
119
120
+ public static byte [] getEncryptKeyFromToken (String token ) {
121
+ if (token == null || token .trim ().isEmpty ()) {
122
+ return defaultKey .getBytes ();
123
+ }
124
+ byte [] salt = generateSalt ();
125
+ try {
126
+ return deriveKeyInternal (token .getBytes (), salt , ITERATION_COUNT , dkLen );
127
+ } catch (NoSuchAlgorithmException | InvalidKeyException e ) {
128
+ throw new EncryptException ("Error deriving key from token" , e );
129
+ }
130
+ }
131
+
132
+ private static byte [] deriveKeyInternal (byte [] password , byte [] salt , int c , int dkLen )
133
+ throws NoSuchAlgorithmException , InvalidKeyException {
134
+
135
+ int hLen = getPRFLength ();
136
+
137
+ if (dkLen < 1 ) {
138
+ throw new EncryptException ("main key's dkLen must be positive integer: " + dkLen );
139
+ }
140
+ if ((long ) dkLen > (long ) (Math .pow (2 , 32 ) - 1 ) * hLen ) {
141
+ throw new EncryptException ("main key's dkLen is too long: " + dkLen );
142
+ }
143
+
144
+ int n = (int ) Math .ceil ((double ) dkLen / hLen );
145
+ int r = dkLen - (n - 1 ) * hLen ;
146
+
147
+ byte [] blocks = new byte [n * hLen ];
148
+
149
+ for (int i = 1 ; i <= n ; i ++) {
150
+ byte [] block = F (password , salt , c , i );
151
+ System .arraycopy (block , 0 , blocks , (i - 1 ) * hLen , hLen );
152
+ }
153
+
154
+ return Arrays .copyOf (blocks , dkLen );
155
+ }
156
+
157
+ /** main function F */
158
+ private static byte [] F (byte [] password , byte [] salt , int c , int i )
159
+ throws NoSuchAlgorithmException , InvalidKeyException {
160
+
161
+ // U1 = PRF(P, S || INT(i))
162
+ byte [] input = concatenate (salt , intToBigEndian (i ));
163
+ byte [] U = prf (password , input );
164
+ byte [] result = U .clone ();
165
+
166
+ // U2 to Uc
167
+ for (int j = 2 ; j <= c ; j ++) {
168
+ U = prf (password , U );
169
+ xorBytes (result , U );
170
+ }
171
+
172
+ return result ;
173
+ }
174
+
175
+ /** PRF implementation (HMAC-SHA256) */
176
+ private static byte [] prf (byte [] key , byte [] data )
177
+ throws NoSuchAlgorithmException , InvalidKeyException {
178
+ Mac hmac = Mac .getInstance (HMAC_ALGORITHM );
179
+ hmac .init (new SecretKeySpec (key , HMAC_ALGORITHM ));
180
+ return hmac .doFinal (data );
181
+ }
182
+
183
+ private static int getPRFLength () throws NoSuchAlgorithmException {
184
+ return Mac .getInstance (HMAC_ALGORITHM ).getMacLength ();
185
+ }
186
+
187
+ private static byte [] generateSalt () {
188
+ byte [] salt = new byte [SALT_LENGTH ];
189
+ new SecureRandom ().nextBytes (salt );
190
+ return salt ;
191
+ }
192
+
193
+ private static byte [] intToBigEndian (int i ) {
194
+ return new byte [] {(byte ) (i >>> 24 ), (byte ) (i >>> 16 ), (byte ) (i >>> 8 ), (byte ) i };
195
+ }
196
+
197
+ private static void xorBytes (byte [] result , byte [] input ) {
198
+ for (int i = 0 ; i < result .length ; i ++) {
199
+ result [i ] ^= input [i ];
200
+ }
201
+ }
202
+
203
+ private static byte [] concatenate (byte [] a , byte [] b ) {
204
+ byte [] output = new byte [a .length + b .length ];
205
+ System .arraycopy (a , 0 , output , 0 , a .length );
206
+ System .arraycopy (b , 0 , output , a .length , b .length );
207
+ return output ;
208
+ }
209
+
109
210
public static byte [] hexStringToByteArray (String hexString ) {
110
211
int len = hexString .length ();
111
212
byte [] byteArray = new byte [len / 2 ];
@@ -139,11 +240,10 @@ public static String getNormalKeyStr(TSFileConfig conf) {
139
240
"SHA-256 algorithm not found while using SHA-256 to generate data key" , e );
140
241
}
141
242
md .update ("IoTDB is the best" .getBytes ());
142
- md .update (conf .getEncryptKey (). getBytes () );
243
+ md .update (conf .getEncryptKey ());
143
244
byte [] data_key = Arrays .copyOfRange (md .digest (), 0 , 16 );
144
245
data_key =
145
- IEncryptor .getEncryptor (conf .getEncryptType (), conf .getEncryptKey ().getBytes ())
146
- .encrypt (data_key );
246
+ IEncryptor .getEncryptor (conf .getEncryptType (), conf .getEncryptKey ()).encrypt (data_key );
147
247
148
248
StringBuilder valueStr = new StringBuilder ();
149
249
@@ -180,7 +280,7 @@ public static EncryptParameter getEncryptParameter(TSFileConfig conf) {
180
280
"SHA-256 algorithm not found while using SHA-256 to generate data key" , e );
181
281
}
182
282
md .update ("IoTDB is the best" .getBytes ());
183
- md .update (conf .getEncryptKey (). getBytes () );
283
+ md .update (conf .getEncryptKey ());
184
284
dataEncryptKey = Arrays .copyOfRange (md .digest (), 0 , 16 );
185
285
} else {
186
286
encryptType = "org.apache.tsfile.encrypt.UNENCRYPTED" ;
@@ -227,7 +327,7 @@ public static IEncrypt getEncrypt(TSFileConfig conf) {
227
327
"SHA-256 algorithm not found while using SHA-256 to generate data key" , e );
228
328
}
229
329
md .update ("IoTDB is the best" .getBytes ());
230
- md .update (conf .getEncryptKey (). getBytes () );
330
+ md .update (conf .getEncryptKey ());
231
331
dataEncryptKey = Arrays .copyOfRange (md .digest (), 0 , 16 );
232
332
} else {
233
333
encryptType = "org.apache.tsfile.encrypt.UNENCRYPTED" ;
0 commit comments