Merge branch '364-add-mac-to-crypto-component' into 'master'

Add MAC function to crypto component



See merge request !295
This commit is contained in:
Torsten Grote
2016-08-26 13:34:56 +00:00
3 changed files with 88 additions and 0 deletions

View File

@@ -143,6 +143,13 @@ public interface CryptoComponent {
*/
byte[] hash(byte[]... inputs);
/**
* Returns a message authentication code with the given key over the
* given inputs. The inputs are unambiguously combined by prefixing each
* input with its length.
*/
byte[] mac(SecretKey macKey, byte[]... inputs);
/**
* Encrypts and authenticates the given plaintext so it can be written to
* storage. The encryption and authentication keys are derived from the

View File

@@ -403,6 +403,20 @@ class CryptoComponentImpl implements CryptoComponent {
return digest.digest();
}
@Override
public byte[] mac(SecretKey macKey, byte[]... inputs) {
Digest mac = new Blake2sDigest(macKey.getBytes());
byte[] length = new byte[INT_32_BYTES];
for (byte[] input : inputs) {
ByteUtils.writeUint32(input.length, length, 0);
mac.update(length, 0, length.length);
mac.update(input, 0, input.length);
}
byte[] output = new byte[mac.getDigestSize()];
mac.doFinal(output, 0);
return output;
}
@Override
public byte[] encryptWithPassword(byte[] input, String password) {
AuthenticatedCipher cipher = new XSalsa20Poly1305AuthenticatedCipher();

View File

@@ -0,0 +1,67 @@
package org.briarproject.crypto;
import org.briarproject.BriarTestCase;
import org.briarproject.TestSeedProvider;
import org.briarproject.TestUtils;
import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.SecretKey;
import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse;
public class MacTest extends BriarTestCase {
private final CryptoComponent crypto;
public MacTest() {
crypto = new CryptoComponentImpl(new TestSeedProvider());
}
@Test
public void testIdenticalKeysAndInputsProduceIdenticalMacs() {
// Generate a random key and some random input
byte[] keyBytes = TestUtils.getRandomBytes(SecretKey.LENGTH);
SecretKey k = new SecretKey(keyBytes);
byte[] inputBytes = TestUtils.getRandomBytes(123);
byte[] inputBytes1 = TestUtils.getRandomBytes(234);
byte[] inputBytes2 = new byte[0];
// Calculate the MAC twice - the results should be identical
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
byte[] mac1 = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
assertArrayEquals(mac, mac1);
}
@Test
public void testDifferentKeysProduceDifferentMacs() {
// Generate two random keys and some random input
byte[] keyBytes = TestUtils.getRandomBytes(SecretKey.LENGTH);
SecretKey k = new SecretKey(keyBytes);
byte[] keyBytes1 = TestUtils.getRandomBytes(SecretKey.LENGTH);
SecretKey k1 = new SecretKey(keyBytes1);
byte[] inputBytes = TestUtils.getRandomBytes(123);
byte[] inputBytes1 = TestUtils.getRandomBytes(234);
byte[] inputBytes2 = new byte[0];
// Calculate the MAC with each key - the results should be different
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
byte[] mac1 = crypto.mac(k1, inputBytes, inputBytes1, inputBytes2);
assertFalse(Arrays.equals(mac, mac1));
}
@Test
public void testDifferentInputsProduceDifferentMacs() {
// Generate a random key and some random input
byte[] keyBytes = TestUtils.getRandomBytes(SecretKey.LENGTH);
SecretKey k = new SecretKey(keyBytes);
byte[] inputBytes = TestUtils.getRandomBytes(123);
byte[] inputBytes1 = TestUtils.getRandomBytes(234);
byte[] inputBytes2 = new byte[0];
// Calculate the MAC with the inputs in different orders - the results
// should be different
byte[] mac = crypto.mac(k, inputBytes, inputBytes1, inputBytes2);
byte[] mac1 = crypto.mac(k, inputBytes2, inputBytes1, inputBytes);
assertFalse(Arrays.equals(mac, mac1));
}
}