Migrate from SQLite and ciphertext blobs to SQLCipher + KeyStore

This commit is contained in:
Moxie Marlinspike
2018-01-24 19:17:44 -08:00
parent d1819b6361
commit f36b296e2e
134 changed files with 3633 additions and 3544 deletions

View File

@@ -4,9 +4,12 @@ package org.thoughtcrime.securesms.video;
import android.annotation.TargetApi;
import android.media.MediaDataSource;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.crypto.DecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
import org.thoughtcrime.securesms.util.Util;
import java.io.File;
@@ -16,17 +19,26 @@ import java.io.InputStream;
@TargetApi(Build.VERSION_CODES.M)
public class EncryptedMediaDataSource extends MediaDataSource {
private final File mediaFile;
private final MasterSecret masterSecret;
private final AttachmentSecret attachmentSecret;
private final File mediaFile;
private final byte[] random;
private final long length;
public EncryptedMediaDataSource(MasterSecret masterSecret, File mediaFile) {
this.mediaFile = mediaFile;
this.masterSecret = masterSecret;
public EncryptedMediaDataSource(@NonNull AttachmentSecret attachmentSecret, @NonNull File mediaFile, @Nullable byte[] random, long length) {
this.attachmentSecret = attachmentSecret;
this.mediaFile = mediaFile;
this.random = random;
this.length = length;
}
@Override
public int readAt(long position, byte[] bytes, int offset, int length) throws IOException {
InputStream inputStream = DecryptingPartInputStream.createFor(masterSecret, mediaFile);
if (random == null) return readAtClassic(position, bytes, offset, length);
else return readAtModern(position, bytes, offset, length);
}
private int readAtClassic(long position, byte[] bytes, int offset, int length) throws IOException {
InputStream inputStream = ClassicDecryptingPartInputStream.createFor(attachmentSecret, mediaFile);
byte[] buffer = new byte[4096];
long headerRemaining = position;
@@ -43,19 +55,24 @@ public class EncryptedMediaDataSource extends MediaDataSource {
return returnValue;
}
@Override
public long getSize() throws IOException {
InputStream inputStream = DecryptingPartInputStream.createFor(masterSecret, mediaFile);
byte[] buffer = new byte[4096];
long size = 0;
private int readAtModern(long position, byte[] bytes, int offset, int length) throws IOException {
assert(random != null);
int read;
InputStream inputStream = ModernDecryptingPartInputStream.createFor(attachmentSecret, random, mediaFile);
while ((read = inputStream.read(buffer)) != -1) {
size += read;
if (inputStream.skip(position) != position) {
throw new IOException("Skip failed: " + position);
}
return size;
int returnValue = inputStream.read(bytes, offset, length);
inputStream.close();
return returnValue;
}
@Override
public long getSize() throws IOException {
return length;
}
@Override

View File

@@ -53,7 +53,6 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.AttachmentServer;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.util.ViewUtil;
@@ -95,11 +94,11 @@ public class VideoPlayer extends FrameLayout {
}
}
public void setVideoSource(@NonNull MasterSecret masterSecret, @NonNull VideoSlide videoSource, boolean autoplay)
public void setVideoSource(@NonNull VideoSlide videoSource, boolean autoplay)
throws IOException
{
if (Build.VERSION.SDK_INT >= 16) setExoViewSource(masterSecret, videoSource, autoplay);
else setVideoViewSource(masterSecret, videoSource, autoplay);
if (Build.VERSION.SDK_INT >= 16) setExoViewSource(videoSource, autoplay);
else setVideoViewSource(videoSource, autoplay);
}
public void pause() {
@@ -124,7 +123,7 @@ public class VideoPlayer extends FrameLayout {
this.window = window;
}
private void setExoViewSource(@NonNull MasterSecret masterSecret, @NonNull VideoSlide videoSource, boolean autoplay)
private void setExoViewSource(@NonNull VideoSlide videoSource, boolean autoplay)
throws IOException
{
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
@@ -138,7 +137,7 @@ public class VideoPlayer extends FrameLayout {
exoView.setPlayer(exoPlayer);
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(getContext(), "GenericUserAgent", null);
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(getContext(), masterSecret, defaultDataSourceFactory, null);
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(getContext(), defaultDataSourceFactory, null);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(videoSource.getUri(), attachmentDataSourceFactory, extractorsFactory, null, null);
@@ -147,7 +146,7 @@ public class VideoPlayer extends FrameLayout {
exoPlayer.setPlayWhenReady(autoplay);
}
private void setVideoViewSource(@NonNull MasterSecret masterSecret, @NonNull VideoSlide videoSource, boolean autoplay)
private void setVideoViewSource(@NonNull VideoSlide videoSource, boolean autoplay)
throws IOException
{
if (this.attachmentServer != null) {
@@ -156,7 +155,7 @@ public class VideoPlayer extends FrameLayout {
if (videoSource.getUri() != null && PartAuthority.isLocalUri(videoSource.getUri())) {
Log.w(TAG, "Starting video attachment server for part provider Uri...");
this.attachmentServer = new AttachmentServer(getContext(), masterSecret, videoSource.asAttachment());
this.attachmentServer = new AttachmentServer(getContext(), videoSource.asAttachment());
this.attachmentServer.start();
//noinspection ConstantConditions

View File

@@ -9,22 +9,18 @@ import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.TransferListener;
import org.thoughtcrime.securesms.crypto.MasterSecret;
public class AttachmentDataSourceFactory implements DataSource.Factory {
private final Context context;
private final MasterSecret masterSecret;
private final Context context;
private final DefaultDataSourceFactory defaultDataSourceFactory;
private final TransferListener<? super DataSource> listener;
public AttachmentDataSourceFactory(@NonNull Context context, @NonNull MasterSecret masterSecret,
public AttachmentDataSourceFactory(@NonNull Context context,
@NonNull DefaultDataSourceFactory defaultDataSourceFactory,
@Nullable TransferListener<? super DataSource> listener)
{
this.context = context;
this.masterSecret = masterSecret;
this.defaultDataSourceFactory = defaultDataSourceFactory;
this.listener = listener;
}
@@ -32,6 +28,6 @@ public class AttachmentDataSourceFactory implements DataSource.Factory {
@Override
public AttachmentDataSource createDataSource() {
return new AttachmentDataSource(defaultDataSourceFactory.createDataSource(),
new PartDataSource(context, masterSecret, listener));
new PartDataSource(context, listener));
}
}

View File

@@ -23,19 +23,15 @@ import java.io.InputStream;
public class PartDataSource implements DataSource {
private final @NonNull Context context;
private final @NonNull MasterSecret masterSecret;
private final @Nullable TransferListener<? super PartDataSource> listener;
private Uri uri;
private InputStream inputSteam;
public PartDataSource(@NonNull Context context,
@NonNull MasterSecret masterSecret,
@Nullable TransferListener<? super PartDataSource> listener)
public PartDataSource(@NonNull Context context, @Nullable TransferListener<? super PartDataSource> listener)
{
this.context = context.getApplicationContext();
this.masterSecret = masterSecret;
this.listener = listener;
this.context = context.getApplicationContext();
this.listener = listener;
}
@Override
@@ -44,11 +40,11 @@ public class PartDataSource implements DataSource {
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
PartUriParser partUri = new PartUriParser(uri);
Attachment attachment = attachmentDatabase.getAttachment(masterSecret, partUri.getPartId());
Attachment attachment = attachmentDatabase.getAttachment(partUri.getPartId());
if (attachment == null) throw new IOException("Attachment not found");
this.inputSteam = attachmentDatabase.getAttachmentStream(masterSecret, partUri.getPartId());
this.inputSteam = attachmentDatabase.getAttachmentStream(partUri.getPartId());
if (inputSteam == null) throw new IOException("InputStream not foudn");