17
17
import javax .crypto .Mac ;
18
18
import javax .crypto .SecretKey ;
19
19
import javax .crypto .spec .IvParameterSpec ;
20
+ import javax .xml .bind .DatatypeConverter ;
20
21
import java .io .ByteArrayOutputStream ;
21
22
import java .io .IOException ;
22
23
import java .security .GeneralSecurityException ;
35
36
import java .security .spec .X509EncodedKeySpec ;
36
37
import java .util .ArrayList ;
37
38
import java .util .Arrays ;
38
- import java .util .Base64 ;
39
39
import java .util .List ;
40
40
import java .util .Map ;
41
41
import java .util .regex .Matcher ;
42
42
import java .util .regex .Pattern ;
43
- import java .util .stream .Collectors ;
44
43
45
44
/**
46
45
* Static lib containing methods for handling encryption.
@@ -189,9 +188,9 @@ public static String getPrivateKeyFormattedString(KeyPair keyPair) {
189
188
*/
190
189
private static String getPrivateKeyFormattedString (PrivateKey privateKey ) {
191
190
byte [] encodedPrivateKey = privateKey .getEncoded ();
192
- byte [] base64 = Base64 . getEncoder (). encode (encodedPrivateKey );
191
+ String privateKeyString = DatatypeConverter . printBase64Binary (encodedPrivateKey );
193
192
194
- return String .format (PRIVATE_KEY_FORMAT , new String ( base64 ) );
193
+ return String .format (PRIVATE_KEY_FORMAT , privateKeyString );
195
194
}
196
195
197
196
/**
@@ -230,7 +229,7 @@ private static byte[] getAllPublicKeyByteFromFormattedString(String publicKeyStr
230
229
publicKeyString = publicKeyString .replace (PUBLIC_KEY_END , STRING_EMPTY );
231
230
publicKeyString = publicKeyString .replace (NEWLINE , STRING_EMPTY );
232
231
233
- return Base64 . getDecoder (). decode (publicKeyString );
232
+ return DatatypeConverter . parseBase64Binary (publicKeyString );
234
233
}
235
234
236
235
/**
@@ -257,7 +256,7 @@ private static byte[] getAllPrivateKeyByteFromFormattedString(String privateKeyS
257
256
privateKeyString = privateKeyString .replace (PRIVATE_KEY_END , STRING_EMPTY );
258
257
privateKeyString = privateKeyString .replace (NEWLINE , STRING_EMPTY );
259
258
260
- return Base64 . getDecoder (). decode (privateKeyString );
259
+ return DatatypeConverter . parseBase64Binary (privateKeyString );
261
260
}
262
261
263
262
public static String getPublicKeyFormattedString (KeyPair keyPair ) {
@@ -269,9 +268,9 @@ public static String getPublicKeyFormattedString(KeyPair keyPair) {
269
268
*/
270
269
public static String getPublicKeyFormattedString (PublicKey publicKey ) {
271
270
byte [] encodedPublicKey = publicKey .getEncoded ();
272
- byte [] base64 = Base64 . getEncoder (). encode (encodedPublicKey );
271
+ String publicKeyString = DatatypeConverter . printBase64Binary (encodedPublicKey );
273
272
274
- return String .format (PUBLIC_KEY_FORMAT , new String ( base64 ) );
273
+ return String .format (PUBLIC_KEY_FORMAT , publicKeyString );
275
274
}
276
275
277
276
/**
@@ -308,22 +307,27 @@ private static byte[] generateInitializationVector() {
308
307
return initializationVector ;
309
308
}
310
309
311
- private static void addHeaderClientEncryptionKey (ApiContext apiContext , SecretKey key ,
312
- Map <String , String > customHeaders ) {
310
+ private static void addHeaderClientEncryptionKey (
311
+ ApiContext apiContext ,
312
+ SecretKey key ,
313
+ Map <String , String > customHeaders
314
+ ) {
313
315
try {
314
316
Cipher cipher = Cipher .getInstance (KEY_CIPHER_ALGORITHM );
315
317
cipher .init (Cipher .ENCRYPT_MODE , apiContext .getInstallationContext ().getPublicKeyServer ());
316
318
byte [] keyEncrypted = cipher .doFinal (key .getEncoded ());
317
- String keyEncryptedEncoded = Base64 . getEncoder (). encodeToString (keyEncrypted );
319
+ String keyEncryptedEncoded = DatatypeConverter . printBase64Binary (keyEncrypted );
318
320
customHeaders .put (HEADER_CLIENT_ENCRYPTION_KEY , keyEncryptedEncoded );
319
321
} catch (GeneralSecurityException exception ) {
320
322
throw new BunqException (exception .getMessage ());
321
323
}
322
324
}
323
325
324
- private static void addHeaderClientEncryptionIv (byte [] initializationVector , Map <String ,
325
- String > customHeaders ) {
326
- String initializationVectorEncoded = Base64 .getEncoder ().encodeToString (initializationVector );
326
+ private static void addHeaderClientEncryptionIv (
327
+ byte [] initializationVector ,
328
+ Map <String , String > customHeaders
329
+ ) {
330
+ String initializationVectorEncoded = DatatypeConverter .printBase64Binary (initializationVector );
327
331
328
332
customHeaders .put (HEADER_CLIENT_ENCRYPTION_IV , initializationVectorEncoded );
329
333
}
@@ -357,7 +361,7 @@ private static void addHeaderClientEncryptionHmac(byte[] requestBytes,
357
361
bufferedSink .flush ();
358
362
bufferedSink .close ();
359
363
byte [] hmac = mac .doFinal ();
360
- String hmacEncoded = Base64 . getEncoder (). encodeToString (hmac );
364
+ String hmacEncoded = DatatypeConverter . printBase64Binary (hmac );
361
365
customHeaders .put (HEADER_CLIENT_ENCRYPTION_HMAC , hmacEncoded );
362
366
} catch (GeneralSecurityException | IOException exception ) {
363
367
throw new BunqException (exception .getMessage ());
@@ -412,16 +416,27 @@ private static byte[] getEntityBodyBytes(BunqRequestBuilder requestBuilder) thro
412
416
}
413
417
414
418
private static String generateRequestHeadersSortedString (BunqRequestBuilder bunqRequestBuilder ) {
415
- return Arrays .stream (bunqRequestBuilder .getAllHeaderAsArray ())
416
- .filter (
417
- header ->
418
- header .getName ().startsWith (HEADER_NAME_PREFIX_X_BUNQ ) ||
419
- header .getName ().equals (ApiClient .HEADER_CACHE_CONTROL ) ||
420
- header .getName ().equals (ApiClient .HEADER_USER_AGENT )
421
- )
422
- .map (header -> header .getName () + DELIMITER_HEADER_NAME_AND_VALUE + header .getValue ())
423
- .sorted ()
424
- .collect (Collectors .joining (NEWLINE ));
419
+ StringBuilder stringBuilder = new StringBuilder ();
420
+
421
+ BunqBasicHeader [] allHeadersAsArray = bunqRequestBuilder .getAllHeaderAsArray ();
422
+ Arrays .sort (allHeadersAsArray );
423
+
424
+ for (BunqBasicHeader header : allHeadersAsArray ) {
425
+ if (header .getName ().startsWith (HEADER_NAME_PREFIX_X_BUNQ ) ||
426
+ header .getName ().equals (ApiClient .HEADER_CACHE_CONTROL ) ||
427
+ header .getName ().equals (ApiClient .HEADER_USER_AGENT )) {
428
+ if (stringBuilder .length () != 0 ) {
429
+ stringBuilder .append (NEWLINE );
430
+ }
431
+
432
+ stringBuilder
433
+ .append (header .getName ())
434
+ .append (DELIMITER_HEADER_NAME_AND_VALUE )
435
+ .append (header .getValue ());
436
+ }
437
+ }
438
+
439
+ return stringBuilder .toString ();
425
440
}
426
441
427
442
/**
@@ -439,7 +454,7 @@ private static String signBase64(byte[] bytesToSign, KeyPair keyPair) throws Bun
439
454
byte [] dataBytesSigned = signDataWithSignature (signature , bytesToSign );
440
455
verifyDataSigned (signature , keyPair .getPublic (), bytesToSign , dataBytesSigned );
441
456
442
- return Base64 . getEncoder (). encodeToString (dataBytesSigned );
457
+ return DatatypeConverter . printBase64Binary (dataBytesSigned );
443
458
}
444
459
445
460
private static Signature getSignatureInstance () throws BunqException {
@@ -500,8 +515,9 @@ public static void validateResponseSignature(
500
515
HEADER_SERVER_SIGNATURE ,
501
516
response .header (HEADER_SERVER_SIGNATURE )
502
517
);
503
- byte [] serverSignatureBase64Bytes = headerServerSignature .getValue ().getBytes ();
504
- byte [] serverSignatureDecoded = Base64 .getDecoder ().decode (serverSignatureBase64Bytes );
518
+ byte [] serverSignatureDecoded = DatatypeConverter .parseBase64Binary (
519
+ headerServerSignature .getValue ()
520
+ );
505
521
verifyDataSigned (signature , keyPublicServer , responseBytes , serverSignatureDecoded );
506
522
}
507
523
@@ -561,16 +577,25 @@ private static byte[] getResponseHeadBytes(int responseCode, BunqBasicHeader[] r
561
577
return requestHeadString .getBytes ();
562
578
}
563
579
564
- private static String generateResponseHeadersSortedString (BunqBasicHeader [] responseHeaders ) {
565
- return Arrays .stream (responseHeaders )
566
- .filter (
567
- header ->
568
- header .getName ().startsWith (HEADER_NAME_PREFIX_X_BUNQ ) &&
569
- !header .getName ().equals (HEADER_SERVER_SIGNATURE )
570
- )
571
- .map (header -> header .getName () + DELIMITER_HEADER_NAME_AND_VALUE + header .getValue ())
572
- .sorted ()
573
- .collect (Collectors .joining (NEWLINE ));
580
+ private static String generateResponseHeadersSortedString (BunqBasicHeader [] allResponseHeader ) {
581
+ StringBuilder stringBuilder = new StringBuilder ();
582
+ Arrays .sort (allResponseHeader );
583
+
584
+ for (BunqBasicHeader header : allResponseHeader ) {
585
+ if (header .getName ().startsWith (HEADER_NAME_PREFIX_X_BUNQ ) &&
586
+ !header .getName ().equals (HEADER_SERVER_SIGNATURE )) {
587
+ if (stringBuilder .length () != 0 ) {
588
+ stringBuilder .append (NEWLINE );
589
+ }
590
+
591
+ stringBuilder
592
+ .append (header .getName ())
593
+ .append (DELIMITER_HEADER_NAME_AND_VALUE )
594
+ .append (header .getValue ());
595
+ }
596
+ }
597
+
598
+ return stringBuilder .toString ();
574
599
}
575
600
576
601
}
0 commit comments