mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-24 07:58:50 -05:00
some playing with content stream decryption and providing the result as content stream
This commit is contained in:
parent
f03b349057
commit
3ac472125a
@ -37,7 +37,6 @@ import java.util.Date;
|
|||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -118,7 +117,8 @@ public class Apg {
|
|||||||
public static final String EXTRA_STATUS = "status";
|
public static final String EXTRA_STATUS = "status";
|
||||||
public static final String EXTRA_ERROR = "error";
|
public static final String EXTRA_ERROR = "error";
|
||||||
public static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage";
|
public static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage";
|
||||||
public static final String EXTRA_ENCRYPTED_MESSAGE = "decryptedMessage";
|
public static final String EXTRA_ENCRYPTED_MESSAGE = "encryptedMessage";
|
||||||
|
public static final String EXTRA_RESULT_URI = "resultUri";
|
||||||
public static final String EXTRA_SIGNATURE = "signature";
|
public static final String EXTRA_SIGNATURE = "signature";
|
||||||
public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId";
|
public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId";
|
||||||
public static final String EXTRA_SIGNATURE_USER_ID = "signatureUserId";
|
public static final String EXTRA_SIGNATURE_USER_ID = "signatureUserId";
|
||||||
@ -1851,4 +1851,43 @@ public class Apg {
|
|||||||
public static String getFullVersion(Context context) {
|
public static String getFullVersion(Context context) {
|
||||||
return "APG v" + getVersion(context);
|
return "APG v" + getVersion(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String generateRandomString(int length) {
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
/*
|
||||||
|
try {
|
||||||
|
random = SecureRandom.getInstance("SHA1PRNG", new BouncyCastleProvider());
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
// TODO: need to handle this case somehow
|
||||||
|
return null;
|
||||||
|
}*/
|
||||||
|
byte bytes[] = new byte[length];
|
||||||
|
random.nextBytes(bytes);
|
||||||
|
String result = "";
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
int v = ((int)bytes[i] + 256) % 64;
|
||||||
|
if (v < 10) {
|
||||||
|
result += (char)((int)'0' + v);
|
||||||
|
} else if (v < 36) {
|
||||||
|
result += (char)((int)'A' + v - 10);
|
||||||
|
} else if (v < 62) {
|
||||||
|
result += (char)((int)'a' + v - 36);
|
||||||
|
} else if (v == 62) {
|
||||||
|
result += '_';
|
||||||
|
} else if (v == 63) {
|
||||||
|
result += '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long getLengthOfStream(InputStream in) throws IOException {
|
||||||
|
long size = 0;
|
||||||
|
long n = 0;
|
||||||
|
byte dummy[] = new byte[0x10000];
|
||||||
|
while ((n = in.read(dummy)) > 0) {
|
||||||
|
size += n;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import java.util.regex.Matcher;
|
|||||||
|
|
||||||
import org.bouncycastle2.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle2.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle2.openpgp.PGPException;
|
import org.bouncycastle2.openpgp.PGPException;
|
||||||
|
import org.thialfihar.android.apg.provider.DataProvider;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
@ -86,6 +87,8 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
private String mInputFilename = null;
|
private String mInputFilename = null;
|
||||||
private String mOutputFilename = null;
|
private String mOutputFilename = null;
|
||||||
|
|
||||||
|
private Uri mContentUri = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@ -220,26 +223,29 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
mSource.showNext();
|
mSource.showNext();
|
||||||
}
|
}
|
||||||
} else if (Apg.Intent.DECRYPT_AND_RETURN.equals(mIntent.getAction())) {
|
} else if (Apg.Intent.DECRYPT_AND_RETURN.equals(mIntent.getAction())) {
|
||||||
Bundle extras = mIntent.getExtras();
|
mContentUri = mIntent.getData();
|
||||||
if (extras == null) {
|
if (mContentUri == null) {
|
||||||
extras = new Bundle();
|
Bundle extras = mIntent.getExtras();
|
||||||
}
|
if (extras == null) {
|
||||||
String data = extras.getString(Apg.EXTRA_TEXT);
|
extras = new Bundle();
|
||||||
if (data != null) {
|
}
|
||||||
Matcher matcher = Apg.PGP_MESSAGE.matcher(data);
|
String data = extras.getString(Apg.EXTRA_TEXT);
|
||||||
if (matcher.matches()) {
|
if (data != null) {
|
||||||
data = matcher.group(1);
|
Matcher matcher = Apg.PGP_MESSAGE.matcher(data);
|
||||||
// replace non breakable spaces
|
|
||||||
data = data.replaceAll("\\xa0", " ");
|
|
||||||
mMessage.setText(data);
|
|
||||||
} else {
|
|
||||||
matcher = Apg.PGP_SIGNED_MESSAGE.matcher(data);
|
|
||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
data = matcher.group(1);
|
data = matcher.group(1);
|
||||||
// replace non breakable spaces
|
// replace non breakable spaces
|
||||||
data = data.replaceAll("\\xa0", " ");
|
data = data.replaceAll("\\xa0", " ");
|
||||||
mMessage.setText(data);
|
mMessage.setText(data);
|
||||||
mDecryptButton.setText(R.string.btn_verify);
|
} else {
|
||||||
|
matcher = Apg.PGP_SIGNED_MESSAGE.matcher(data);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
data = matcher.group(1);
|
||||||
|
// replace non breakable spaces
|
||||||
|
data = data.replaceAll("\\xa0", " ");
|
||||||
|
mMessage.setText(data);
|
||||||
|
mDecryptButton.setText(R.string.btn_verify);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,7 +399,9 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
String error = null;
|
String error = null;
|
||||||
try {
|
try {
|
||||||
InputStream in;
|
InputStream in;
|
||||||
if (mDecryptTarget == Id.target.file) {
|
if (mContentUri != null) {
|
||||||
|
in = getContentResolver().openInputStream(mContentUri);
|
||||||
|
} else if (mDecryptTarget == Id.target.file) {
|
||||||
if (mInputFilename.startsWith("file")) {
|
if (mInputFilename.startsWith("file")) {
|
||||||
in = new FileInputStream(mInputFilename);
|
in = new FileInputStream(mInputFilename);
|
||||||
} else {
|
} else {
|
||||||
@ -412,7 +420,9 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
setSecretKeyId(Id.key.symmetric);
|
setSecretKeyId(Id.key.symmetric);
|
||||||
// look at the file/message again to check whether there's
|
// look at the file/message again to check whether there's
|
||||||
// symmetric encryption data in there
|
// symmetric encryption data in there
|
||||||
if (mDecryptTarget == Id.target.file) {
|
if (mContentUri != null) {
|
||||||
|
in = getContentResolver().openInputStream(mContentUri);
|
||||||
|
} else if (mDecryptTarget == Id.target.file) {
|
||||||
if (mInputFilename.startsWith("file")) {
|
if (mInputFilename.startsWith("file")) {
|
||||||
in = new FileInputStream(mInputFilename);
|
in = new FileInputStream(mInputFilename);
|
||||||
} else {
|
} else {
|
||||||
@ -494,22 +504,32 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
try {
|
try {
|
||||||
PositionAwareInputStream in = null;
|
PositionAwareInputStream in = null;
|
||||||
OutputStream out = null;
|
OutputStream out = null;
|
||||||
|
String randomString = null;
|
||||||
long size = 0;
|
long size = 0;
|
||||||
|
|
||||||
if (mDecryptTarget == Id.target.message) {
|
if (mContentUri != null) {
|
||||||
|
in = new PositionAwareInputStream(getContentResolver().openInputStream(mContentUri));
|
||||||
|
size = Apg.getLengthOfStream(getContentResolver().openInputStream(mContentUri));
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
randomString = Apg.generateRandomString(32);
|
||||||
|
if (randomString == null) {
|
||||||
|
throw new Apg.GeneralException("couldn't generate random file name");
|
||||||
|
}
|
||||||
|
this.openFileInput(randomString).close();
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
// found a name that isn't used yet
|
||||||
|
}
|
||||||
|
out = openFileOutput(randomString, MODE_PRIVATE);
|
||||||
|
} else if (mDecryptTarget == Id.target.message) {
|
||||||
String messageData = mMessage.getText().toString();
|
String messageData = mMessage.getText().toString();
|
||||||
in = new PositionAwareInputStream(new ByteArrayInputStream(messageData.getBytes()));
|
in = new PositionAwareInputStream(new ByteArrayInputStream(messageData.getBytes()));
|
||||||
out = new ByteArrayOutputStream();
|
out = new ByteArrayOutputStream();
|
||||||
size = messageData.getBytes().length;
|
size = messageData.getBytes().length;
|
||||||
} else {
|
} else {
|
||||||
if (mInputFilename.startsWith("content")) {
|
if (mInputFilename.startsWith("content")) {
|
||||||
InputStream tmp = getContentResolver().openInputStream(Uri.parse(mInputFilename));
|
size = Apg.getLengthOfStream(getContentResolver().openInputStream(Uri.parse(mInputFilename)));
|
||||||
size = 0;
|
|
||||||
long n = 0;
|
|
||||||
byte dummy[] = new byte[0x10000];
|
|
||||||
while ((n = tmp.read(dummy)) > 0) {
|
|
||||||
size += n;
|
|
||||||
}
|
|
||||||
in = new PositionAwareInputStream(
|
in = new PositionAwareInputStream(
|
||||||
getContentResolver().openInputStream(Uri.parse(mInputFilename)));
|
getContentResolver().openInputStream(Uri.parse(mInputFilename)));
|
||||||
} else {
|
} else {
|
||||||
@ -528,7 +548,10 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.close();
|
out.close();
|
||||||
if (mDecryptTarget == Id.target.message) {
|
|
||||||
|
if (randomString != null) {
|
||||||
|
data.putString(Apg.EXTRA_RESULT_URI, "content://" + DataProvider.AUTHORITY + "/data/" + randomString);
|
||||||
|
} else if (mDecryptTarget == Id.target.message) {
|
||||||
data.putString(Apg.EXTRA_DECRYPTED_MESSAGE,
|
data.putString(Apg.EXTRA_DECRYPTED_MESSAGE,
|
||||||
new String(((ByteArrayOutputStream) out).toByteArray()));
|
new String(((ByteArrayOutputStream) out).toByteArray()));
|
||||||
}
|
}
|
||||||
@ -570,6 +593,14 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Toast.makeText(this, R.string.decryptionSuccessful, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.decryptionSuccessful, Toast.LENGTH_SHORT).show();
|
||||||
|
if (mReturnResult) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtras(data);
|
||||||
|
setResult(RESULT_OK, intent);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (mDecryptTarget) {
|
switch (mDecryptTarget) {
|
||||||
case Id.target.message: {
|
case Id.target.message: {
|
||||||
String decryptedMessage = data.getString(Apg.EXTRA_DECRYPTED_MESSAGE);
|
String decryptedMessage = data.getString(Apg.EXTRA_DECRYPTED_MESSAGE);
|
||||||
@ -616,13 +647,6 @@ public class DecryptActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
mSignatureLayout.setVisibility(View.VISIBLE);
|
mSignatureLayout.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mReturnResult) {
|
|
||||||
Intent intent = new Intent();
|
|
||||||
intent.putExtras(data);
|
|
||||||
setResult(RESULT_OK, intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.thialfihar.android.apg.provider;
|
package org.thialfihar.android.apg.provider;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.thialfihar.android.apg.Id;
|
import org.thialfihar.android.apg.Id;
|
||||||
@ -27,6 +29,7 @@ import android.database.Cursor;
|
|||||||
import android.database.DatabaseUtils;
|
import android.database.DatabaseUtils;
|
||||||
import android.database.sqlite.SQLiteQueryBuilder;
|
import android.database.sqlite.SQLiteQueryBuilder;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
public class DataProvider extends ContentProvider {
|
public class DataProvider extends ContentProvider {
|
||||||
@ -50,6 +53,8 @@ public class DataProvider extends ContentProvider {
|
|||||||
private static final int SECRET_KEY_RING_USER_ID = 221;
|
private static final int SECRET_KEY_RING_USER_ID = 221;
|
||||||
private static final int SECRET_KEY_RING_USER_ID_RANK = 222;
|
private static final int SECRET_KEY_RING_USER_ID_RANK = 222;
|
||||||
|
|
||||||
|
private static final int DATA_STREAM = 301;
|
||||||
|
|
||||||
private static final String PUBLIC_KEY_RING_CONTENT_DIR_TYPE =
|
private static final String PUBLIC_KEY_RING_CONTENT_DIR_TYPE =
|
||||||
"vnd.android.cursor.dir/vnd.thialfihar.apg.public.key_ring";
|
"vnd.android.cursor.dir/vnd.thialfihar.apg.public.key_ring";
|
||||||
private static final String PUBLIC_KEY_RING_CONTENT_ITEM_TYPE =
|
private static final String PUBLIC_KEY_RING_CONTENT_ITEM_TYPE =
|
||||||
@ -109,6 +114,8 @@ public class DataProvider extends ContentProvider {
|
|||||||
|
|
||||||
mUriMatcher.addURI(AUTHORITY, "key_rings/secret", SECRET_KEY_RING);
|
mUriMatcher.addURI(AUTHORITY, "key_rings/secret", SECRET_KEY_RING);
|
||||||
mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*", SECRET_KEY_RING_ID);
|
mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*", SECRET_KEY_RING_ID);
|
||||||
|
|
||||||
|
mUriMatcher.addURI(AUTHORITY, "data/*", DATA_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -360,4 +367,15 @@ public class DataProvider extends ContentProvider {
|
|||||||
// not supported
|
// not supported
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
||||||
|
int match = mUriMatcher.match(uri);
|
||||||
|
if (match != DATA_STREAM) {
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
String fileName = uri.getPathSegments().get(1);
|
||||||
|
File file = new File(getContext().getFilesDir().getAbsolutePath(), fileName);
|
||||||
|
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user