Use temporary files for encryption/decryption

pull/164/head
M66B 5 years ago
parent 3f4d192512
commit f3fa2d0038

@ -112,9 +112,8 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
@ -1557,130 +1556,144 @@ public class FragmentCompose extends FragmentBase {
MimeMessage imessage = new MimeMessage(isession); MimeMessage imessage = new MimeMessage(isession);
MessageHelper.build(context, message, attachments, identity, imessage); MessageHelper.build(context, message, attachments, identity, imessage);
// Create temporary files
File plain = File.createTempFile("plain", "." + id, context.getCacheDir());
File encrypted = File.createTempFile("encrypted", "." + id, context.getCacheDir());
// Serialize message // Serialize message
ByteArrayOutputStream os = new ByteArrayOutputStream(); try (OutputStream out = new FileOutputStream(plain)) {
imessage.writeTo(os); imessage.writeTo(out);
ByteArrayInputStream decrypted = new ByteArrayInputStream(os.toByteArray()); }
ByteArrayOutputStream encrypted = null;
if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction()) || // Call OpenPGP
OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(data.getAction())) Intent result;
encrypted = new ByteArrayOutputStream(); try (InputStream in = new FileInputStream(plain)) {
try (OutputStream out = new FileOutputStream(encrypted)) {
// Encrypt message Log.i("Executing " + data.getAction());
Log.i("Executing " + data.getAction()); OpenPgpApi api = new OpenPgpApi(context, pgpService.getService());
OpenPgpApi api = new OpenPgpApi(context, pgpService.getService()); result = api.executeApi(data, in, out);
Intent result = api.executeApi(data, decrypted, encrypted); }
}
int resultCode = result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
Log.i("Result action=" + data.getAction() + " code=" + resultCode); plain.delete();
switch (resultCode) {
case OpenPgpApi.RESULT_CODE_SUCCESS: // Process result
// Attach encrypted data / signature try {
if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction()) || int resultCode = result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(data.getAction()) || Log.i("Result action=" + data.getAction() + " code=" + resultCode);
OpenPgpApi.ACTION_DETACHED_SIGN.equals(data.getAction())) switch (resultCode) {
try { case OpenPgpApi.RESULT_CODE_SUCCESS:
db.beginTransaction(); // Attach encrypted data / signature
if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction()) ||
String name; OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(data.getAction()) ||
int encryption; OpenPgpApi.ACTION_DETACHED_SIGN.equals(data.getAction()))
if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction())) { try {
name = "keydata.asc"; db.beginTransaction();
encryption = EntityAttachment.PGP_KEY;
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(data.getAction())) { String name;
name = "encrypted.asc"; int encryption;
encryption = EntityAttachment.PGP_MESSAGE; if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction())) {
} else if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(data.getAction())) { name = "keydata.asc";
name = "signature.asc"; encryption = EntityAttachment.PGP_KEY;
encryption = EntityAttachment.PGP_SIGNATURE; } else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(data.getAction())) {
} else name = "encrypted.asc";
throw new IllegalStateException(data.getAction()); encryption = EntityAttachment.PGP_MESSAGE;
} else if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(data.getAction())) {
EntityAttachment attachment = new EntityAttachment(); name = "signature.asc";
attachment.message = id; encryption = EntityAttachment.PGP_SIGNATURE;
attachment.sequence = db.attachment().getAttachmentSequence(id) + 1; } else
attachment.name = name; throw new IllegalStateException(data.getAction());
attachment.type = "application/octet-stream";
attachment.disposition = Part.INLINE; EntityAttachment attachment = new EntityAttachment();
attachment.encryption = encryption; attachment.message = id;
attachment.id = db.attachment().insertAttachment(attachment); attachment.sequence = db.attachment().getAttachmentSequence(id) + 1;
attachment.name = name;
byte[] bytes; attachment.type = "application/octet-stream";
if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(data.getAction())) attachment.disposition = Part.INLINE;
bytes = result.getByteArrayExtra(OpenPgpApi.RESULT_DETACHED_SIGNATURE); attachment.encryption = encryption;
else attachment.id = db.attachment().insertAttachment(attachment);
bytes = encrypted.toByteArray();
File file = attachment.getFile(context);
File file = attachment.getFile(context);
Log.i("Writing " + file + " size=" + bytes.length); if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(data.getAction())) {
try (OutputStream out = new FileOutputStream(file)) { byte[] bytes = result.getByteArrayExtra(OpenPgpApi.RESULT_DETACHED_SIGNATURE);
out.write(bytes); Log.i("Writing " + file + " size=" + bytes.length);
try (OutputStream out = new FileOutputStream(file)) {
out.write(bytes);
}
db.attachment().setDownloaded(attachment.id, (long) bytes.length);
} else {
Log.i("Writing " + file + " size=" + encrypted.length());
Helper.copy(encrypted, file);
db.attachment().setDownloaded(attachment.id, file.length());
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
} }
db.attachment().setDownloaded(attachment.id, (long) bytes.length);
db.setTransactionSuccessful(); if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(data.getAction())) {
} finally { pgpKeyIds = result.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS);
db.endTransaction(); Log.i("Keys=" + pgpKeyIds.length);
}
if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(data.getAction())) { // Send without encryption
pgpKeyIds = result.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); if (pgpKeyIds.length == 0)
Log.i("Keys=" + pgpKeyIds.length); return null;
// Send without encryption // Get encrypt key
if (pgpKeyIds.length == 0) Intent intent = new Intent(OpenPgpApi.ACTION_GET_KEY);
return null; intent.putExtra(OpenPgpApi.EXTRA_KEY_ID, pgpKeyIds[0]);
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
return intent;
} else if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction())) {
if (identity.sign_key != null) {
// Encrypt message
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, pgpKeyIds);
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, identity.sign_key);
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
return intent;
} else {
// Get sign key
return new Intent(OpenPgpApi.ACTION_GET_SIGN_KEY_ID);
}
} else if (OpenPgpApi.ACTION_GET_SIGN_KEY_ID.equals(data.getAction())) {
pgpSignKeyId = result.getLongExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, -1);
db.identity().setIdentitySignKey(identity.id, pgpSignKeyId);
// Get encrypt key
Intent intent = new Intent(OpenPgpApi.ACTION_GET_KEY);
intent.putExtra(OpenPgpApi.EXTRA_KEY_ID, pgpKeyIds[0]);
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
return intent;
} else if (OpenPgpApi.ACTION_GET_KEY.equals(data.getAction())) {
if (identity.sign_key != null) {
// Encrypt message // Encrypt message
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT); Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, pgpKeyIds); intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, pgpKeyIds);
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, identity.sign_key); intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, pgpSignKeyId);
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
return intent; return intent;
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(data.getAction())) {
// Get signature
Intent intent = new Intent(OpenPgpApi.ACTION_DETACHED_SIGN);
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, pgpSignKeyId);
return null;
} else { } else {
// Get sign key // send message
return new Intent(OpenPgpApi.ACTION_GET_SIGN_KEY_ID); return null;
} }
} else if (OpenPgpApi.ACTION_GET_SIGN_KEY_ID.equals(data.getAction())) {
pgpSignKeyId = result.getLongExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, -1);
db.identity().setIdentitySignKey(identity.id, pgpSignKeyId);
// Encrypt message
Intent intent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, pgpKeyIds);
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, pgpSignKeyId);
intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
return intent;
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(data.getAction())) {
// Get signature
Intent intent = new Intent(OpenPgpApi.ACTION_DETACHED_SIGN);
intent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, pgpSignKeyId);
return null;
} else {
// send message
return null;
}
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
return (PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); return (PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
case OpenPgpApi.RESULT_CODE_ERROR: case OpenPgpApi.RESULT_CODE_ERROR:
db.identity().setIdentitySignKey(identity.id, null); db.identity().setIdentitySignKey(identity.id, null);
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
throw new IllegalArgumentException( throw new IllegalArgumentException(
"OpenPgp" + "OpenPgp" +
" error " + (error == null ? "?" : error.getErrorId()) + " error " + (error == null ? "?" : error.getErrorId()) +
": " + (error == null ? "?" : error.getMessage())); ": " + (error == null ? "?" : error.getMessage()));
default: default:
throw new IllegalArgumentException("Unknown result code=" + resultCode); throw new IllegalArgumentException("Unknown result code=" + resultCode);
}
} finally {
encrypted.delete();
} }
} }

