mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 11:49:04 +01:00
Remove AAD from AuthenticatedCipher interface.
This commit is contained in:
@@ -2,14 +2,12 @@ package org.briarproject.api.crypto;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/** An authenticated cipher that supports additional authenticated data. */
|
||||
public interface AuthenticatedCipher {
|
||||
|
||||
/**
|
||||
* Initializes this cipher with a key, an initialisation vector (IV) and
|
||||
* additional authenticated data (AAD).
|
||||
* Initializes this cipher with a key and an initialisation vector (IV).
|
||||
*/
|
||||
void init(boolean encrypt, SecretKey key, byte[] iv, byte[] aad)
|
||||
void init(boolean encrypt, SecretKey key, byte[] iv)
|
||||
throws GeneralSecurityException;
|
||||
|
||||
/** Encrypts or decrypts data in a single-part operation. */
|
||||
@@ -17,8 +15,8 @@ public interface AuthenticatedCipher {
|
||||
int outputOff) throws GeneralSecurityException;
|
||||
|
||||
/** Returns the length of the message authentication code (MAC) in bytes. */
|
||||
int getMacLength();
|
||||
int getMacBytes();
|
||||
|
||||
/** Returns the block size of the cipher in bytes. */
|
||||
int getBlockSize();
|
||||
int getBlockBytes();
|
||||
}
|
||||
|
||||
@@ -6,18 +6,22 @@ import org.briarproject.api.crypto.AuthenticatedCipher;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.spongycastle.crypto.DataLengthException;
|
||||
import org.spongycastle.crypto.InvalidCipherTextException;
|
||||
import org.spongycastle.crypto.engines.AESLightEngine;
|
||||
import org.spongycastle.crypto.modes.AEADBlockCipher;
|
||||
import org.spongycastle.crypto.modes.GCMBlockCipher;
|
||||
import org.spongycastle.crypto.modes.gcm.BasicGCMMultiplier;
|
||||
import org.spongycastle.crypto.params.AEADParameters;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
|
||||
class AuthenticatedCipherImpl implements AuthenticatedCipher {
|
||||
|
||||
private final AEADBlockCipher cipher;
|
||||
private final int macLength;
|
||||
private static final int MAC_BYTES = 16;
|
||||
|
||||
AuthenticatedCipherImpl(AEADBlockCipher cipher, int macLength) {
|
||||
this.cipher = cipher;
|
||||
this.macLength = macLength;
|
||||
private final AEADBlockCipher cipher;
|
||||
|
||||
AuthenticatedCipherImpl() {
|
||||
cipher = new GCMBlockCipher(new AESLightEngine(),
|
||||
new BasicGCMMultiplier());
|
||||
}
|
||||
|
||||
public int process(byte[] input, int inputOff, int len, byte[] output,
|
||||
@@ -36,10 +40,11 @@ class AuthenticatedCipherImpl implements AuthenticatedCipher {
|
||||
}
|
||||
}
|
||||
|
||||
public void init(boolean encrypt, SecretKey key, byte[] iv, byte[] aad)
|
||||
public void init(boolean encrypt, SecretKey key, byte[] iv)
|
||||
throws GeneralSecurityException {
|
||||
KeyParameter k = new KeyParameter(key.getBytes());
|
||||
AEADParameters params = new AEADParameters(k, macLength * 8, iv, aad);
|
||||
// Authenticate the IV by passing it as additional authenticated data
|
||||
AEADParameters params = new AEADParameters(k, MAC_BYTES * 8, iv, iv);
|
||||
try {
|
||||
cipher.init(encrypt, params);
|
||||
} catch(IllegalArgumentException e) {
|
||||
@@ -47,11 +52,11 @@ class AuthenticatedCipherImpl implements AuthenticatedCipher {
|
||||
}
|
||||
}
|
||||
|
||||
public int getMacLength() {
|
||||
return macLength;
|
||||
public int getMacBytes() {
|
||||
return MAC_BYTES;
|
||||
}
|
||||
|
||||
public int getBlockSize() {
|
||||
public int getBlockBytes() {
|
||||
return cipher.getUnderlyingCipher().getBlockSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,6 @@ import org.spongycastle.crypto.engines.AESLightEngine;
|
||||
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator;
|
||||
import org.spongycastle.crypto.macs.HMac;
|
||||
import org.spongycastle.crypto.modes.AEADBlockCipher;
|
||||
import org.spongycastle.crypto.modes.GCMBlockCipher;
|
||||
import org.spongycastle.crypto.modes.gcm.BasicGCMMultiplier;
|
||||
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
@@ -57,7 +54,6 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
private static final int CIPHER_KEY_BYTES = 32; // 256 bits
|
||||
private static final int AGREEMENT_KEY_PAIR_BITS = 384;
|
||||
private static final int SIGNATURE_KEY_PAIR_BITS = 384;
|
||||
private static final int MAC_BYTES = 16; // 128 bits
|
||||
private static final int STORAGE_IV_BYTES = 16; // 128 bits
|
||||
private static final int PBKDF_SALT_BYTES = 16; // 128 bits
|
||||
private static final int PBKDF_TARGET_MILLIS = 500;
|
||||
@@ -299,9 +295,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
|
||||
private AuthenticatedCipher getAuthenticatedCipher() {
|
||||
AEADBlockCipher a = new GCMBlockCipher(new AESLightEngine(),
|
||||
new BasicGCMMultiplier());
|
||||
return new AuthenticatedCipherImpl(a, MAC_BYTES);
|
||||
return new AuthenticatedCipherImpl();
|
||||
}
|
||||
|
||||
public void encodeTag(byte[] tag, SecretKey tagKey, long streamNumber) {
|
||||
@@ -318,6 +312,8 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
|
||||
public byte[] encryptWithPassword(byte[] input, String password) {
|
||||
AuthenticatedCipher cipher = getAuthenticatedCipher();
|
||||
int macBytes = cipher.getMacBytes();
|
||||
// Generate a random salt
|
||||
byte[] salt = new byte[PBKDF_SALT_BYTES];
|
||||
secureRandom.nextBytes(salt);
|
||||
@@ -329,15 +325,14 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
byte[] iv = new byte[STORAGE_IV_BYTES];
|
||||
secureRandom.nextBytes(iv);
|
||||
// The output contains the salt, iterations, IV, ciphertext and MAC
|
||||
int outputLen = salt.length + 4 + iv.length + input.length + MAC_BYTES;
|
||||
int outputLen = salt.length + 4 + iv.length + input.length + macBytes;
|
||||
byte[] output = new byte[outputLen];
|
||||
System.arraycopy(salt, 0, output, 0, salt.length);
|
||||
ByteUtils.writeUint32(iterations, output, salt.length);
|
||||
System.arraycopy(iv, 0, output, salt.length + 4, iv.length);
|
||||
// Initialise the cipher and encrypt the plaintext
|
||||
AuthenticatedCipher cipher = getAuthenticatedCipher();
|
||||
try {
|
||||
cipher.init(true, key, iv, null);
|
||||
cipher.init(true, key, iv);
|
||||
int outputOff = salt.length + 4 + iv.length;
|
||||
cipher.process(input, 0, input.length, output, outputOff);
|
||||
return output;
|
||||
@@ -347,22 +342,23 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
|
||||
public byte[] decryptWithPassword(byte[] input, String password) {
|
||||
AuthenticatedCipher cipher = getAuthenticatedCipher();
|
||||
int macBytes = cipher.getMacBytes();
|
||||
// The input contains the salt, iterations, IV, ciphertext and MAC
|
||||
if(input.length < PBKDF_SALT_BYTES + 4 + STORAGE_IV_BYTES + MAC_BYTES)
|
||||
if(input.length < PBKDF_SALT_BYTES + 4 + STORAGE_IV_BYTES + macBytes)
|
||||
return null; // Invalid
|
||||
byte[] salt = new byte[PBKDF_SALT_BYTES];
|
||||
System.arraycopy(input, 0, salt, 0, salt.length);
|
||||
long iterations = ByteUtils.readUint32(input, salt.length);
|
||||
if(iterations < 0 || iterations > Integer.MAX_VALUE)
|
||||
return null; // Invalid
|
||||
return null; // Invalid iteration count
|
||||
byte[] iv = new byte[STORAGE_IV_BYTES];
|
||||
System.arraycopy(input, salt.length + 4, iv, 0, iv.length);
|
||||
// Derive the key from the password
|
||||
SecretKey key = new SecretKey(pbkdf2(password, salt, (int) iterations));
|
||||
// Initialise the cipher
|
||||
AuthenticatedCipher cipher = getAuthenticatedCipher();
|
||||
try {
|
||||
cipher.init(false, key, iv, null);
|
||||
cipher.init(false, key, iv);
|
||||
} catch(GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -370,7 +366,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
try {
|
||||
int inputOff = salt.length + 4 + iv.length;
|
||||
int inputLen = input.length - inputOff;
|
||||
byte[] output = new byte[inputLen - MAC_BYTES];
|
||||
byte[] output = new byte[inputLen - macBytes];
|
||||
cipher.process(input, inputOff, inputLen, output, 0);
|
||||
return output;
|
||||
} catch(GeneralSecurityException e) {
|
||||
|
||||
@@ -21,7 +21,7 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
||||
private final InputStream in;
|
||||
private final AuthenticatedCipher frameCipher;
|
||||
private final SecretKey frameKey;
|
||||
private final byte[] iv, aad, header, ciphertext;
|
||||
private final byte[] iv, header, ciphertext;
|
||||
|
||||
private long frameNumber;
|
||||
private boolean finalFrame;
|
||||
@@ -32,7 +32,6 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
||||
this.frameCipher = frameCipher;
|
||||
this.frameKey = frameKey;
|
||||
iv = new byte[IV_LENGTH];
|
||||
aad = new byte[IV_LENGTH];
|
||||
header = new byte[HEADER_LENGTH];
|
||||
ciphertext = new byte[MAX_FRAME_LENGTH];
|
||||
frameNumber = 0;
|
||||
@@ -52,9 +51,8 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
||||
}
|
||||
// Decrypt and authenticate the header
|
||||
FrameEncoder.encodeIv(iv, frameNumber, true);
|
||||
FrameEncoder.encodeIv(aad, frameNumber, true);
|
||||
try {
|
||||
frameCipher.init(false, frameKey, iv, aad);
|
||||
frameCipher.init(false, frameKey, iv);
|
||||
int decrypted = frameCipher.process(ciphertext, 0, HEADER_LENGTH,
|
||||
header, 0);
|
||||
if(decrypted != HEADER_LENGTH - MAC_LENGTH)
|
||||
@@ -78,9 +76,8 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
||||
}
|
||||
// Decrypt and authenticate the payload and padding
|
||||
FrameEncoder.encodeIv(iv, frameNumber, false);
|
||||
FrameEncoder.encodeIv(aad, frameNumber, false);
|
||||
try {
|
||||
frameCipher.init(false, frameKey, iv, aad);
|
||||
frameCipher.init(false, frameKey, iv);
|
||||
int decrypted = frameCipher.process(ciphertext, HEADER_LENGTH,
|
||||
payloadLength + paddingLength + MAC_LENGTH, payload, 0);
|
||||
if(decrypted != payloadLength + paddingLength)
|
||||
|
||||
@@ -20,7 +20,7 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
||||
private final OutputStream out;
|
||||
private final AuthenticatedCipher frameCipher;
|
||||
private final SecretKey frameKey;
|
||||
private final byte[] tag, iv, aad, plaintext, ciphertext;
|
||||
private final byte[] tag, iv, plaintext, ciphertext;
|
||||
|
||||
private long frameNumber;
|
||||
private boolean writeTag;
|
||||
@@ -32,7 +32,6 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
||||
this.frameKey = frameKey;
|
||||
this.tag = tag;
|
||||
iv = new byte[IV_LENGTH];
|
||||
aad = new byte[IV_LENGTH];
|
||||
plaintext = new byte[HEADER_LENGTH + MAX_PAYLOAD_LENGTH];
|
||||
ciphertext = new byte[MAX_FRAME_LENGTH];
|
||||
frameNumber = 0;
|
||||
@@ -55,9 +54,8 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
||||
paddingLength);
|
||||
// Encrypt and authenticate the header
|
||||
FrameEncoder.encodeIv(iv, frameNumber, true);
|
||||
FrameEncoder.encodeIv(aad, frameNumber, true);
|
||||
try {
|
||||
frameCipher.init(true, frameKey, iv, aad);
|
||||
frameCipher.init(true, frameKey, iv);
|
||||
int encrypted = frameCipher.process(plaintext, 0,
|
||||
HEADER_LENGTH - MAC_LENGTH, ciphertext, 0);
|
||||
if(encrypted != HEADER_LENGTH) throw new RuntimeException();
|
||||
@@ -70,9 +68,8 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
||||
plaintext[HEADER_LENGTH + payloadLength + i] = 0;
|
||||
// Encrypt and authenticate the payload and padding
|
||||
FrameEncoder.encodeIv(iv, frameNumber, false);
|
||||
FrameEncoder.encodeIv(aad, frameNumber, false);
|
||||
try {
|
||||
frameCipher.init(true, frameKey, iv, aad);
|
||||
frameCipher.init(true, frameKey, iv);
|
||||
int encrypted = frameCipher.process(plaintext, HEADER_LENGTH,
|
||||
payloadLength + paddingLength, ciphertext, HEADER_LENGTH);
|
||||
if(encrypted != payloadLength + paddingLength + MAC_LENGTH)
|
||||
|
||||
@@ -13,7 +13,7 @@ class TestAuthenticatedCipher implements AuthenticatedCipher {
|
||||
|
||||
private boolean encrypt = false;
|
||||
|
||||
public void init(boolean encrypt, SecretKey key, byte[] iv, byte[] aad)
|
||||
public void init(boolean encrypt, SecretKey key, byte[] iv)
|
||||
throws GeneralSecurityException {
|
||||
this.encrypt = encrypt;
|
||||
}
|
||||
@@ -35,11 +35,11 @@ class TestAuthenticatedCipher implements AuthenticatedCipher {
|
||||
}
|
||||
}
|
||||
|
||||
public int getMacLength() {
|
||||
public int getMacBytes() {
|
||||
return MAC_LENGTH;
|
||||
}
|
||||
|
||||
public int getBlockSize() {
|
||||
public int getBlockBytes() {
|
||||
return BLOCK_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user