aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2015-10-15 22:50:34 +0200
committerDominik Schürmann <dominik@dominikschuermann.de>2015-10-15 22:50:34 +0200
commitcac7c3234a6ee1d25f46a9179645e01c1c0512c2 (patch)
treef6e8cdb715249084322740605e5758c312502f00
parentc03dee6fe2f60717f448178dcf49d370dce0bab0 (diff)
downloadopen-keychain-cac7c3234a6ee1d25f46a9179645e01c1c0512c2.tar.gz
open-keychain-cac7c3234a6ee1d25f46a9179645e01c1c0512c2.tar.bz2
open-keychain-cac7c3234a6ee1d25f46a9179645e01c1c0512c2.zip
Support backupVersion ASCII Armor header
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java91
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java9
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml1
8 files changed, 95 insertions, 25 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
index 17db500ce..1398e2d29 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
@@ -82,7 +82,6 @@ public final class Constants {
public static final class Path {
public static final File APP_DIR = new File(Environment.getExternalStorageDirectory(), "OpenKeychain");
- public static final File APP_DIR_FILE = new File(APP_DIR, "export.asc");
}
public static final class Notification {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java
index 5886f000c..1ec43b625 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java
@@ -142,6 +142,7 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
PgpSignEncryptInputParcel inputParcel = new PgpSignEncryptInputParcel();
inputParcel.setSymmetricPassphrase(exportInput.mSymmetricPassphrase);
inputParcel.setEnableAsciiArmorOutput(true);
+ inputParcel.setAddBackupHeader(true);
InputStream inStream = mContext.getContentResolver().openInputStream(exportOutputUri);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
index 24d1215d4..382d6c46d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
@@ -639,6 +639,7 @@ public abstract class OperationResult implements Parcelable {
MSG_DC_ASKIP_NOT_ALLOWED (LogLevel.DEBUG, R.string.msg_dc_askip_not_allowed),
MSG_DC_ASYM (LogLevel.DEBUG, R.string.msg_dc_asym),
MSG_DC_CHARSET (LogLevel.DEBUG, R.string.msg_dc_charset),
+ MSG_DC_BACKUP_VERSION (LogLevel.DEBUG, R.string.msg_dc_backup_version),
MSG_DC_CLEAR_DATA (LogLevel.DEBUG, R.string.msg_dc_clear_data),
MSG_DC_CLEAR_DECOMPRESS (LogLevel.DEBUG, R.string.msg_dc_clear_decompress),
MSG_DC_CLEAR_META_FILE (LogLevel.DEBUG, R.string.msg_dc_clear_meta_file),
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java
index 4a08ab9c1..7fe89b6f2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java
@@ -31,6 +31,7 @@ import java.util.Iterator;
import android.content.Context;
import android.support.annotation.NonNull;
+import android.text.TextUtils;
import android.webkit.MimeTypeMap;
import org.openintents.openpgp.OpenPgpDecryptionResult;
@@ -201,6 +202,57 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
}
+ private static class ArmorHeaders {
+ String charset = null;
+ Integer backupVersion = null;
+ }
+
+ private ArmorHeaders parseArmorHeaders(InputStream in, OperationLog log, int indent) {
+ ArmorHeaders armorHeaders = new ArmorHeaders();
+
+ // If the input stream is armored, and there is a charset specified, take a note for later
+ // https://tools.ietf.org/html/rfc4880#page56
+ if (in instanceof ArmoredInputStream) {
+ ArmoredInputStream aIn = (ArmoredInputStream) in;
+ if (aIn.getArmorHeaders() != null) {
+ for (String header : aIn.getArmorHeaders()) {
+ String[] pieces = header.split(":", 2);
+ if (pieces.length != 2
+ || TextUtils.isEmpty(pieces[0])
+ || TextUtils.isEmpty(pieces[1])) {
+ continue;
+ }
+
+ switch (pieces[0].toLowerCase()) {
+ case "charset": {
+ armorHeaders.charset = pieces[1].trim();
+ break;
+ }
+ case "backupversion": {
+ try {
+ armorHeaders.backupVersion = Integer.valueOf(pieces[1].trim());
+ } catch (NumberFormatException e) {
+ continue;
+ }
+ break;
+ }
+ default: {
+ // continue;
+ }
+ }
+ }
+ if (armorHeaders.charset != null) {
+ log.add(LogType.MSG_DC_CHARSET, indent, armorHeaders.charset);
+ }
+ if (armorHeaders.backupVersion != null) {
+ log.add(LogType.MSG_DC_BACKUP_VERSION, indent, armorHeaders.backupVersion);
+ }
+ }
+ }
+
+ return armorHeaders;
+ }
+
/** Decrypt and/or verify binary or ascii armored pgp data. */
@NonNull
private DecryptVerifyResult decryptVerify(
@@ -215,23 +267,12 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
int currentProgress = 0;
updateProgress(R.string.progress_reading_data, currentProgress, 100);
- // If the input stream is armored, and there is a charset specified, take a note for later
- // https://tools.ietf.org/html/rfc4880#page56
- String charset = null;
- if (in instanceof ArmoredInputStream) {
- ArmoredInputStream aIn = (ArmoredInputStream) in;
- if (aIn.getArmorHeaders() != null) {
- for (String header : aIn.getArmorHeaders()) {
- String[] pieces = header.split(":", 2);
- if (pieces.length == 2 && "charset".equalsIgnoreCase(pieces[0])) {
- charset = pieces[1].trim();
- break;
- }
- }
- if (charset != null) {
- log.add(LogType.MSG_DC_CHARSET, indent, charset);
- }
- }
+ // parse ASCII Armor headers
+ ArmorHeaders armorHeaders = parseArmorHeaders(in, log, indent);
+ String charset = armorHeaders.charset;
+ boolean useBackupCode = false;
+ if (armorHeaders.backupVersion != null && armorHeaders.backupVersion == 1) {
+ useBackupCode = true;
}
OpenPgpDecryptionResultBuilder decryptionResultBuilder = new OpenPgpDecryptionResultBuilder();
@@ -245,7 +286,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
if (obj instanceof PGPEncryptedDataList) {
esResult = handleEncryptedPacket(
- input, cryptoInput, (PGPEncryptedDataList) obj, log, indent, currentProgress);
+ input, cryptoInput, (PGPEncryptedDataList) obj, log, indent,
+ currentProgress, useBackupCode);
// if there is an error, nothing left to do here
if (esResult.errorResult != null) {
@@ -477,7 +519,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
}
private EncryptStreamResult handleEncryptedPacket(PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
- PGPEncryptedDataList enc, OperationLog log, int indent, int currentProgress) throws PGPException {
+ PGPEncryptedDataList enc, OperationLog log, int indent, int currentProgress, boolean useBackupCode) throws PGPException {
EncryptStreamResult result = new EncryptStreamResult();
@@ -609,8 +651,11 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
if (passphrase == null) {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
+ RequiredInputParcel requiredInputParcel = useBackupCode ?
+ RequiredInputParcel.createRequiredBackupCode() :
+ RequiredInputParcel.createRequiredSymmetricPassphrase();
return result.with(new DecryptVerifyResult(log,
- RequiredInputParcel.createRequiredSymmetricPassphrase(),
+ requiredInputParcel,
cryptoInput));
}
@@ -653,8 +698,10 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
result.cleartextStream = encryptedDataSymmetric.getDataStream(decryptorFactory);
} catch (PGPDataValidationException e) {
log.add(LogType.MSG_DC_ERROR_SYM_PASSPHRASE, indent + 1);
- return result.with(new DecryptVerifyResult(log,
- RequiredInputParcel.createRequiredSymmetricPassphrase(), cryptoInput));
+ RequiredInputParcel requiredInputParcel = useBackupCode ?
+ RequiredInputParcel.createRequiredBackupCode() :
+ RequiredInputParcel.createRequiredSymmetricPassphrase();
+ return result.with(new DecryptVerifyResult(log, requiredInputParcel, cryptoInput));
}
result.encryptedData = encryptedDataSymmetric;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
index 36d1a07cb..c2c6234eb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
@@ -44,6 +44,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
protected boolean mDetachedSignature = false;
protected boolean mHiddenRecipients = false;
protected boolean mIntegrityProtected = true;
+ protected boolean mAddBackupHeader = false;
public PgpSignEncryptInputParcel() {
@@ -70,6 +71,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
mDetachedSignature = source.readInt() == 1;
mHiddenRecipients = source.readInt() == 1;
mIntegrityProtected = source.readInt() == 1;
+ mAddBackupHeader = source.readInt() == 1;
}
@Override
@@ -100,6 +102,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
dest.writeInt(mDetachedSignature ? 1 : 0);
dest.writeInt(mHiddenRecipients ? 1 : 0);
dest.writeInt(mIntegrityProtected ? 1 : 0);
+ dest.writeInt(mAddBackupHeader ? 1 : 0);
}
public String getCharset() {
@@ -244,6 +247,15 @@ public class PgpSignEncryptInputParcel implements Parcelable {
return this;
}
+ public PgpSignEncryptInputParcel setAddBackupHeader(boolean addBackupHeader) {
+ this.mAddBackupHeader = addBackupHeader;
+ return this;
+ }
+
+ public boolean isAddBackupHeader() {
+ return mAddBackupHeader;
+ }
+
public boolean isHiddenRecipients() {
return mHiddenRecipients;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
index ecc190d97..25445a6c4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -149,6 +149,10 @@ public class PgpSignEncryptOperation extends BaseOperation {
if (input.getCharset() != null) {
armorOut.setHeader("Charset", input.getCharset());
}
+ // add proprietary header to indicate that this is a key backup
+ if (input.isAddBackupHeader()) {
+ armorOut.setHeader("BackupVersion", "1");
+ }
out = armorOut;
} else {
out = outputStream;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java
index e4dac3227..2c430bc29 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java
@@ -14,8 +14,8 @@ import java.util.Date;
public class RequiredInputParcel implements Parcelable {
public enum RequiredInputType {
- PASSPHRASE, PASSPHRASE_SYMMETRIC, NFC_SIGN, NFC_DECRYPT, NFC_MOVE_KEY_TO_CARD, ENABLE_ORBOT,
- UPLOAD_FAIL_RETRY
+ PASSPHRASE, PASSPHRASE_SYMMETRIC, BACKUP_CODE, NFC_SIGN, NFC_DECRYPT,
+ NFC_MOVE_KEY_TO_CARD, ENABLE_ORBOT, UPLOAD_FAIL_RETRY
}
public Date mSignatureTime;
@@ -117,6 +117,11 @@ public class RequiredInputParcel implements Parcelable {
null, null, null, null, null);
}
+ public static RequiredInputParcel createRequiredBackupCode() {
+ return new RequiredInputParcel(RequiredInputType.BACKUP_CODE,
+ null, null, null, null, null);
+ }
+
public static RequiredInputParcel createRequiredPassphrase(
RequiredInputParcel req) {
return new RequiredInputParcel(RequiredInputType.PASSPHRASE,
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 55f64c25e..be8eb1706 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -1152,6 +1152,7 @@
<string name="msg_dc_askip_not_allowed">"Data not encrypted with allowed key, skipping…"</string>
<string name="msg_dc_asym">"Found block of asymmetrically encrypted data for key %s"</string>
<string name="msg_dc_charset">"Found charset header: '%s'"</string>
+ <string name="msg_dc_backup_version">"Found backupVersion header: '%s'"</string>
<string name="msg_dc_clear_data">"Processing literal data"</string>
<string name="msg_dc_clear_decompress">"Unpacking compressed data"</string>
<string name="msg_dc_clear_meta_file">"Filename: %s"</string>