From 5aaee7bbf6d18643fb1bda429225034cab379a72 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sun, 15 Feb 2015 15:55:49 +0100 Subject: [PATCH] - fixed xorend function - SIV implementation now satisfies all official test vectors --- .../crypto/aes256/AesSivCipherUtil.java | 41 ++++------- .../crypto/aes256/AesSivCipherUtilTest.java | 71 +++++++++++++++++++ 2 files changed, 86 insertions(+), 26 deletions(-) diff --git a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/AesSivCipherUtil.java b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/AesSivCipherUtil.java index 33c9f3cb3..76ab79ec6 100644 --- a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/AesSivCipherUtil.java +++ b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/AesSivCipherUtil.java @@ -13,7 +13,6 @@ import java.security.InvalidKeyException; import java.security.MessageDigest; import java.util.Arrays; -import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.ArrayUtils; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; @@ -61,7 +60,7 @@ final class AesSivCipherUtil { aes.reset(); } - final byte[] ciphertext = xorbegin(plaintext, x); + final byte[] ciphertext = xor(plaintext, x); return ArrayUtils.addAll(iv, ciphertext); } @@ -96,9 +95,7 @@ final class AesSivCipherUtil { aes.reset(); } - final byte[] plaintext = xorbegin(actualCiphertext, x); - - Hex.encodeHexString(actualCiphertext); + final byte[] plaintext = xor(actualCiphertext, x); final byte[] control = s2v(k1, plaintext, additionalData); @@ -178,27 +175,6 @@ final class AesSivCipherUtil { } private static byte[] xor(byte[] in1, byte[] in2) { - if (in1 == null || in2 == null || in1.length != in2.length) { - throw new IllegalArgumentException("Inputs must equal in length."); - } - - return xorbegin(in1, in2); - } - - private static byte[] xorend(byte[] in1, byte[] in2) { - if (in1 == null || in2 == null || in1.length < in2.length) { - throw new IllegalArgumentException("Length of first input must be >= length of second input."); - } - - final byte[] result = new byte[in2.length]; - final int diff = in1.length - in2.length; - for (int i = 0; i < in2.length; i++) { - result[i] = (byte) (in1[i + diff] ^ in2[i]); - } - return result; - } - - private static byte[] xorbegin(byte[] in1, byte[] in2) { if (in1 == null || in2 == null || in1.length > in2.length) { throw new IllegalArgumentException("Length of first input must be <= length of second input."); } @@ -210,4 +186,17 @@ final class AesSivCipherUtil { return result; } + private static byte[] xorend(byte[] in1, byte[] in2) { + if (in1 == null || in2 == null || in1.length < in2.length) { + throw new IllegalArgumentException("Length of first input must be >= length of second input."); + } + + final byte[] result = Arrays.copyOf(in1, in1.length); + final int diff = in1.length - in2.length; + for (int i = 0; i < in2.length; i++) { + result[i + diff] = (byte) (result[i + diff] ^ in2[i]); + } + return result; + } + } diff --git a/main/crypto-aes/src/test/java/org/cryptomator/crypto/aes256/AesSivCipherUtilTest.java b/main/crypto-aes/src/test/java/org/cryptomator/crypto/aes256/AesSivCipherUtilTest.java index c122b94b8..1e355fee5 100644 --- a/main/crypto-aes/src/test/java/org/cryptomator/crypto/aes256/AesSivCipherUtilTest.java +++ b/main/crypto-aes/src/test/java/org/cryptomator/crypto/aes256/AesSivCipherUtilTest.java @@ -147,4 +147,75 @@ public class AesSivCipherUtilTest { final byte[] result = AesSivCipherUtil.sivDecrypt(key, ciphertext, ad); Assert.assertArrayEquals(expected, result); } + + /** + * https://tools.ietf.org/html/rfc5297#appendix-A.2 + */ + @Test + public void testNonceBasedAuthenticatedEncryption() throws InvalidKeyException { + + final byte[] key = {(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) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47, // + (byte) 0x48, (byte) 0x49, (byte) 0x4a, (byte) 0x4b, // + (byte) 0x4c, (byte) 0x4d, (byte) 0x4e, (byte) 0x4f}; + + final byte[] ad1 = {(byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33, // + (byte) 0x44, (byte) 0x55, (byte) 0x66, (byte) 0x77, // + (byte) 0x88, (byte) 0x99, (byte) 0xaa, (byte) 0xbb, // + (byte) 0xcc, (byte) 0xdd, (byte) 0xee, (byte) 0xff, // + (byte) 0xde, (byte) 0xad, (byte) 0xda, (byte) 0xda, // + (byte) 0xde, (byte) 0xad, (byte) 0xda, (byte) 0xda, // + (byte) 0xff, (byte) 0xee, (byte) 0xdd, (byte) 0xcc, // + (byte) 0xbb, (byte) 0xaa, (byte) 0x99, (byte) 0x88, // + (byte) 0x77, (byte) 0x66, (byte) 0x55, (byte) 0x44, // + (byte) 0x33, (byte) 0x22, (byte) 0x11, (byte) 0x00}; + + final byte[] ad2 = {(byte) 0x10, (byte) 0x20, (byte) 0x30, (byte) 0x40, // + (byte) 0x50, (byte) 0x60, (byte) 0x70, (byte) 0x80, // + (byte) 0x90, (byte) 0xa0}; + + final byte[] nonce = {(byte) 0x09, (byte) 0xf9, (byte) 0x11, (byte) 0x02, // + (byte) 0x9d, (byte) 0x74, (byte) 0xe3, (byte) 0x5b, // + (byte) 0xd8, (byte) 0x41, (byte) 0x56, (byte) 0xc5, // + (byte) 0x63, (byte) 0x56, (byte) 0x88, (byte) 0xc0}; + + final byte[] plaintext = {(byte) 0x74, (byte) 0x68, (byte) 0x69, (byte) 0x73, // + (byte) 0x20, (byte) 0x69, (byte) 0x73, (byte) 0x20, // + (byte) 0x73, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, // + (byte) 0x20, (byte) 0x70, (byte) 0x6c, (byte) 0x61, // + (byte) 0x69, (byte) 0x6e, (byte) 0x74, (byte) 0x65, // + (byte) 0x78, (byte) 0x74, (byte) 0x20, (byte) 0x74, // + (byte) 0x6f, (byte) 0x20, (byte) 0x65, (byte) 0x6e, // + (byte) 0x63, (byte) 0x72, (byte) 0x79, (byte) 0x70, // + (byte) 0x74, (byte) 0x20, (byte) 0x75, (byte) 0x73, // + (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x20, // + (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[] expected = {(byte) 0x7b, (byte) 0xdb, (byte) 0x6e, (byte) 0x3b, // + (byte) 0x43, (byte) 0x26, (byte) 0x67, (byte) 0xeb, // + (byte) 0x06, (byte) 0xf4, (byte) 0xd1, (byte) 0x4b, // + (byte) 0xff, (byte) 0x2f, (byte) 0xbd, (byte) 0x0f, // + (byte) 0xcb, (byte) 0x90, (byte) 0x0f, (byte) 0x2f, // + (byte) 0xdd, (byte) 0xbe, (byte) 0x40, (byte) 0x43, // + (byte) 0x26, (byte) 0x60, (byte) 0x19, (byte) 0x65, // + (byte) 0xc8, (byte) 0x89, (byte) 0xbf, (byte) 0x17, // + (byte) 0xdb, (byte) 0xa7, (byte) 0x7c, (byte) 0xeb, // + (byte) 0x09, (byte) 0x4f, (byte) 0xa6, (byte) 0x63, // + (byte) 0xb7, (byte) 0xa3, (byte) 0xf7, (byte) 0x48, // + (byte) 0xba, (byte) 0x8a, (byte) 0xf8, (byte) 0x29, // + (byte) 0xea, (byte) 0x64, (byte) 0xad, (byte) 0x54, // + (byte) 0x4a, (byte) 0x27, (byte) 0x2e, (byte) 0x9c, // + (byte) 0x48, (byte) 0x5b, (byte) 0x62, (byte) 0xa3, // + (byte) 0xfd, (byte) 0x5c, (byte) 0x0d}; + + Assert.assertArrayEquals(expected, result); + + } }