aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java162
1 files changed, 69 insertions, 93 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
index f0403e625..09c28e7c5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
@@ -26,9 +26,9 @@ import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPLiteralData;
import org.spongycastle.openpgp.PGPLiteralDataGenerator;
import org.spongycastle.openpgp.PGPSignatureGenerator;
-import org.spongycastle.openpgp.PGPV3SignatureGenerator;
import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator;
import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
+import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
@@ -48,6 +48,7 @@ import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.util.Arrays;
import java.util.Date;
+import java.util.LinkedList;
/**
* This class uses a Builder pattern!
@@ -66,11 +67,13 @@ public class PgpSignEncrypt {
private int mSymmetricEncryptionAlgorithm;
private long mSignatureMasterKeyId;
private int mSignatureHashAlgorithm;
- private boolean mSignatureForceV3;
private String mSignaturePassphrase;
private boolean mEncryptToSigner;
private boolean mCleartextInput;
+ private byte[] mNfcSignedHash = null;
+ private Date mNfcCreationTimestamp = null;
+
private static byte[] NEW_LINE;
static {
@@ -96,10 +99,11 @@ public class PgpSignEncrypt {
this.mSymmetricEncryptionAlgorithm = builder.mSymmetricEncryptionAlgorithm;
this.mSignatureMasterKeyId = builder.mSignatureMasterKeyId;
this.mSignatureHashAlgorithm = builder.mSignatureHashAlgorithm;
- this.mSignatureForceV3 = builder.mSignatureForceV3;
this.mSignaturePassphrase = builder.mSignaturePassphrase;
this.mEncryptToSigner = builder.mEncryptToSigner;
this.mCleartextInput = builder.mCleartextInput;
+ this.mNfcSignedHash = builder.mNfcSignedHash;
+ this.mNfcCreationTimestamp = builder.mNfcCreationTimestamp;
}
public static class Builder {
@@ -118,11 +122,13 @@ public class PgpSignEncrypt {
private int mSymmetricEncryptionAlgorithm = 0;
private long mSignatureMasterKeyId = Constants.key.none;
private int mSignatureHashAlgorithm = 0;
- private boolean mSignatureForceV3 = false;
private String mSignaturePassphrase = null;
private boolean mEncryptToSigner = false;
private boolean mCleartextInput = false;
+ private byte[] mNfcSignedHash = null;
+ private Date mNfcCreationTimestamp = null;
+
public Builder(ProviderHelper providerHelper, String versionHeader, InputData data, OutputStream outStream) {
this.mProviderHelper = providerHelper;
this.mVersionHeader = versionHeader;
@@ -130,7 +136,7 @@ public class PgpSignEncrypt {
this.mOutStream = outStream;
}
- public Builder setProgressable(Progressable progressable) {
+ public Builder setProgressable(Progressable progressable) {
mProgressable = progressable;
return this;
}
@@ -170,11 +176,6 @@ public class PgpSignEncrypt {
return this;
}
- public Builder setSignatureForceV3(boolean signatureForceV3) {
- mSignatureForceV3 = signatureForceV3;
- return this;
- }
-
public Builder setSignaturePassphrase(String signaturePassphrase) {
mSignaturePassphrase = signaturePassphrase;
return this;
@@ -200,6 +201,12 @@ public class PgpSignEncrypt {
return this;
}
+ public Builder setNfcState(byte[] signedHash, Date creationTimestamp) {
+ mNfcSignedHash = signedHash;
+ mNfcCreationTimestamp = creationTimestamp;
+ return this;
+ }
+
public PgpSignEncrypt build() {
return new PgpSignEncrypt(this);
}
@@ -227,17 +234,32 @@ public class PgpSignEncrypt {
}
}
+ public static class WrongPassphraseException extends Exception {
+ public WrongPassphraseException() {
+ }
+ }
+
public static class NoSigningKeyException extends Exception {
public NoSigningKeyException() {
}
}
+ public static class NeedNfcDataException extends Exception {
+ public byte[] mHashToSign;
+ public Date mCreationTimestamp;
+
+ public NeedNfcDataException(byte[] hashToSign, Date creationTimestamp) {
+ mHashToSign = hashToSign;
+ mCreationTimestamp = creationTimestamp;
+ }
+ }
+
/**
* Signs and/or encrypts data based on parameters of class
*/
public void execute()
throws IOException, PGPException, NoSuchProviderException,
- NoSuchAlgorithmException, SignatureException, KeyExtractionException, NoSigningKeyException, NoPassphraseException {
+ NoSuchAlgorithmException, SignatureException, KeyExtractionException, NoSigningKeyException, NoPassphraseException, NeedNfcDataException, WrongPassphraseException {
boolean enableSignature = mSignatureMasterKeyId != Constants.key.none;
boolean enableEncryption = ((mEncryptionMasterKeyIds != null && mEncryptionMasterKeyIds.length > 0)
@@ -255,16 +277,6 @@ public class PgpSignEncrypt {
mEncryptionMasterKeyIds[mEncryptionMasterKeyIds.length - 1] = mSignatureMasterKeyId;
}
- ArmoredOutputStream armorOut = null;
- OutputStream out;
- if (mEnableAsciiArmorOutput) {
- armorOut = new ArmoredOutputStream(mOutStream);
- armorOut.setHeader("Version", mVersionHeader);
- out = armorOut;
- } else {
- out = mOutStream;
- }
-
/* Get keys for signature generation for later usage */
CanonicalizedSecretKey signingKey = null;
if (enableSignature) {
@@ -276,7 +288,7 @@ public class PgpSignEncrypt {
}
try {
signingKey = signingKeyRing.getSigningSubKey();
- } catch(PgpGeneralException e) {
+ } catch (PgpGeneralException e) {
throw new NoSigningKeyException();
}
@@ -287,10 +299,19 @@ public class PgpSignEncrypt {
updateProgress(R.string.progress_extracting_signature_key, 0, 100);
try {
- signingKey.unlock(mSignaturePassphrase);
+ if (!signingKey.unlock(mSignaturePassphrase)) {
+ throw new WrongPassphraseException();
+ }
} catch (PgpGeneralException e) {
throw new KeyExtractionException();
}
+
+ // check if hash algo is supported
+ LinkedList<Integer> supported = signingKey.getSupportedHashAlgorithms();
+ if (!supported.contains(mSignatureHashAlgorithm)) {
+ // get most preferred
+ mSignatureHashAlgorithm = supported.getLast();
+ }
}
updateProgress(R.string.progress_preparing_streams, 5, 100);
@@ -331,29 +352,34 @@ public class PgpSignEncrypt {
/* Initialize signature generator object for later usage */
PGPSignatureGenerator signatureGenerator = null;
- PGPV3SignatureGenerator signatureV3Generator = null;
if (enableSignature) {
updateProgress(R.string.progress_preparing_signature, 10, 100);
try {
boolean cleartext = mCleartextInput && mEnableAsciiArmorOutput && !enableEncryption;
- if (mSignatureForceV3) {
- signatureV3Generator = signingKey.getV3SignatureGenerator(
- mSignatureHashAlgorithm,cleartext);
- } else {
- signatureGenerator = signingKey.getSignatureGenerator(
- mSignatureHashAlgorithm, cleartext);
- }
+ signatureGenerator = signingKey.getSignatureGenerator(
+ mSignatureHashAlgorithm, cleartext, mNfcSignedHash, mNfcCreationTimestamp);
} catch (PgpGeneralException e) {
// TODO throw correct type of exception (which shouldn't be PGPException)
throw new KeyExtractionException();
}
}
+ ArmoredOutputStream armorOut = null;
+ OutputStream out;
+ if (mEnableAsciiArmorOutput) {
+ armorOut = new ArmoredOutputStream(mOutStream);
+ armorOut.setHeader("Version", mVersionHeader);
+ out = armorOut;
+ } else {
+ out = mOutStream;
+ }
+
PGPCompressedDataGenerator compressGen = null;
- OutputStream pOut;
+ OutputStream pOut = null;
OutputStream encryptionOut = null;
BCPGOutputStream bcpgOut;
+
if (enableEncryption) {
/* actual encryption */
@@ -367,11 +393,7 @@ public class PgpSignEncrypt {
}
if (enableSignature) {
- if (mSignatureForceV3) {
- signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
- } else {
- signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
- }
+ signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
}
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
@@ -389,11 +411,7 @@ public class PgpSignEncrypt {
// update signature buffer if signature is requested
if (enableSignature) {
- if (mSignatureForceV3) {
- signatureV3Generator.update(buffer, 0, n);
- } else {
- signatureGenerator.update(buffer, 0, n);
- }
+ signatureGenerator.update(buffer, 0, n);
}
progress += n;
@@ -415,11 +433,7 @@ public class PgpSignEncrypt {
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
// update signature buffer with first line
- if (mSignatureForceV3) {
- processLineV3(reader.readLine(), armorOut, signatureV3Generator);
- } else {
- processLine(reader.readLine(), armorOut, signatureGenerator);
- }
+ processLine(reader.readLine(), armorOut, signatureGenerator);
while (true) {
String line = reader.readLine();
@@ -433,13 +447,8 @@ public class PgpSignEncrypt {
armorOut.write(NEW_LINE);
// update signature buffer with input line
- if (mSignatureForceV3) {
- signatureV3Generator.update(NEW_LINE);
- processLineV3(line, armorOut, signatureV3Generator);
- } else {
- signatureGenerator.update(NEW_LINE);
- processLine(line, armorOut, signatureGenerator);
- }
+ signatureGenerator.update(NEW_LINE);
+ processLine(line, armorOut, signatureGenerator);
}
armorOut.endClearText();
@@ -459,11 +468,7 @@ public class PgpSignEncrypt {
bcpgOut = new BCPGOutputStream(out);
}
- if (mSignatureForceV3) {
- signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
- } else {
- signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
- }
+ signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
// file name not needed, so empty string
@@ -475,11 +480,7 @@ public class PgpSignEncrypt {
while ((n = in.read(buffer)) > 0) {
pOut.write(buffer, 0, n);
- if (mSignatureForceV3) {
- signatureV3Generator.update(buffer, 0, n);
- } else {
- signatureGenerator.update(buffer, 0, n);
- }
+ signatureGenerator.update(buffer, 0, n);
}
literalGen.close();
@@ -490,10 +491,11 @@ public class PgpSignEncrypt {
if (enableSignature) {
updateProgress(R.string.progress_generating_signature, 95, 100);
- if (mSignatureForceV3) {
- signatureV3Generator.generate().encode(pOut);
- } else {
+ try {
signatureGenerator.generate().encode(pOut);
+ } catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) {
+ // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed
+ throw new NeedNfcDataException(e.hashToSign, e.creationTimestamp);
}
}
@@ -543,30 +545,4 @@ public class PgpSignEncrypt {
pSignatureGenerator.update(data);
}
- private static void processLineV3(final String pLine, final ArmoredOutputStream pArmoredOutput,
- final PGPV3SignatureGenerator pSignatureGenerator)
- throws IOException, SignatureException {
-
- if (pLine == null) {
- return;
- }
-
- final char[] chars = pLine.toCharArray();
- int len = chars.length;
-
- while (len > 0) {
- if (!Character.isWhitespace(chars[len - 1])) {
- break;
- }
- len--;
- }
-
- final byte[] data = pLine.substring(0, len).getBytes("UTF-8");
-
- if (pArmoredOutput != null) {
- pArmoredOutput.write(data);
- }
- pSignatureGenerator.update(data);
- }
-
}