Temporary storage crypto doesn't need AAD, so it can use a Cipher.

This commit is contained in:
akwizgran
2013-03-06 23:01:01 +00:00
parent 91a068c4bd
commit edaf4e4b23

View File

@@ -8,7 +8,6 @@ import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
@@ -58,6 +57,7 @@ class CryptoComponentImpl implements CryptoComponent {
private static final String SIGNATURE_ALGO = "ECDSA"; private static final String SIGNATURE_ALGO = "ECDSA";
private static final String TAG_CIPHER_ALGO = "AES/ECB/NoPadding"; private static final String TAG_CIPHER_ALGO = "AES/ECB/NoPadding";
private static final int GCM_MAC_LENGTH = 16; // 128 bits private static final int GCM_MAC_LENGTH = 16; // 128 bits
private static final String STORAGE_CIPHER_ALGO = "AES/GCM";
private static final int STORAGE_IV_LENGTH = 32; // 256 bits private static final int STORAGE_IV_LENGTH = 32; // 256 bits
// Labels for key derivation // Labels for key derivation
@@ -383,56 +383,47 @@ class CryptoComponentImpl implements CryptoComponent {
return new AuthenticatedCipherImpl(cipher, GCM_MAC_LENGTH); return new AuthenticatedCipherImpl(cipher, GCM_MAC_LENGTH);
} }
private AuthenticatedCipher getTemporaryStorageCipher() { public byte[] encryptTemporaryStorage(byte[] input) {
// This code is specific to BouncyCastle because javax.crypto.Cipher
// doesn't support additional authenticated data until Java 7
AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine());
return new AuthenticatedCipherImpl(cipher, GCM_MAC_LENGTH);
}
public byte[] encryptTemporaryStorage(byte[] plaintext) {
AuthenticatedCipher cipher = getTemporaryStorageCipher();
// Generate a random IV // Generate a random IV
byte[] iv = new byte[STORAGE_IV_LENGTH]; byte[] ivBytes = new byte[STORAGE_IV_LENGTH];
secureRandom.nextBytes(iv); secureRandom.nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
// The output contains the IV, ciphertext and MAC // The output contains the IV, ciphertext and MAC
int ciphertextLength = iv.length + plaintext.length + GCM_MAC_LENGTH; int outputLen = STORAGE_IV_LENGTH + input.length + GCM_MAC_LENGTH;
byte[] ciphertext = new byte[ciphertextLength]; byte[] output = new byte[outputLen];
System.arraycopy(iv, 0, ciphertext, 0, iv.length); System.arraycopy(ivBytes, 0, output, 0, STORAGE_IV_LENGTH);
// Initialise the cipher and encrypt the plaintext // Initialise the cipher and encrypt the plaintext
Cipher cipher;
try { try {
cipher.init(ENCRYPT_MODE, temporaryStorageKey, iv, null); cipher = Cipher.getInstance(STORAGE_CIPHER_ALGO, PROVIDER);
cipher.doFinal(plaintext, 0, plaintext.length, ciphertext, cipher.init(ENCRYPT_MODE, temporaryStorageKey, iv);
iv.length); cipher.doFinal(input, 0, input.length, output,
STORAGE_IV_LENGTH);
} catch(GeneralSecurityException e) { } catch(GeneralSecurityException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return ciphertext; return output;
} }
public byte[] decryptTemporaryStorage(byte[] ciphertext) { public byte[] decryptTemporaryStorage(byte[] input) {
// The input contains the IV, ciphertext and MAC // The input contains the IV, ciphertext and MAC
if(ciphertext.length < STORAGE_IV_LENGTH + GCM_MAC_LENGTH) if(input.length < STORAGE_IV_LENGTH + GCM_MAC_LENGTH)
throw new IllegalArgumentException(); return null; // Invalid
AuthenticatedCipher cipher = getTemporaryStorageCipher(); IvParameterSpec iv = new IvParameterSpec(input, 0, STORAGE_IV_LENGTH);
// Copy the IV
byte[] iv = new byte[STORAGE_IV_LENGTH];
System.arraycopy(ciphertext, 0, iv, 0, iv.length);
// Initialise the cipher // Initialise the cipher
Cipher cipher;
try { try {
cipher.init(DECRYPT_MODE, temporaryStorageKey, iv, null); cipher = Cipher.getInstance(STORAGE_CIPHER_ALGO, PROVIDER);
} catch(InvalidKeyException e) { cipher.init(DECRYPT_MODE, temporaryStorageKey, iv);
} catch(GeneralSecurityException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
// Try to decrypt the ciphertext (may be invalid) // Try to decrypt the ciphertext (may be invalid)
int plaintextLength = ciphertext.length - iv.length - GCM_MAC_LENGTH;
byte[] plaintext = new byte[plaintextLength];
try { try {
cipher.doFinal(ciphertext, iv.length, ciphertext.length - iv.length, return cipher.doFinal(input, STORAGE_IV_LENGTH,
plaintext, 0); input.length - STORAGE_IV_LENGTH);
} catch(GeneralSecurityException e) { } catch(GeneralSecurityException e) {
return null; // Invalid ciphertext return null; // Invalid
} }
return plaintext;
} }
} }