mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-01 05:37:13 +00:00
- always check HMAC before decryption
- separating AES and CMAC key during SIV mode
This commit is contained in:
@@ -293,7 +293,7 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
final String[] cleartextPathComps = StringUtils.split(cleartextPath, cleartextPathSep);
|
||||
final List<String> encryptedPathComps = new ArrayList<>(cleartextPathComps.length);
|
||||
for (final String cleartext : cleartextPathComps) {
|
||||
final String encrypted = encryptPathComponent(cleartext, primaryMasterKey, ioSupport);
|
||||
final String encrypted = encryptPathComponent(cleartext, primaryMasterKey, hMacMasterKey, ioSupport);
|
||||
encryptedPathComps.add(encrypted);
|
||||
}
|
||||
return StringUtils.join(encryptedPathComps, encryptedPathSep);
|
||||
@@ -317,11 +317,11 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
* These alternative names consist of the checksum, a unique id and a special file extension defined in
|
||||
* {@link FileNamingConventions#LONG_NAME_FILE_EXT}.
|
||||
*/
|
||||
private String encryptPathComponent(final String cleartext, final SecretKey key, CryptorIOSupport ioSupport) throws IOException, InvalidKeyException {
|
||||
private String encryptPathComponent(final String cleartext, final SecretKey aesKey, final SecretKey macKey, CryptorIOSupport ioSupport) throws IOException, InvalidKeyException {
|
||||
final byte[] cleartextBytes = cleartext.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// encrypt:
|
||||
final byte[] encryptedBytes = AesSivCipherUtil.sivEncrypt(key.getEncoded(), cleartextBytes);
|
||||
final byte[] encryptedBytes = AesSivCipherUtil.sivEncrypt(aesKey, macKey, cleartextBytes);
|
||||
final String ivAndCiphertext = ENCRYPTED_FILENAME_CODEC.encodeAsString(encryptedBytes);
|
||||
|
||||
if (ivAndCiphertext.length() + BASIC_FILE_EXT.length() > ENCRYPTED_FILENAME_LENGTH_LIMIT) {
|
||||
@@ -342,7 +342,7 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
final String[] encryptedPathComps = StringUtils.split(encryptedPath, encryptedPathSep);
|
||||
final List<String> cleartextPathComps = new ArrayList<>(encryptedPathComps.length);
|
||||
for (final String encrypted : encryptedPathComps) {
|
||||
final String cleartext = decryptPathComponent(encrypted, primaryMasterKey, ioSupport);
|
||||
final String cleartext = decryptPathComponent(encrypted, primaryMasterKey, hMacMasterKey, ioSupport);
|
||||
cleartextPathComps.add(new String(cleartext));
|
||||
}
|
||||
return StringUtils.join(cleartextPathComps, cleartextPathSep);
|
||||
@@ -354,7 +354,7 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
/**
|
||||
* @see #encryptPathComponent(String, SecretKey, CryptorIOSupport)
|
||||
*/
|
||||
private String decryptPathComponent(final String encrypted, final SecretKey key, CryptorIOSupport ioSupport) throws IOException, InvalidKeyException, DecryptFailedException {
|
||||
private String decryptPathComponent(final String encrypted, final SecretKey aesKey, final SecretKey macKey, CryptorIOSupport ioSupport) throws IOException, InvalidKeyException, DecryptFailedException {
|
||||
final String ciphertext;
|
||||
if (encrypted.endsWith(LONG_NAME_FILE_EXT)) {
|
||||
final String basename = StringUtils.removeEnd(encrypted, LONG_NAME_FILE_EXT);
|
||||
@@ -371,7 +371,7 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
|
||||
// decrypt:
|
||||
final byte[] encryptedBytes = ENCRYPTED_FILENAME_CODEC.decode(ciphertext);
|
||||
final byte[] cleartextBytes = AesSivCipherUtil.sivDecrypt(key.getEncoded(), encryptedBytes);
|
||||
final byte[] cleartextBytes = AesSivCipherUtil.sivDecrypt(aesKey, macKey, encryptedBytes);
|
||||
|
||||
return new String(cleartextBytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
@@ -389,8 +389,7 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
ioSupport.writePathSpecificMetadata(metadataFile, objectMapper.writeValueAsBytes(metadata));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authenticateContent(SeekableByteChannel encryptedFile) throws IOException {
|
||||
private void authenticateContent(SeekableByteChannel encryptedFile) throws IOException, DecryptFailedException {
|
||||
// init mac:
|
||||
final Mac calculatedMac = this.hmacSha256(hMacMasterKey);
|
||||
|
||||
@@ -411,7 +410,11 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
IOUtils.copyLarge(macIn, new NullOutputStream());
|
||||
|
||||
// compare (in constant time):
|
||||
return MessageDigest.isEqual(storedMac.array(), calculatedMac.doFinal());
|
||||
boolean macMatches = MessageDigest.isEqual(storedMac.array(), calculatedMac.doFinal());
|
||||
|
||||
if (!macMatches) {
|
||||
throw new DecryptFailedException("MAC authentication failed.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -440,7 +443,7 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decryptedFile(SeekableByteChannel encryptedFile, OutputStream plaintextFile) throws IOException {
|
||||
public Long decryptedFile(SeekableByteChannel encryptedFile, OutputStream plaintextFile) throws IOException, DecryptFailedException {
|
||||
// read iv:
|
||||
encryptedFile.position(0);
|
||||
final ByteBuffer countingIv = ByteBuffer.allocate(AES_BLOCK_LENGTH);
|
||||
@@ -454,6 +457,9 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
throw new IOException("Failed to read file header.");
|
||||
}
|
||||
|
||||
// check MAC:
|
||||
this.authenticateContent(encryptedFile);
|
||||
|
||||
// go to begin of content:
|
||||
encryptedFile.position(64);
|
||||
|
||||
@@ -467,7 +473,7 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decryptRange(SeekableByteChannel encryptedFile, OutputStream plaintextFile, long pos, long length) throws IOException {
|
||||
public Long decryptRange(SeekableByteChannel encryptedFile, OutputStream plaintextFile, long pos, long length) throws IOException, DecryptFailedException {
|
||||
// read iv:
|
||||
encryptedFile.position(0);
|
||||
final ByteBuffer countingIv = ByteBuffer.allocate(AES_BLOCK_LENGTH);
|
||||
@@ -478,6 +484,9 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
|
||||
throw new IOException("Failed to read file header.");
|
||||
}
|
||||
|
||||
// check MAC:
|
||||
this.authenticateContent(encryptedFile);
|
||||
|
||||
// seek relevant position and update iv:
|
||||
long firstRelevantBlock = pos / AES_BLOCK_LENGTH; // cut of fraction!
|
||||
long beginOfFirstRelevantBlock = firstRelevantBlock * AES_BLOCK_LENGTH;
|
||||
|
||||
@@ -13,6 +13,8 @@ import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.bouncycastle.crypto.BlockCipher;
|
||||
import org.bouncycastle.crypto.CipherParameters;
|
||||
@@ -31,15 +33,26 @@ final class AesSivCipherUtil {
|
||||
private static final byte[] BYTES_ZERO = new byte[16];
|
||||
private static final byte DOUBLING_CONST = (byte) 0x87;
|
||||
|
||||
static byte[] sivEncrypt(byte[] key, byte[] plaintext, byte[]... additionalData) throws InvalidKeyException {
|
||||
if (key.length != 32 && key.length != 48 && key.length != 64) {
|
||||
throw new InvalidKeyException("Invalid key length " + key.length);
|
||||
static byte[] sivEncrypt(SecretKey aesKey, SecretKey macKey, byte[] plaintext, byte[]... additionalData) throws InvalidKeyException {
|
||||
final byte[] aesKeyBytes = aesKey.getEncoded();
|
||||
final byte[] macKeyBytes = macKey.getEncoded();
|
||||
if (aesKeyBytes == null || macKeyBytes == null) {
|
||||
throw new IllegalArgumentException("Can't get bytes of given key.");
|
||||
}
|
||||
try {
|
||||
return sivEncrypt(aesKeyBytes, macKeyBytes, plaintext, additionalData);
|
||||
} finally {
|
||||
Arrays.fill(aesKeyBytes, (byte) 0);
|
||||
Arrays.fill(macKeyBytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] sivEncrypt(byte[] aesKey, byte[] macKey, byte[] plaintext, byte[]... additionalData) throws InvalidKeyException {
|
||||
if (aesKey.length != 16 && aesKey.length != 24 && aesKey.length != 32) {
|
||||
throw new InvalidKeyException("Invalid aesKey length " + aesKey.length);
|
||||
}
|
||||
|
||||
final byte[] k1 = Arrays.copyOf(key, key.length / 2);
|
||||
final byte[] k2 = Arrays.copyOfRange(key, k1.length, key.length);
|
||||
|
||||
final byte[] iv = s2v(k1, plaintext, additionalData);
|
||||
final byte[] iv = s2v(macKey, plaintext, additionalData);
|
||||
|
||||
final int numBlocks = (plaintext.length + 15) / 16;
|
||||
|
||||
@@ -52,7 +65,7 @@ final class AesSivCipherUtil {
|
||||
|
||||
final byte[] x = new byte[numBlocks * 16];
|
||||
final BlockCipher aes = new AESFastEngine();
|
||||
aes.init(true, new KeyParameter(k2));
|
||||
aes.init(true, new KeyParameter(aesKey));
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
final long ctrVal = initialCtrVal + i;
|
||||
ctrBuf.putLong(8, ctrVal);
|
||||
@@ -65,13 +78,24 @@ final class AesSivCipherUtil {
|
||||
return ArrayUtils.addAll(iv, ciphertext);
|
||||
}
|
||||
|
||||
static byte[] sivDecrypt(byte[] key, byte[] ciphertext, byte[]... additionalData) throws DecryptFailedException, InvalidKeyException {
|
||||
if (key.length != 32 && key.length != 48 && key.length != 64) {
|
||||
throw new InvalidKeyException("Invalid key length " + key.length);
|
||||
static byte[] sivDecrypt(SecretKey aesKey, SecretKey macKey, byte[] plaintext, byte[]... additionalData) throws InvalidKeyException, DecryptFailedException {
|
||||
final byte[] aesKeyBytes = aesKey.getEncoded();
|
||||
final byte[] macKeyBytes = macKey.getEncoded();
|
||||
if (aesKeyBytes == null || macKeyBytes == null) {
|
||||
throw new IllegalArgumentException("Can't get bytes of given key.");
|
||||
}
|
||||
try {
|
||||
return sivDecrypt(aesKeyBytes, macKeyBytes, plaintext, additionalData);
|
||||
} finally {
|
||||
Arrays.fill(aesKeyBytes, (byte) 0);
|
||||
Arrays.fill(macKeyBytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
final byte[] k1 = Arrays.copyOf(key, key.length / 2);
|
||||
final byte[] k2 = Arrays.copyOfRange(key, k1.length, key.length);
|
||||
static byte[] sivDecrypt(byte[] aesKey, byte[] macKey, byte[] ciphertext, byte[]... additionalData) throws DecryptFailedException, InvalidKeyException {
|
||||
if (aesKey.length != 16 && aesKey.length != 24 && aesKey.length != 32) {
|
||||
throw new InvalidKeyException("Invalid aesKey length " + aesKey.length);
|
||||
}
|
||||
|
||||
final byte[] iv = Arrays.copyOf(ciphertext, 16);
|
||||
|
||||
@@ -87,7 +111,7 @@ final class AesSivCipherUtil {
|
||||
|
||||
final byte[] x = new byte[numBlocks * 16];
|
||||
final BlockCipher aes = new AESFastEngine();
|
||||
aes.init(true, new KeyParameter(k2));
|
||||
aes.init(true, new KeyParameter(aesKey));
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
final long ctrVal = initialCtrVal + i;
|
||||
ctrBuf.putLong(8, ctrVal);
|
||||
@@ -97,7 +121,7 @@ final class AesSivCipherUtil {
|
||||
|
||||
final byte[] plaintext = xor(actualCiphertext, x);
|
||||
|
||||
final byte[] control = s2v(k1, plaintext, additionalData);
|
||||
final byte[] control = s2v(macKey, plaintext, additionalData);
|
||||
|
||||
if (MessageDigest.isEqual(control, iv)) {
|
||||
return plaintext;
|
||||
@@ -106,8 +130,8 @@ final class AesSivCipherUtil {
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] s2v(byte[] key, byte[] plaintext, byte[]... additionalData) {
|
||||
final CipherParameters params = new KeyParameter(key);
|
||||
static byte[] s2v(byte[] macKey, byte[] plaintext, byte[]... additionalData) {
|
||||
final CipherParameters params = new KeyParameter(macKey);
|
||||
final BlockCipher aes = new AESFastEngine();
|
||||
final CMac mac = new CMac(aes);
|
||||
mac.init(params);
|
||||
|
||||
@@ -14,26 +14,12 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.Security;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.cryptomator.crypto.CryptorIOSupport;
|
||||
import org.cryptomator.crypto.exceptions.DecryptFailedException;
|
||||
import org.cryptomator.crypto.exceptions.UnsupportedKeyLengthException;
|
||||
@@ -86,8 +72,8 @@ public class Aes256CryptorTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntegrityAuthentication() throws IOException {
|
||||
@Test(expected = DecryptFailedException.class)
|
||||
public void testIntegrityAuthentication() throws IOException, DecryptFailedException {
|
||||
// our test plaintext data:
|
||||
final byte[] plaintextData = "Hello World".getBytes();
|
||||
final InputStream plaintextIn = new ByteArrayInputStream(plaintextData);
|
||||
@@ -104,11 +90,6 @@ public class Aes256CryptorTest {
|
||||
|
||||
encryptedData.position(0);
|
||||
|
||||
// authenticate unmodified content:
|
||||
final SeekableByteChannel encryptedIn1 = new ByteBufferBackedSeekableChannel(encryptedData);
|
||||
final boolean isContentUnmodified1 = cryptor.authenticateContent(encryptedIn1);
|
||||
Assert.assertTrue(isContentUnmodified1);
|
||||
|
||||
// toggle one bit inf first content byte:
|
||||
encryptedData.position(64);
|
||||
final byte fifthByte = encryptedData.get();
|
||||
@@ -117,30 +98,10 @@ public class Aes256CryptorTest {
|
||||
|
||||
encryptedData.position(0);
|
||||
|
||||
// authenticate modified content:
|
||||
final SeekableByteChannel encryptedIn2 = new ByteBufferBackedSeekableChannel(encryptedData);
|
||||
final boolean isContentUnmodified2 = cryptor.authenticateContent(encryptedIn2);
|
||||
Assert.assertFalse(isContentUnmodified2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void foo() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
final byte[] iv = new byte[16];
|
||||
final byte[] keyBytes = new byte[16];
|
||||
final SecretKey key = new SecretKeySpec(keyBytes, "AES");
|
||||
final Cipher pkcs5PaddedCipher = Cipher.getInstance("AES/CTR/PKCS5Padding", BouncyCastleProvider.PROVIDER_NAME);
|
||||
pkcs5PaddedCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
|
||||
final Cipher unpaddedCipher = Cipher.getInstance("AES/CTR/NoPadding");
|
||||
unpaddedCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
|
||||
|
||||
// test data:
|
||||
final byte[] plaintextData = "Hello World".getBytes();
|
||||
final byte[] pkcs5PaddedCiphertext = pkcs5PaddedCipher.doFinal(plaintextData);
|
||||
final byte[] unpaddedCiphertext = unpaddedCipher.doFinal(plaintextData);
|
||||
|
||||
Assert.assertFalse(Arrays.equals(pkcs5PaddedCiphertext, unpaddedCiphertext));
|
||||
// decrypt modified content (should fail with DecryptFailedException):
|
||||
final SeekableByteChannel encryptedIn = new ByteBufferBackedSeekableChannel(encryptedData);
|
||||
final ByteArrayOutputStream plaintextOut = new ByteArrayOutputStream();
|
||||
cryptor.decryptedFile(encryptedIn, plaintextOut);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+22
-19
@@ -14,7 +14,7 @@ public class AesSivCipherUtilTest {
|
||||
|
||||
@Test
|
||||
public void testS2v() throws DecoderException {
|
||||
final byte[] key = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
|
||||
final byte[] macKey = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
|
||||
(byte) 0xfb, (byte) 0xfa, (byte) 0xf9, (byte) 0xf8, //
|
||||
(byte) 0xf7, (byte) 0xf6, (byte) 0xf5, (byte) 0xf4, //
|
||||
(byte) 0xf3, (byte) 0xf2, (byte) 0xf1, (byte) 0xf0};
|
||||
@@ -36,17 +36,18 @@ public class AesSivCipherUtilTest {
|
||||
(byte) 0x95, (byte) 0x0a, (byte) 0xcd, (byte) 0x32, //
|
||||
(byte) 0x0a, (byte) 0x2e, (byte) 0xcc, (byte) 0x93};
|
||||
|
||||
final byte[] result = AesSivCipherUtil.s2v(key, plaintext, ad);
|
||||
final byte[] result = AesSivCipherUtil.s2v(macKey, plaintext, ad);
|
||||
Assert.assertArrayEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSivEncrypt() throws InvalidKeyException {
|
||||
final byte[] key = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
|
||||
final byte[] macKey = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
|
||||
(byte) 0xfb, (byte) 0xfa, (byte) 0xf9, (byte) 0xf8, //
|
||||
(byte) 0xf7, (byte) 0xf6, (byte) 0xf5, (byte) 0xf4, //
|
||||
(byte) 0xf3, (byte) 0xf2, (byte) 0xf1, (byte) 0xf0, //
|
||||
(byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, //
|
||||
(byte) 0xf3, (byte) 0xf2, (byte) 0xf1, (byte) 0xf0};
|
||||
|
||||
final byte[] aesKey = {(byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, //
|
||||
(byte) 0xf4, (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, //
|
||||
(byte) 0xf8, (byte) 0xf9, (byte) 0xfa, (byte) 0xfb, //
|
||||
(byte) 0xfc, (byte) 0xfd, (byte) 0xfe, (byte) 0xff};
|
||||
@@ -72,17 +73,18 @@ public class AesSivCipherUtilTest {
|
||||
(byte) 0xda, (byte) 0xef, (byte) 0x7f, (byte) 0x6a, //
|
||||
(byte) 0xfe, (byte) 0x5c};
|
||||
|
||||
final byte[] result = AesSivCipherUtil.sivEncrypt(key, plaintext, ad);
|
||||
final byte[] result = AesSivCipherUtil.sivEncrypt(aesKey, macKey, plaintext, ad);
|
||||
Assert.assertArrayEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSivDecrypt() throws DecryptFailedException, InvalidKeyException {
|
||||
final byte[] key = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
|
||||
final byte[] macKey = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
|
||||
(byte) 0xfb, (byte) 0xfa, (byte) 0xf9, (byte) 0xf8, //
|
||||
(byte) 0xf7, (byte) 0xf6, (byte) 0xf5, (byte) 0xf4, //
|
||||
(byte) 0xf3, (byte) 0xf2, (byte) 0xf1, (byte) 0xf0, //
|
||||
(byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, //
|
||||
(byte) 0xf3, (byte) 0xf2, (byte) 0xf1, (byte) 0xf0};
|
||||
|
||||
final byte[] aesKey = {(byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, //
|
||||
(byte) 0xf4, (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, //
|
||||
(byte) 0xf8, (byte) 0xf9, (byte) 0xfa, (byte) 0xfb, //
|
||||
(byte) 0xfc, (byte) 0xfd, (byte) 0xfe, (byte) 0xff};
|
||||
@@ -108,17 +110,18 @@ public class AesSivCipherUtilTest {
|
||||
(byte) 0x99, (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, //
|
||||
(byte) 0xdd, (byte) 0xee};
|
||||
|
||||
final byte[] result = AesSivCipherUtil.sivDecrypt(key, ciphertext, ad);
|
||||
final byte[] result = AesSivCipherUtil.sivDecrypt(aesKey, macKey, ciphertext, ad);
|
||||
Assert.assertArrayEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test(expected = DecryptFailedException.class)
|
||||
public void testSivDecryptWithInvalidKey() throws DecryptFailedException, InvalidKeyException {
|
||||
final byte[] key = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
|
||||
final byte[] macKey = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
|
||||
(byte) 0xfb, (byte) 0xfa, (byte) 0xf9, (byte) 0xf8, //
|
||||
(byte) 0xf7, (byte) 0xf6, (byte) 0xf5, (byte) 0xf4, //
|
||||
(byte) 0xf3, (byte) 0xf2, (byte) 0xf1, (byte) 0xf0, //
|
||||
(byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, //
|
||||
(byte) 0xf3, (byte) 0xf2, (byte) 0xf1, (byte) 0xf0};
|
||||
|
||||
final byte[] aesKey = {(byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, //
|
||||
(byte) 0xf4, (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, //
|
||||
(byte) 0xf8, (byte) 0xf9, (byte) 0xfa, (byte) 0xfb, //
|
||||
(byte) 0xfc, (byte) 0xfd, (byte) 0xfe, (byte) 0x00};
|
||||
@@ -144,7 +147,7 @@ public class AesSivCipherUtilTest {
|
||||
(byte) 0x99, (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, //
|
||||
(byte) 0xdd, (byte) 0xee};
|
||||
|
||||
final byte[] result = AesSivCipherUtil.sivDecrypt(key, ciphertext, ad);
|
||||
final byte[] result = AesSivCipherUtil.sivDecrypt(aesKey, macKey, ciphertext, ad);
|
||||
Assert.assertArrayEquals(expected, result);
|
||||
}
|
||||
|
||||
@@ -153,12 +156,12 @@ public class AesSivCipherUtilTest {
|
||||
*/
|
||||
@Test
|
||||
public void testNonceBasedAuthenticatedEncryption() throws InvalidKeyException {
|
||||
|
||||
final byte[] key = {(byte) 0x7f, (byte) 0x7e, (byte) 0x7d, (byte) 0x7c, //
|
||||
final byte[] macKey = {(byte) 0x7f, (byte) 0x7e, (byte) 0x7d, (byte) 0x7c, //
|
||||
(byte) 0x7b, (byte) 0x7a, (byte) 0x79, (byte) 0x78, //
|
||||
(byte) 0x77, (byte) 0x76, (byte) 0x75, (byte) 0x74, //
|
||||
(byte) 0x73, (byte) 0x72, (byte) 0x71, (byte) 0x70, //
|
||||
(byte) 0x40, (byte) 0x41, (byte) 0x42, (byte) 0x43, //
|
||||
(byte) 0x73, (byte) 0x72, (byte) 0x71, (byte) 0x70};
|
||||
|
||||
final byte[] aesKey = {(byte) 0x40, (byte) 0x41, (byte) 0x42, (byte) 0x43, //
|
||||
(byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47, //
|
||||
(byte) 0x48, (byte) 0x49, (byte) 0x4a, (byte) 0x4b, //
|
||||
(byte) 0x4c, (byte) 0x4d, (byte) 0x4e, (byte) 0x4f};
|
||||
@@ -196,7 +199,7 @@ public class AesSivCipherUtilTest {
|
||||
(byte) 0x53, (byte) 0x49, (byte) 0x56, (byte) 0x2d, //
|
||||
(byte) 0x41, (byte) 0x45, (byte) 0x53};
|
||||
|
||||
final byte[] result = AesSivCipherUtil.sivEncrypt(key, plaintext, ad1, ad2, nonce);
|
||||
final byte[] result = AesSivCipherUtil.sivEncrypt(aesKey, macKey, plaintext, ad1, ad2, nonce);
|
||||
|
||||
final byte[] expected = {(byte) 0x7b, (byte) 0xdb, (byte) 0x6e, (byte) 0x3b, //
|
||||
(byte) 0x43, (byte) 0x26, (byte) 0x67, (byte) 0xeb, //
|
||||
|
||||
Reference in New Issue
Block a user