diff options
author | Thialfihar <thialfihar@gmail.com> | 2010-07-09 11:28:39 +0000 |
---|---|---|
committer | Thialfihar <thialfihar@gmail.com> | 2010-07-09 11:28:39 +0000 |
commit | 3ac472125a7ad3b7b600c32129a50def3b8a1b8a (patch) | |
tree | 94c4bab7ce686dd048e132eea57cff2c950ee03a | |
parent | f03b34905724f6f1fbdad03c974d29b730a7d827 (diff) | |
download | open-keychain-3ac472125a7ad3b7b600c32129a50def3b8a1b8a.tar.gz open-keychain-3ac472125a7ad3b7b600c32129a50def3b8a1b8a.tar.bz2 open-keychain-3ac472125a7ad3b7b600c32129a50def3b8a1b8a.zip |
some playing with content stream decryption and providing the result as content stream
-rw-r--r-- | src/org/thialfihar/android/apg/Apg.java | 43 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/DecryptActivity.java | 90 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/provider/DataProvider.java | 18 |
3 files changed, 116 insertions, 35 deletions
diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java index b2ae19368..d606a553c 100644 --- a/src/org/thialfihar/android/apg/Apg.java +++ b/src/org/thialfihar/android/apg/Apg.java @@ -37,7 +37,6 @@ import java.util.Date; import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Pattern;
@@ -118,7 +117,8 @@ public class Apg { public static final String EXTRA_STATUS = "status";
public static final String EXTRA_ERROR = "error";
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_KEY_ID = "signatureKeyId";
public static final String EXTRA_SIGNATURE_USER_ID = "signatureUserId";
@@ -1851,4 +1851,43 @@ public class Apg { public static String getFullVersion(Context 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;
+ }
}
diff --git a/src/org/thialfihar/android/apg/DecryptActivity.java b/src/org/thialfihar/android/apg/DecryptActivity.java index 98480bbf7..571edbdf5 100644 --- a/src/org/thialfihar/android/apg/DecryptActivity.java +++ b/src/org/thialfihar/android/apg/DecryptActivity.java @@ -31,6 +31,7 @@ import java.util.regex.Matcher; import org.bouncycastle2.jce.provider.BouncyCastleProvider; import org.bouncycastle2.openpgp.PGPException; +import org.thialfihar.android.apg.provider.DataProvider; import android.app.Dialog; import android.content.ActivityNotFoundException; @@ -86,6 +87,8 @@ public class DecryptActivity extends BaseActivity { private String mInputFilename = null; private String mOutputFilename = null; + private Uri mContentUri = null; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -220,26 +223,29 @@ public class DecryptActivity extends BaseActivity { mSource.showNext(); } } else if (Apg.Intent.DECRYPT_AND_RETURN.equals(mIntent.getAction())) { - Bundle extras = mIntent.getExtras(); - if (extras == null) { - extras = new Bundle(); - } - String data = extras.getString(Apg.EXTRA_TEXT); - if (data != null) { - Matcher matcher = Apg.PGP_MESSAGE.matcher(data); - if (matcher.matches()) { - data = matcher.group(1); - // replace non breakable spaces - data = data.replaceAll("\\xa0", " "); - mMessage.setText(data); - } else { - matcher = Apg.PGP_SIGNED_MESSAGE.matcher(data); + mContentUri = mIntent.getData(); + if (mContentUri == null) { + Bundle extras = mIntent.getExtras(); + if (extras == null) { + extras = new Bundle(); + } + String data = extras.getString(Apg.EXTRA_TEXT); + if (data != null) { + Matcher matcher = Apg.PGP_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); + } 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; try { InputStream in; - if (mDecryptTarget == Id.target.file) { + if (mContentUri != null) { + in = getContentResolver().openInputStream(mContentUri); + } else if (mDecryptTarget == Id.target.file) { if (mInputFilename.startsWith("file")) { in = new FileInputStream(mInputFilename); } else { @@ -412,7 +420,9 @@ public class DecryptActivity extends BaseActivity { setSecretKeyId(Id.key.symmetric); // look at the file/message again to check whether there's // 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")) { in = new FileInputStream(mInputFilename); } else { @@ -494,22 +504,32 @@ public class DecryptActivity extends BaseActivity { try { PositionAwareInputStream in = null; OutputStream out = null; + String randomString = null; 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(); in = new PositionAwareInputStream(new ByteArrayInputStream(messageData.getBytes())); out = new ByteArrayOutputStream(); size = messageData.getBytes().length; } else { if (mInputFilename.startsWith("content")) { - InputStream tmp = getContentResolver().openInputStream(Uri.parse(mInputFilename)); - size = 0; - long n = 0; - byte dummy[] = new byte[0x10000]; - while ((n = tmp.read(dummy)) > 0) { - size += n; - } + size = Apg.getLengthOfStream(getContentResolver().openInputStream(Uri.parse(mInputFilename))); in = new PositionAwareInputStream( getContentResolver().openInputStream(Uri.parse(mInputFilename))); } else { @@ -528,7 +548,10 @@ public class DecryptActivity extends BaseActivity { } 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, new String(((ByteArrayOutputStream) out).toByteArray())); } @@ -570,6 +593,14 @@ public class DecryptActivity extends BaseActivity { } 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) { case Id.target.message: { String decryptedMessage = data.getString(Apg.EXTRA_DECRYPTED_MESSAGE); @@ -616,13 +647,6 @@ public class DecryptActivity extends BaseActivity { } mSignatureLayout.setVisibility(View.VISIBLE); } - - if (mReturnResult) { - Intent intent = new Intent(); - intent.putExtras(data); - setResult(RESULT_OK, intent); - finish(); - } } @Override diff --git a/src/org/thialfihar/android/apg/provider/DataProvider.java b/src/org/thialfihar/android/apg/provider/DataProvider.java index 0a4bfbad4..9cf083528 100644 --- a/src/org/thialfihar/android/apg/provider/DataProvider.java +++ b/src/org/thialfihar/android/apg/provider/DataProvider.java @@ -16,6 +16,8 @@ package org.thialfihar.android.apg.provider; +import java.io.File; +import java.io.FileNotFoundException; import java.util.HashMap; import org.thialfihar.android.apg.Id; @@ -27,6 +29,7 @@ import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; +import android.os.ParcelFileDescriptor; import android.text.TextUtils; 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_RANK = 222; + private static final int DATA_STREAM = 301; + private static final String PUBLIC_KEY_RING_CONTENT_DIR_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.public.key_ring"; 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_ID); + + mUriMatcher.addURI(AUTHORITY, "data/*", DATA_STREAM); } @Override @@ -360,4 +367,15 @@ public class DataProvider extends ContentProvider { // not supported 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); + } } |