@ -115,7 +115,6 @@ import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection; import org.openintents.openpgp.util.OpenPgpServiceConnection;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -3841,23 +3840,23 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
Intent data = args.getParcelable("data"); Intent data = args.getParcelable("data");
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
List<EntityAttachment> attachments = db.attachment().getAttachments(id);
InputStream in = null;
boolean inline = false; boolean inline = false;
InputStream encrypted = null;
// Find encrypted data // Find encrypted data
List<EntityAttachment> attachments = db.attachment().getAttachments(id);
for (EntityAttachment attachment : attachments) for (EntityAttachment attachment : attachments)
if (EntityAttachment.PGP_MESSAGE.equals(attachment.encryption)) { if (EntityAttachment.PGP_MESSAGE.equals(attachment.encryption)) {
if (!attachment.available) if (!attachment.available)
throw new IllegalArgumentException(context.getString(R.string.title_attachments_missing)); throw new IllegalArgumentException(context.getString(R.string.title_attachments_missing));
File file = attachment.getFile(context); File file = attachment.getFile(context);
encrypted = new FileInputStream(file); in = new FileInputStream(file);
break; break;
} }
if (encrypted == null) { if (in == null) {
EntityMessage message = db.message().getMessage(id); EntityMessage message = db.message().getMessage(id);
if (message != null && message.content) { if (message != null && message.content) {
File file = message.getFile(context); File file = message.getFile(context);
@ -3876,106 +3875,117 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
section = TextUtils.join("\n\r", disarmored); section = TextUtils.join("\n\r", disarmored);
inline = true; inline = true;
encrypted = new ByteArrayInputStream(section.getBytes()); in = new ByteArrayInputStream(section.getBytes());
} }
} }
} }
} }
if (encrypted == null) if (in == null)
throw new IllegalArgumentException(context.getString(R.string.title_not_encrypted)); throw new IllegalArgumentException(context.getString(R.string.title_not_encrypted));
ByteArrayOutputStream decrypted = new ByteArrayOutputStream(); Intent result;
File plain = File.createTempFile("plain", "." + id, context.getCacheDir());
// Decrypt message try {
OpenPgpApi api = new OpenPgpApi(context, pgpService.getService()); // Decrypt message
Intent result = api.executeApi(data, encrypted, decrypted); try {
try (OutputStream out = new FileOutputStream(plain)) {
OpenPgpApi api = new OpenPgpApi(context, pgpService.getService());
result = api.executeApi(data, in, out);
}
} finally {
in.close();
}
Log.i("PGP result=" + result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)); Log.i("PGP result=" + result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR));
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS: case OpenPgpApi.RESULT_CODE_SUCCESS:
EntityMessage message = db.message().getMessage(id); EntityMessage message = db.message().getMessage(id);
if (message == null) if (message == null)
return null; return null;
if (inline) { if (inline) {
try { try {
db.beginTransaction(); db.beginTransaction();
// Write decrypted body // Write decrypted body
Helper.writeText(message.getFile(context), decrypted.toString()); Helper.copy(plain, message.getFile(context));
db.message().setMessageStored(id, new Date().getTime());
db.message().setMessageStored(id, new Date().getTime()); db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
db.setTransactionSuccessful(); } else {
} finally { // Decode message
db.endTransaction(); MessageHelper.MessageParts parts;
} Properties props = MessageHelper.getSessionProperties();
Session isession = Session.getInstance(props, null);
try (InputStream fis = new FileInputStream(plain)) {
MimeMessage imessage = new MimeMessage(isession, fis);
MessageHelper helper = new MessageHelper(imessage);
parts = helper.getMessageParts();
}
} else { try {
// Decode message db.beginTransaction();
Properties props = MessageHelper.getSessionProperties();
Session isession = Session.getInstance(props, null); // Write decrypted body
ByteArrayInputStream is = new ByteArrayInputStream(decrypted.toByteArray()); String html = parts.getHtml(context);
MimeMessage imessage = new MimeMessage(isession, is); Helper.writeText(message.getFile(context), html);
MessageHelper helper = new MessageHelper(imessage);
MessageHelper.MessageParts parts = helper.getMessageParts(); // Remove previously decrypted attachments
for (EntityAttachment local : attachments)
try { if (local.encryption == null)
db.beginTransaction(); db.attachment().deleteAttachment(local.id);
// Write decrypted body int sequence = db.attachment().getAttachmentSequence(id);
String html = parts.getHtml(context);
Helper.writeText(message.getFile(context), html); // Add decrypted attachments
List<EntityAttachment> remotes = parts.getAttachments();
// Remove previously decrypted attachments for (int index = 0; index < remotes.size(); index++) {
for (EntityAttachment local : attachments) EntityAttachment remote = remotes.get(index);
if (local.encryption == null) remote.message = id;
db.attachment().deleteAttachment(local.id); remote.sequence = ++sequence;
remote.id = db.attachment().insertAttachment(remote);
int sequence = db.attachment().getAttachmentSequence(id); try {
parts.downloadAttachment(context, index, remote);
// Add decrypted attachments } catch (Throwable ex) {
List<EntityAttachment> remotes = parts.getAttachments(); Log.e(ex);
for (int index = 0; index < remotes.size(); index++) { }
EntityAttachment remote = remotes.get(index);
remote.message = id;
remote.sequence = ++sequence;
remote.id = db.attachment().insertAttachment(remote);
try {
parts.downloadAttachment(context, index, remote);
} catch (Throwable ex) {
Log.e(ex);
} }
}
db.message().setMessageStored(id, new Date().getTime()); db.message().setMessageStored(id, new Date().getTime());
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
}
} }
}
// Check signature status // Check signature status
OpenPgpSignatureResult sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); OpenPgpSignatureResult sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
int sresult = (sigResult == null ? RESULT_NO_SIGNATURE : sigResult.getResult()); int sresult = (sigResult == null ? RESULT_NO_SIGNATURE : sigResult.getResult());
if (sresult == RESULT_NO_SIGNATURE) if (sresult == RESULT_NO_SIGNATURE)
Snackbar.make(view, R.string.title_signature_none, Snackbar.LENGTH_LONG).show(); Snackbar.make(view, R.string.title_signature_none, Snackbar.LENGTH_LONG).show();
else if (sresult == RESULT_VALID_KEY_CONFIRMED) else if (sresult == RESULT_VALID_KEY_CONFIRMED)
Snackbar.make(view, R.string.title_signature_valid, Snackbar.LENGTH_LONG).show(); Snackbar.make(view, R.string.title_signature_valid, Snackbar.LENGTH_LONG).show();
else else
db.message().setMessageError(id, getString(R.string.title_signature_invalid)); db.message().setMessageError(id, getString(R.string.title_signature_invalid));
break; break;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
FragmentMessages.this.message = id; FragmentMessages.this.message = id;
return result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); return result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
case OpenPgpApi.RESULT_CODE_ERROR: case OpenPgpApi.RESULT_CODE_ERROR:
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
throw new IllegalArgumentException(error.getMessage()); throw new IllegalArgumentException(error.getMessage());
}
} finally {
plain.delete();
} }
return null; return null;

Loading…
Cancel
Save