Skip to content

Commit 31cccc9

Browse files
Version 1.2.0 is now compatible with Android API Level 16 (Removed use of AEADBadTagException)
1 parent 9393f4e commit 31cccc9

File tree

6 files changed

+43
-28
lines changed

6 files changed

+43
-28
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
- Defaults on AES, but supports any block cipher with a 128-bit block size.
1515
- Supports any key sizes that the block cipher supports (e.g. 128/192/256-bit keys for AES)
1616
- Thread-safe
17+
- Compatible with Android API Level 16 (since version 1.2.0)
18+
19+
## Audits
20+
- [Version 1.0.8 audit by Tim McLean](https://www.chosenplaintext.ca/publications/20161104-siv-mode-report.pdf) (Issues fixed with 1.1.0)
1721

1822
## Usage
1923
```java
@@ -37,7 +41,7 @@ public void encryptWithAssociatedData() {
3741
<dependency>
3842
<groupId>org.cryptomator</groupId>
3943
<artifactId>siv-mode</artifactId>
40-
<version>1.1.1</version>
44+
<version>1.2.0</version>
4145
</dependency>
4246
</dependencies>
4347
```

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>org.cryptomator</groupId>
55
<artifactId>siv-mode</artifactId>
6-
<version>1.1.1</version>
6+
<version>1.2.0</version>
77

88
<name>SIV Mode</name>
99
<description>RFC 5297 SIV mode: deterministic authenticated encryption</description>

src/main/java/org/cryptomator/siv/SivMode.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.nio.ByteBuffer;
1212
import java.util.Arrays;
1313

14-
import javax.crypto.AEADBadTagException;
1514
import javax.crypto.IllegalBlockSizeException;
1615
import javax.crypto.SecretKey;
1716

@@ -159,10 +158,10 @@ public byte[] encrypt(byte[] ctrKey, byte[] macKey, byte[] plaintext, byte[]...
159158
* @param associatedData Optional associated data, which needs to be authenticated during decryption.
160159
* @return Plaintext byte array.
161160
* @throws IllegalArgumentException If keys are invalid or {@link SecretKey#getEncoded()} is not supported.
162-
* @throws AEADBadTagException If the authentication failed, e.g. because ciphertext and/or associatedData are corrupted.
161+
* @throws UnauthenticCiphertextException If the authentication failed, e.g. because ciphertext and/or associatedData are corrupted.
163162
* @throws IllegalBlockSizeException If the provided ciphertext is of invalid length.
164163
*/
165-
public byte[] decrypt(SecretKey ctrKey, SecretKey macKey, byte[] ciphertext, byte[]... associatedData) throws AEADBadTagException, IllegalBlockSizeException {
164+
public byte[] decrypt(SecretKey ctrKey, SecretKey macKey, byte[] ciphertext, byte[]... associatedData) throws UnauthenticCiphertextException, IllegalBlockSizeException {
166165
final byte[] ctrKeyBytes = ctrKey.getEncoded();
167166
final byte[] macKeyBytes = macKey.getEncoded();
168167
if (ctrKeyBytes == null || macKeyBytes == null) {
@@ -185,10 +184,10 @@ public byte[] decrypt(SecretKey ctrKey, SecretKey macKey, byte[] ciphertext, byt
185184
* @param associatedData Optional associated data, which needs to be authenticated during decryption.
186185
* @return Plaintext byte array.
187186
* @throws IllegalArgumentException If the either of the two keys is of invalid length for the used {@link BlockCipher}.
188-
* @throws AEADBadTagException If the authentication failed, e.g. because ciphertext and/or associatedData are corrupted.
187+
* @throws UnauthenticCiphertextException If the authentication failed, e.g. because ciphertext and/or associatedData are corrupted.
189188
* @throws IllegalBlockSizeException If the provided ciphertext is of invalid length.
190189
*/
191-
public byte[] decrypt(byte[] ctrKey, byte[] macKey, byte[] ciphertext, byte[]... associatedData) throws AEADBadTagException, IllegalBlockSizeException {
190+
public byte[] decrypt(byte[] ctrKey, byte[] macKey, byte[] ciphertext, byte[]... associatedData) throws UnauthenticCiphertextException, IllegalBlockSizeException {
192191
if (ciphertext.length < 16) {
193192
throw new IllegalBlockSizeException("Input length must be greater than or equal 16.");
194193
}
@@ -230,7 +229,7 @@ public byte[] decrypt(byte[] ctrKey, byte[] macKey, byte[] ciphertext, byte[]...
230229
if (diff == 0) {
231230
return plaintext;
232231
} else {
233-
throw new AEADBadTagException("authentication in SIV decryption failed");
232+
throw new UnauthenticCiphertextException("authentication in SIV decryption failed");
234233
}
235234
}
236235

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.cryptomator.siv;
2+
3+
import javax.crypto.BadPaddingException;
4+
5+
/**
6+
* Drop-in replacement for {@link javax.crypto.AEADBadTagException}, which is not available on some older Android systems.
7+
*/
8+
public class UnauthenticCiphertextException extends BadPaddingException {
9+
10+
public UnauthenticCiphertextException(String message) {
11+
super(message);
12+
}
13+
14+
}

src/test/java/org/cryptomator/siv/SivModeBenchmark.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.util.Arrays;
1212
import java.util.concurrent.TimeUnit;
1313

14-
import javax.crypto.AEADBadTagException;
1514
import javax.crypto.IllegalBlockSizeException;
1615

1716
import org.bouncycastle.crypto.BlockCipher;
@@ -75,7 +74,7 @@ public void shuffleData() {
7574
}
7675

7776
@Benchmark
78-
public void benchmarkJce(Blackhole bh) throws AEADBadTagException, IllegalBlockSizeException {
77+
public void benchmarkJce(Blackhole bh) throws UnauthenticCiphertextException, IllegalBlockSizeException {
7978
byte[] encrypted = jceSivMode.encrypt(encKey, macKey, cleartextData, associatedData);
8079
byte[] decrypted = jceSivMode.decrypt(encKey, macKey, encrypted, associatedData);
8180
Assert.assertArrayEquals(cleartextData, decrypted);
@@ -84,7 +83,7 @@ public void benchmarkJce(Blackhole bh) throws AEADBadTagException, IllegalBlockS
8483
}
8584

8685
@Benchmark
87-
public void benchmarkBcFast(Blackhole bh) throws AEADBadTagException, IllegalBlockSizeException {
86+
public void benchmarkBcFast(Blackhole bh) throws UnauthenticCiphertextException, IllegalBlockSizeException {
8887
byte[] encrypted = bcFastSivMode.encrypt(encKey, macKey, cleartextData, associatedData);
8988
byte[] decrypted = bcFastSivMode.decrypt(encKey, macKey, encrypted, associatedData);
9089
Assert.assertArrayEquals(cleartextData, decrypted);
@@ -93,7 +92,7 @@ public void benchmarkBcFast(Blackhole bh) throws AEADBadTagException, IllegalBlo
9392
}
9493

9594
@Benchmark
96-
public void benchmarkBcLight(Blackhole bh) throws AEADBadTagException, IllegalBlockSizeException {
95+
public void benchmarkBcLight(Blackhole bh) throws UnauthenticCiphertextException, IllegalBlockSizeException {
9796
byte[] encrypted = bcLightSivMode.encrypt(encKey, macKey, cleartextData, associatedData);
9897
byte[] decrypted = bcLightSivMode.decrypt(encKey, macKey, encrypted, associatedData);
9998
Assert.assertArrayEquals(cleartextData, decrypted);

src/test/java/org/cryptomator/siv/SivModeTest.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.io.IOException;
1212
import java.security.InvalidKeyException;
1313

14-
import javax.crypto.AEADBadTagException;
1514
import javax.crypto.IllegalBlockSizeException;
1615
import javax.crypto.SecretKey;
1716
import javax.crypto.spec.SecretKeySpec;
@@ -76,7 +75,7 @@ public BlockCipher create() {
7675
}
7776

7877
@Test(expected = IllegalArgumentException.class)
79-
public void testDecryptWithInvalidKey1() throws AEADBadTagException, IllegalBlockSizeException {
78+
public void testDecryptWithInvalidKey1() throws UnauthenticCiphertextException, IllegalBlockSizeException {
8079
SecretKey key1 = Mockito.mock(SecretKey.class);
8180
Mockito.when(key1.getEncoded()).thenReturn(null);
8281
SecretKey key2 = Mockito.mock(SecretKey.class);
@@ -86,7 +85,7 @@ public void testDecryptWithInvalidKey1() throws AEADBadTagException, IllegalBloc
8685
}
8786

8887
@Test(expected = IllegalArgumentException.class)
89-
public void testDecryptWithInvalidKey2() throws AEADBadTagException, IllegalBlockSizeException {
88+
public void testDecryptWithInvalidKey2() throws UnauthenticCiphertextException, IllegalBlockSizeException {
9089
SecretKey key1 = Mockito.mock(SecretKey.class);
9190
Mockito.when(key1.getEncoded()).thenReturn(new byte[16]);
9291
SecretKey key2 = Mockito.mock(SecretKey.class);
@@ -96,7 +95,7 @@ public void testDecryptWithInvalidKey2() throws AEADBadTagException, IllegalBloc
9695
}
9796

9897
@Test(expected = IllegalBlockSizeException.class)
99-
public void testDecryptWithInvalidBlockSize() throws AEADBadTagException, IllegalBlockSizeException {
98+
public void testDecryptWithInvalidBlockSize() throws UnauthenticCiphertextException, IllegalBlockSizeException {
10099
final byte[] dummyKey = new byte[16];
101100
final SecretKey ctrKey = new SecretKeySpec(dummyKey, "AES");
102101
final SecretKey macKey = new SecretKeySpec(dummyKey, "AES");
@@ -114,7 +113,7 @@ public void testEncryptAssociatedDataLimit() {
114113
}
115114

116115
@Test(expected = IllegalArgumentException.class)
117-
public void testDecryptAssociatedDataLimit() throws AEADBadTagException, IllegalBlockSizeException {
116+
public void testDecryptAssociatedDataLimit() throws UnauthenticCiphertextException, IllegalBlockSizeException {
118117
final byte[] ctrKey = new byte[16];
119118
final byte[] macKey = new byte[16];
120119
final byte[] plaintext = new byte[80];
@@ -188,7 +187,7 @@ public void testSivEncrypt() {
188187
}
189188

190189
@Test
191-
public void testSivDecrypt() throws AEADBadTagException, IllegalBlockSizeException {
190+
public void testSivDecrypt() throws UnauthenticCiphertextException, IllegalBlockSizeException {
192191
final byte[] macKey = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
193192
(byte) 0xfb, (byte) 0xfa, (byte) 0xf9, (byte) 0xf8, //
194193
(byte) 0xf7, (byte) 0xf6, (byte) 0xf5, (byte) 0xf4, //
@@ -224,8 +223,8 @@ public void testSivDecrypt() throws AEADBadTagException, IllegalBlockSizeExcepti
224223
Assert.assertArrayEquals(expected, result);
225224
}
226225

227-
@Test(expected = AEADBadTagException.class)
228-
public void testSivDecryptWithInvalidKey() throws AEADBadTagException, IllegalBlockSizeException {
226+
@Test(expected = UnauthenticCiphertextException.class)
227+
public void testSivDecryptWithInvalidKey() throws UnauthenticCiphertextException, IllegalBlockSizeException {
229228
final byte[] macKey = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
230229
(byte) 0xfb, (byte) 0xfa, (byte) 0xf9, (byte) 0xf8, //
231230
(byte) 0xf7, (byte) 0xf6, (byte) 0xf5, (byte) 0xf4, //
@@ -256,7 +255,7 @@ public void testSivDecryptWithInvalidKey() throws AEADBadTagException, IllegalBl
256255
}
257256

258257
@Test(expected = IllegalBlockSizeException.class)
259-
public void testSivDecryptWithInvalidCiphertext() throws AEADBadTagException, IllegalBlockSizeException {
258+
public void testSivDecryptWithInvalidCiphertext() throws UnauthenticCiphertextException, IllegalBlockSizeException {
260259
final byte[] macKey = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
261260
(byte) 0xfb, (byte) 0xfa, (byte) 0xf9, (byte) 0xf8, //
262261
(byte) 0xf7, (byte) 0xf6, (byte) 0xf5, (byte) 0xf4, //
@@ -346,7 +345,7 @@ public void testNonceBasedAuthenticatedEncryption() throws InvalidKeyException {
346345
}
347346

348347
@Test
349-
public void testEncryptionAndDecryptionUsingJavaxCryptoApi() throws AEADBadTagException, IllegalBlockSizeException {
348+
public void testEncryptionAndDecryptionUsingJavaxCryptoApi() throws UnauthenticCiphertextException, IllegalBlockSizeException {
350349
final byte[] dummyKey = new byte[16];
351350
final SecretKey ctrKey = new SecretKeySpec(dummyKey, "AES");
352351
final SecretKey macKey = new SecretKeySpec(dummyKey, "AES");
@@ -423,7 +422,7 @@ public void testXorend() {
423422
}
424423

425424
@Test
426-
public void testGeneratedTestCases() throws IOException, AEADBadTagException, IllegalBlockSizeException {
425+
public void testGeneratedTestCases() throws IOException, UnauthenticCiphertextException, IllegalBlockSizeException {
427426
final EncryptionTestCase[] allTestCases = EncryptionTestCase.readTestCases();
428427

429428
// Check that decryption fails if the wrong MAC key is used
@@ -440,7 +439,7 @@ public void testGeneratedTestCases() throws IOException, AEADBadTagException, Il
440439
try {
441440
new SivMode().decrypt(testCase.getCtrKey(), macKey, testCase.getCiphertext(), testCase.getAssociatedData());
442441
Assert.fail();
443-
} catch (AEADBadTagException ex) {
442+
} catch (UnauthenticCiphertextException ex) {
444443
// Test case passed.
445444
}
446445
}
@@ -460,7 +459,7 @@ public void testGeneratedTestCases() throws IOException, AEADBadTagException, Il
460459
try {
461460
new SivMode().decrypt(testCase.getCtrKey(), testCase.getMacKey(), ciphertext, testCase.getAssociatedData());
462461
Assert.fail();
463-
} catch (AEADBadTagException ex) {
462+
} catch (UnauthenticCiphertextException ex) {
464463
// Test case passed.
465464
}
466465
}
@@ -486,7 +485,7 @@ public void testGeneratedTestCases() throws IOException, AEADBadTagException, Il
486485
try {
487486
new SivMode().decrypt(testCase.getCtrKey(), testCase.getMacKey(), testCase.getCiphertext(), ad);
488487
Assert.fail();
489-
} catch (AEADBadTagException ex) {
488+
} catch (UnauthenticCiphertextException ex) {
490489
// Test case passed.
491490
}
492491

@@ -503,7 +502,7 @@ public void testGeneratedTestCases() throws IOException, AEADBadTagException, Il
503502
try {
504503
new SivMode().decrypt(testCase.getCtrKey(), testCase.getMacKey(), testCase.getCiphertext(), prependedAd);
505504
Assert.fail();
506-
} catch (AEADBadTagException ex) {
505+
} catch (UnauthenticCiphertextException ex) {
507506
// Test case passed.
508507
}
509508

@@ -514,7 +513,7 @@ public void testGeneratedTestCases() throws IOException, AEADBadTagException, Il
514513
try {
515514
new SivMode().decrypt(testCase.getCtrKey(), testCase.getMacKey(), testCase.getCiphertext(), appendedAd);
516515
Assert.fail();
517-
} catch (AEADBadTagException ex) {
516+
} catch (UnauthenticCiphertextException ex) {
518517
// Test case passed.
519518
}
520519
}

0 commit comments

Comments
 (0)