14
14
import org .joda .time .format .DateTimeFormatter ;
15
15
import org .json .JSONObject ;
16
16
17
+ import javax .crypto .KeyGenerator ;
17
18
import javax .crypto .Mac ;
19
+ import javax .crypto .SecretKey ;
18
20
import javax .crypto .spec .SecretKeySpec ;
19
21
import java .io .File ;
20
22
import java .io .IOException ;
26
28
import java .security .InvalidKeyException ;
27
29
import java .security .NoSuchAlgorithmException ;
28
30
import java .util .ArrayList ;
31
+ import java .util .Base64 ;
29
32
import java .util .HashMap ;
30
33
import java .util .Map ;
31
34
import java .util .Random ;
@@ -303,6 +306,7 @@ private RequestBody getBody(Map<String, String> data, @Nullable Map<String, File
303
306
private Map <String , String > toPayload (Map <String , Object > data ) throws LocalOperationException {
304
307
Map <String , Object > dataClone = new HashMap <String , Object >(data );
305
308
dataClone .put ("auth" , getAuthData ());
309
+ dataClone .put ("nonce" , getNonce ("AES" , 256 ));
306
310
307
311
Map <String , String > payload = new HashMap <String , String >();
308
312
payload .put ("params" , jsonifyData (dataClone ));
@@ -350,14 +354,14 @@ private Map<String, String> getAuthData() {
350
354
*/
351
355
private String getSignature (String message ) throws LocalOperationException {
352
356
byte [] kSecret = transloadit .secret .getBytes (Charset .forName ("UTF-8" ));
353
- byte [] rawHmac = hmacSHA1 (kSecret , message );
357
+ byte [] rawHmac = hmacSHA384 (kSecret , message );
354
358
byte [] hexBytes = new Hex ().encode (rawHmac );
355
-
356
- return new String ( hexBytes , Charset . forName ( "UTF-8" )) ;
359
+ String signature = "sha384:" + new String ( hexBytes , Charset . forName ( "UTF-8" ));
360
+ return signature ;
357
361
}
358
362
359
- private byte [] hmacSHA1 (byte [] key , String data ) throws LocalOperationException {
360
- final String algorithm = "HmacSHA1 " ;
363
+ private byte [] hmacSHA384 (byte [] key , String data ) throws LocalOperationException {
364
+ final String algorithm = "HmacSHA384 " ;
361
365
Mac mac ;
362
366
363
367
try {
@@ -371,6 +375,25 @@ private byte[] hmacSHA1(byte[] key, String data) throws LocalOperationException
371
375
return mac .doFinal (data .getBytes (Charset .forName ("UTF-8" )));
372
376
}
373
377
378
+ /**
379
+ * Generates a strong cryptographic nonce in order to make the request's signature unique.
380
+ * @param cipher Algorithm to derive key with
381
+ * @param lengthInBits Length of the generated key in bits
382
+ * @return A Key formatted as String
383
+ */
384
+ protected String getNonce (String cipher , int lengthInBits ) {
385
+ KeyGenerator keyGenerator = null ;
386
+ try {
387
+ keyGenerator = KeyGenerator .getInstance (cipher );
388
+ } catch (NoSuchAlgorithmException e ) {
389
+ throw new RuntimeException (e );
390
+ }
391
+ keyGenerator .init (lengthInBits );
392
+ SecretKey secKey = keyGenerator .generateKey ();
393
+ String encodedKey = Base64 .getEncoder ().encodeToString (secKey .getEncoded ());
394
+ return encodedKey ;
395
+ }
396
+
374
397
/**
375
398
* Helper method, which performs a retryRateLimit action if a POST request has hit the servers rate limit.
376
399
* All parameters of the failed POST request should be provided to this method.
0 commit comments