16
16
import javax .crypto .Cipher ;
17
17
import javax .crypto .SecretKey ;
18
18
import javax .crypto .spec .GCMParameterSpec ;
19
- import java .io .ByteArrayInputStream ;
20
- import java .io .ByteArrayOutputStream ;
21
- import java .io .DataInputStream ;
22
- import java .io .DataOutputStream ;
23
- import java .io .IOException ;
19
+ import java .nio .ByteBuffer ;
24
20
import java .security .GeneralSecurityException ;
25
21
import java .security .InvalidKeyException ;
26
22
import java .security .Key ;
27
- import java .security .SecureRandom ;
28
23
import java .util .Map ;
29
24
30
25
/**
@@ -34,54 +29,46 @@ class AesGcmJceKeyCipher extends JceKeyCipher {
34
29
private static final int NONCE_LENGTH = 12 ;
35
30
private static final int TAG_LENGTH = 128 ;
36
31
private static final String TRANSFORMATION = "AES/GCM/NoPadding" ;
37
- private final SecureRandom rnd = new SecureRandom ();
38
32
39
33
AesGcmJceKeyCipher (SecretKey key ) {
40
34
super (key , key );
41
35
}
42
36
43
37
private static byte [] specToBytes (final GCMParameterSpec spec ) {
44
38
final byte [] nonce = spec .getIV ();
45
- final ByteArrayOutputStream baos = new ByteArrayOutputStream ();
46
- try (final DataOutputStream dos = new DataOutputStream (baos )) {
47
- dos .writeInt (spec .getTLen ());
48
- dos .writeInt (nonce .length );
49
- dos .write (nonce );
50
- dos .close ();
51
- baos .close ();
52
- } catch (final IOException ex ) {
53
- throw new AssertionError ("Impossible exception" , ex );
54
- }
55
- return baos .toByteArray ();
39
+ final byte [] result = new byte [Integer .BYTES + Integer .BYTES + nonce .length ];
40
+ final ByteBuffer buffer = ByteBuffer .wrap (result );
41
+ buffer .putInt (spec .getTLen ());
42
+ buffer .putInt (nonce .length );
43
+ buffer .put (nonce );
44
+ return result ;
56
45
}
57
46
58
47
private static GCMParameterSpec bytesToSpec (final byte [] data , final int offset ) throws InvalidKeyException {
59
- final ByteArrayInputStream bais = new ByteArrayInputStream (data , offset , data .length - offset );
60
- try (final DataInputStream dis = new DataInputStream (bais )) {
61
- final int tagLen = dis .readInt ();
62
- final int nonceLen = dis .readInt ();
48
+ final ByteBuffer buffer = ByteBuffer .wrap (data , offset , data .length - offset );
63
49
64
- if (tagLen != TAG_LENGTH ) {
65
- throw new InvalidKeyException (String .format ("Authentication tag length must be %s" , TAG_LENGTH ));
66
- }
50
+ final int tagLen = buffer .getInt ();
51
+ final int nonceLen = buffer .getInt ();
67
52
68
- if (nonceLen != NONCE_LENGTH ) {
69
- throw new InvalidKeyException (String .format ("Initialization vector (IV) length must be %s" , NONCE_LENGTH ));
70
- }
53
+ if (tagLen != TAG_LENGTH ) {
54
+ throw new InvalidKeyException (String .format ("Authentication tag length must be %s" , TAG_LENGTH ));
55
+ }
71
56
72
- final byte [] nonce = new byte [nonceLen ];
73
- dis .readFully (nonce );
74
- return new GCMParameterSpec (tagLen , nonce );
75
- } catch (final IOException ex ) {
76
- throw new AssertionError ("Impossible exception" , ex );
57
+ if (nonceLen != NONCE_LENGTH || buffer .remaining () != NONCE_LENGTH ) {
58
+ throw new InvalidKeyException (String .format ("Initialization vector (IV) length must be %s" , NONCE_LENGTH ));
77
59
}
60
+
61
+ final byte [] nonce = new byte [nonceLen ];
62
+ buffer .get (nonce );
63
+
64
+ return new GCMParameterSpec (tagLen , nonce );
78
65
}
79
66
80
67
@ Override
81
68
WrappingData buildWrappingCipher (final Key key , final Map <String , String > encryptionContext )
82
69
throws GeneralSecurityException {
83
70
final byte [] nonce = new byte [NONCE_LENGTH ];
84
- rnd .nextBytes (nonce );
71
+ Utils . getSecureRandom () .nextBytes (nonce );
85
72
final GCMParameterSpec spec = new GCMParameterSpec (TAG_LENGTH , nonce );
86
73
final Cipher cipher = Cipher .getInstance (TRANSFORMATION );
87
74
cipher .init (Cipher .ENCRYPT_MODE , key , spec );
0 commit comments