Have stream generate random value

This commit is contained in:
Moxie Marlinspike
2018-02-01 13:30:33 -08:00
parent c004ead940
commit bdd4b456c4
4 changed files with 52 additions and 19 deletions

View File

@@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
@@ -23,21 +24,47 @@ public class ModernDecryptingPartInputStream {
public static InputStream createFor(@NonNull AttachmentSecret attachmentSecret, @NonNull byte[] random, @NonNull File file)
throws IOException
{
return createFor(attachmentSecret, random, new FileInputStream(file));
}
public static InputStream createFor(@NonNull AttachmentSecret attachmentSecret, @NonNull File file)
throws IOException
{
FileInputStream inputStream = new FileInputStream(file);
byte[] random = new byte[32];
readFully(inputStream, random);
return createFor(attachmentSecret, random, inputStream);
}
private static InputStream createFor(@NonNull AttachmentSecret attachmentSecret, @NonNull byte[] random, @NonNull InputStream inputStream) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(attachmentSecret.getModernKey(), "HmacSHA256"));
FileInputStream fileInputStream = new FileInputStream(file);
byte[] iv = new byte[16];
byte[] key = mac.doFinal(random);
byte[] iv = new byte[16];
byte[] key = mac.doFinal(random);
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
return new CipherInputStream(fileInputStream, cipher);
return new CipherInputStream(inputStream, cipher);
} catch (NoSuchAlgorithmException | InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException e) {
throw new AssertionError(e);
}
}
private static void readFully(InputStream in, byte[] buffer) throws IOException {
int offset = 0;
for (;;) {
int read = in.read(buffer, offset, buffer.length-offset);
if (read + offset < buffer.length) offset += read;
else return;
}
}
}

View File

@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.crypto;
import android.support.annotation.NonNull;
import android.util.Pair;
import java.io.File;
import java.io.FileOutputStream;
@@ -10,6 +11,7 @@ import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
@@ -25,9 +27,12 @@ import javax.crypto.spec.SecretKeySpec;
*/
public class ModernEncryptingPartOutputStream {
public static OutputStream createFor(@NonNull AttachmentSecret attachmentSecret, byte[] random, File file)
public static Pair<byte[], OutputStream> createFor(@NonNull AttachmentSecret attachmentSecret, @NonNull File file, boolean inline)
throws IOException
{
byte[] random = new byte[32];
new SecureRandom().nextBytes(random);
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(attachmentSecret.getModernKey(), "HmacSHA256"));
@@ -39,7 +44,11 @@ public class ModernEncryptingPartOutputStream {
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
return new CipherOutputStream(fileOutputStream, cipher);
if (inline) {
fileOutputStream.write(random);
}
return new Pair<>(random, new CipherOutputStream(fileOutputStream, cipher));
} catch (NoSuchAlgorithmException | InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException e) {
throw new AssertionError(e);
}