@@ -76,7 +76,7 @@ public SivEngine(byte[] key) {
7676 * @throws IllegalArgumentException if either param exceeds the limits for safe use.
7777 */
7878 public byte [] encrypt (byte [] plaintext , byte []... associatedData ) {
79- final byte [] ciphertext = new byte [16 + plaintext .length ];
79+ final byte [] ciphertext = new byte [IV_LENGTH + plaintext .length ];
8080 try {
8181 int encrypted = encrypt (plaintext , ciphertext , 0 , associatedData );
8282 assert encrypted == ciphertext .length ;
@@ -86,19 +86,19 @@ public byte[] encrypt(byte[] plaintext, byte[]... associatedData) {
8686 return ciphertext ;
8787 }
8888
89- public int encrypt (byte [] input , byte [] output , int outputOffset , byte []... associatedData ) throws ShortBufferException {
89+ public int encrypt (byte [] plaintext , byte [] output , int outputOffset , byte []... associatedData ) throws ShortBufferException {
9090 // Check if plaintext length will cause overflows
91- if (input .length > (Integer .MAX_VALUE - IV_LENGTH )) {
91+ if (plaintext .length > (Integer .MAX_VALUE - IV_LENGTH )) {
9292 throw new IllegalArgumentException ("Plaintext is too long" );
9393 }
9494
95- if (output .length - outputOffset < IV_LENGTH + input .length ) {
95+ if (output .length - outputOffset < IV_LENGTH + plaintext .length ) {
9696 throw new ShortBufferException ();
9797 }
98- byte [] iv = s2v (input , associatedData );
98+ byte [] iv = s2v (plaintext , associatedData );
9999 assert iv .length == IV_LENGTH ;
100100 System .arraycopy (iv , 0 , output , 0 , IV_LENGTH );
101- return IV_LENGTH + computeCtr (input , iv , output , IV_LENGTH );
101+ return IV_LENGTH + computeCtr (plaintext , 0 , plaintext . length , iv , 0 , IV_LENGTH , output , IV_LENGTH );
102102 }
103103
104104 /**
@@ -115,16 +115,20 @@ public byte[] decrypt(byte[] ciphertext, byte[]... associatedData) throws AEADBa
115115 throw new IllegalBlockSizeException ("Input length must be greater than or equal 16." );
116116 }
117117
118- final byte [] iv = Arrays .copyOf (ciphertext , IV_LENGTH );
119- final byte [] actualCiphertext = Arrays .copyOfRange (ciphertext , IV_LENGTH , ciphertext .length );
120- final byte [] plaintext = computeCtr (actualCiphertext , iv );
118+ final byte [] plaintext = new byte [ciphertext .length - IV_LENGTH ];
119+ try {
120+ int decrypted = computeCtr (ciphertext , IV_LENGTH , ciphertext .length - IV_LENGTH , ciphertext , 0 , IV_LENGTH , plaintext , 0 );
121+ assert decrypted == plaintext .length ;
122+ } catch (ShortBufferException e ) {
123+ throw new IllegalStateException (e );
124+ }
121125 final byte [] control = s2v (plaintext , associatedData );
122126
123127 // time-constant comparison (taken from MessageDigest.isEqual in JDK8)
124- assert iv .length == control . length ;
128+ assert control .length == IV_LENGTH ;
125129 int diff = 0 ;
126- for (int i = 0 ; i < iv . length ; i ++) {
127- diff |= iv [i ] ^ control [i ];
130+ for (int i = 0 ; i < IV_LENGTH ; i ++) {
131+ diff |= ciphertext [i ] ^ control [i ];
128132 }
129133
130134 if (diff == 0 ) {
@@ -139,24 +143,24 @@ public byte[] decrypt(byte[] ciphertext, byte[]... associatedData) throws AEADBa
139143 byte [] computeCtr (byte [] input , final byte [] iv ) {
140144 byte [] output = new byte [input .length ];
141145 try {
142- int processed = computeCtr (input , iv , output , 0 );
146+ int processed = computeCtr (input , 0 , input . length , iv , 0 , iv . length , output , 0 );
143147 assert processed == output .length ;
144148 } catch (ShortBufferException e ) {
145149 throw new IllegalStateException (e );
146150 }
147151 return output ;
148152 }
149153
150- // visible for testing
151- int computeCtr (byte [] input , final byte [] iv , byte [] output , int outputOffset ) throws ShortBufferException {
154+ private int computeCtr (byte [] input , int inOff , int inLen , final byte [] iv , int ivOff , int ivLen , byte [] output , int outputOffset ) throws ShortBufferException {
152155 // clear out the 31st and 63rd (rightmost) bit:
153- final byte [] adjustedIv = Arrays .copyOf (iv , 16 );
156+ assert ivLen == IV_LENGTH ;
157+ final byte [] adjustedIv = Arrays .copyOfRange (iv , ivOff , ivOff + ivLen );
154158 adjustedIv [8 ] = (byte ) (adjustedIv [8 ] & 0x7F );
155159 adjustedIv [12 ] = (byte ) (adjustedIv [12 ] & 0x7F );
156160
157161 try {
158162 ctrCipher .init (Cipher .ENCRYPT_MODE , ctrKey , new IvParameterSpec (adjustedIv ));
159- return ctrCipher .doFinal (input , 0 , input . length , output , outputOffset );
163+ return ctrCipher .doFinal (input , inOff , inLen , output , outputOffset );
160164 } catch (InvalidKeyException | InvalidAlgorithmParameterException e ) {
161165 throw new IllegalArgumentException ("Key or IV invalid." );
162166 } catch (BadPaddingException e ) {
0 commit comments