diff options
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.java | 137 |
1 files changed, 56 insertions, 81 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 b0e546662..901611982 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -27,9 +27,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; @@ -50,6 +50,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! @@ -68,12 +69,14 @@ 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 String mOriginalFilename; + private byte[] mNfcSignedHash = null; + private Date mNfcCreationTimestamp = null; + private static byte[] NEW_LINE; static { @@ -99,10 +102,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; this.mOriginalFilename = builder.mOriginalFilename; } @@ -122,11 +126,12 @@ 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 String mOriginalFilename = ""; + private byte[] mNfcSignedHash = null; + private Date mNfcCreationTimestamp = null; public Builder(ProviderHelper providerHelper, InputData data, OutputStream outStream) { mProviderHelper = providerHelper; @@ -179,11 +184,6 @@ public class PgpSignEncrypt { return this; } - public Builder setSignatureForceV3(boolean signatureForceV3) { - mSignatureForceV3 = signatureForceV3; - return this; - } - public Builder setSignaturePassphrase(String signaturePassphrase) { mSignaturePassphrase = signaturePassphrase; return this; @@ -216,6 +216,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); } @@ -243,17 +249,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) @@ -305,10 +326,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, 2, 100); @@ -349,19 +379,13 @@ public class PgpSignEncrypt { /* Initialize signature generator object for later usage */ PGPSignatureGenerator signatureGenerator = null; - PGPV3SignatureGenerator signatureV3Generator = null; if (enableSignature) { updateProgress(R.string.progress_preparing_signature, 4, 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(); @@ -371,9 +395,10 @@ public class PgpSignEncrypt { ProgressScaler progressScaler = new ProgressScaler(mProgressable, 8, 95, 100); PGPCompressedDataGenerator compressGen = null; - OutputStream pOut; + OutputStream pOut = null; OutputStream encryptionOut = null; BCPGOutputStream bcpgOut; + if (enableEncryption) { /* actual encryption */ updateProgress(R.string.progress_encrypting, 8, 100); @@ -388,11 +413,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(); @@ -408,11 +429,7 @@ public class PgpSignEncrypt { // update signature buffer if signature is requested if (enableSignature) { - if (mSignatureForceV3) { - signatureV3Generator.update(buffer, 0, length); - } else { - signatureGenerator.update(buffer, 0, length); - } + signatureGenerator.update(buffer, 0, length); } alreadyWritten += length; @@ -435,11 +452,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); // TODO: progress: fake annealing? while (true) { @@ -454,13 +467,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(); @@ -480,11 +488,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(); pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, mOriginalFilename, new Date(), @@ -496,11 +500,7 @@ public class PgpSignEncrypt { while ((length = in.read(buffer)) > 0) { pOut.write(buffer, 0, length); - if (mSignatureForceV3) { - signatureV3Generator.update(buffer, 0, length); - } else { - signatureGenerator.update(buffer, 0, length); - } + signatureGenerator.update(buffer, 0, length); alreadyWritten += length; if (mData.getSize() > 0) { @@ -517,10 +517,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); } } @@ -570,30 +571,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); - } - } |