merge internal signText and signAndEncrypt methods

This commit is contained in:
Dominik Schürmann
2014-02-18 22:47:26 +01:00
parent 708d0c9a5a
commit 9b4245739e
3 changed files with 201 additions and 239 deletions

View File

@@ -98,7 +98,7 @@ public class PgpOperation {
private OutputStream mOutStream; private OutputStream mOutStream;
public PgpOperation(Context context, ProgressDialogUpdater progress, InputData data, public PgpOperation(Context context, ProgressDialogUpdater progress, InputData data,
OutputStream outStream) { OutputStream outStream) {
super(); super();
this.mContext = context; this.mContext = context;
this.mProgress = progress; this.mProgress = progress;
@@ -118,9 +118,10 @@ public class PgpOperation {
} }
} }
public void signAndEncrypt(boolean useAsciiArmor, int compression, long[] encryptionKeyIds, public void signAndEncrypt(boolean enableAsciiArmor, int compressionId, long[] encryptionKeyIds,
String encryptionPassphrase, int symmetricEncryptionAlgorithm, long signatureKeyId, String encryptionPassphrase, int symmetricEncryptionAlgorithm,
int signatureHashAlgorithm, boolean signatureForceV3, String signaturePassphrase) long signatureKeyId, int signatureHashAlgorithm,
boolean signatureForceV3, String signaturePassphrase)
throws IOException, PgpGeneralException, PGPException, NoSuchProviderException, throws IOException, PgpGeneralException, PGPException, NoSuchProviderException,
NoSuchAlgorithmException, SignatureException { NoSuchAlgorithmException, SignatureException {
@@ -128,26 +129,34 @@ public class PgpOperation {
encryptionKeyIds = new long[0]; encryptionKeyIds = new long[0];
} }
boolean enableSignature = signatureKeyId != Id.key.none;
boolean enableCompression = compressionId == Id.choice.compression.none;
boolean enableEncryption = encryptionKeyIds.length != 0 || encryptionPassphrase != null;
int signatureType;
// TODO: disable when encrypting???
if (enableAsciiArmor && enableSignature && !enableEncryption) {
signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT;
} else {
signatureType = PGPSignature.BINARY_DOCUMENT;
}
ArmoredOutputStream armorOut = null; ArmoredOutputStream armorOut = null;
OutputStream out = null; OutputStream out;
OutputStream encryptOut = null; OutputStream encryptionOut = null;
if (useAsciiArmor) { if (enableAsciiArmor) {
armorOut = new ArmoredOutputStream(mOutStream); armorOut = new ArmoredOutputStream(mOutStream);
armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext)); armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
out = armorOut; out = armorOut;
} else { } else {
out = mOutStream; out = mOutStream;
} }
PGPSecretKey signingKey = null; PGPSecretKey signingKey = null;
PGPSecretKeyRing signingKeyRing = null; PGPSecretKeyRing signingKeyRing = null;
PGPPrivateKey signaturePrivateKey = null; PGPPrivateKey signaturePrivateKey = null;
if (enableSignature) {
if (encryptionKeyIds.length == 0 && encryptionPassphrase == null) {
throw new PgpGeneralException(
mContext.getString(R.string.error_no_encryption_keys_or_passphrase));
}
if (signatureKeyId != Id.key.none) {
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, signatureKeyId); signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, signatureKeyId);
signingKey = PgpKeyHelper.getSigningKey(mContext, signatureKeyId); signingKey = PgpKeyHelper.getSigningKey(mContext, signatureKeyId);
if (signingKey == null) { if (signingKey == null) {
@@ -172,50 +181,51 @@ public class PgpOperation {
updateProgress(R.string.progress_preparing_streams, 5, 100); updateProgress(R.string.progress_preparing_streams, 5, 100);
// encrypt and compress input file content // encrypt and compress input file content
JcePGPDataEncryptorBuilder encryptorBuilder = new JcePGPDataEncryptorBuilder( if (enableEncryption) {
symmetricEncryptionAlgorithm).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME) JcePGPDataEncryptorBuilder encryptorBuilder = new JcePGPDataEncryptorBuilder(
.setWithIntegrityPacket(true); symmetricEncryptionAlgorithm).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
.setWithIntegrityPacket(true);
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(encryptorBuilder); PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(encryptorBuilder);
if (encryptionKeyIds.length == 0) { if (encryptionKeyIds.length == 0) {
// Symmetric encryption // Symmetric encryption
Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption"); Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption");
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator = new JcePBEKeyEncryptionMethodGenerator( JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator = new JcePBEKeyEncryptionMethodGenerator(
encryptionPassphrase.toCharArray()); encryptionPassphrase.toCharArray());
cPk.addMethod(symmetricEncryptionGenerator); cPk.addMethod(symmetricEncryptionGenerator);
} else { } else {
// Asymmetric encryption // Asymmetric encryption
for (long id : encryptionKeyIds) { for (long id : encryptionKeyIds) {
PGPPublicKey key = PgpKeyHelper.getEncryptPublicKey(mContext, id); PGPPublicKey key = PgpKeyHelper.getEncryptPublicKey(mContext, id);
if (key != null) { if (key != null) {
JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator = new JcePublicKeyKeyEncryptionMethodGenerator( JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator = new JcePublicKeyKeyEncryptionMethodGenerator(
key); key);
cPk.addMethod(pubKeyEncryptionGenerator); cPk.addMethod(pubKeyEncryptionGenerator);
}
} }
} }
encryptionOut = cPk.open(out, new byte[1 << 16]);
} }
encryptOut = cPk.open(out, new byte[1 << 16]);
PGPSignatureGenerator signatureGenerator = null; PGPSignatureGenerator signatureGenerator = null;
PGPV3SignatureGenerator signatureV3Generator = null; PGPV3SignatureGenerator signatureV3Generator = null;
if (enableSignature) {
if (signatureKeyId != Id.key.none) {
updateProgress(R.string.progress_preparing_signature, 10, 100); updateProgress(R.string.progress_preparing_signature, 10, 100);
// content signer based on signing key algorithm and choosen hash algorithm // content signer based on signing key algorithm and chosen hash algorithm
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
signingKey.getPublicKey().getAlgorithm(), signatureHashAlgorithm) signingKey.getPublicKey().getAlgorithm(), signatureHashAlgorithm)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
if (signatureForceV3) { if (signatureForceV3) {
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder); signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
signatureV3Generator.init(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey); signatureV3Generator.init(signatureType, signaturePrivateKey);
} else { } else {
signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey); signatureGenerator.init(signatureType, signaturePrivateKey);
String userId = PgpKeyHelper.getMainUserId(PgpKeyHelper String userId = PgpKeyHelper.getMainUserId(PgpKeyHelper
.getMasterKey(signingKeyRing)); .getMasterKey(signingKeyRing));
@@ -226,49 +236,100 @@ public class PgpOperation {
} }
PGPCompressedDataGenerator compressGen = null; PGPCompressedDataGenerator compressGen = null;
BCPGOutputStream bcpgOut = null; OutputStream pOut;
if (compression == Id.choice.compression.none) { if (enableEncryption) {
bcpgOut = new BCPGOutputStream(encryptOut); BCPGOutputStream bcpgOut;
} else { if (enableCompression) {
compressGen = new PGPCompressedDataGenerator(compression); compressGen = new PGPCompressedDataGenerator(compressionId);
bcpgOut = new BCPGOutputStream(compressGen.open(encryptOut)); bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut));
}
if (signatureKeyId != Id.key.none) {
if (signatureForceV3) {
signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
} else { } else {
signatureGenerator.generateOnePassVersion(false).encode(bcpgOut); bcpgOut = new BCPGOutputStream(encryptionOut);
} }
}
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); if (enableSignature) {
// file name not needed, so empty string
OutputStream pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(),
new byte[1 << 16]);
updateProgress(R.string.progress_encrypting, 20, 100);
long done = 0;
int n = 0;
byte[] buffer = new byte[1 << 16];
InputStream in = mData.getInputStream();
while ((n = in.read(buffer)) > 0) {
pOut.write(buffer, 0, n);
if (signatureKeyId != Id.key.none) {
if (signatureForceV3) { if (signatureForceV3) {
signatureV3Generator.update(buffer, 0, n); signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
} else { } else {
signatureGenerator.update(buffer, 0, n); signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
} }
} }
done += n;
if (mData.getSize() != 0) { PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
updateProgress((int) (20 + (95 - 20) * done / mData.getSize()), 100); // file name not needed, so empty string
pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(),
new byte[1 << 16]);
updateProgress(R.string.progress_encrypting, 20, 100);
long progress = 0;
int n;
byte[] buffer = new byte[1 << 16];
InputStream in = mData.getInputStream();
while ((n = in.read(buffer)) > 0) {
pOut.write(buffer, 0, n);
// update signature buffer if signature is requested
if (enableSignature) {
if (signatureForceV3) {
signatureV3Generator.update(buffer, 0, n);
} else {
signatureGenerator.update(buffer, 0, n);
}
}
progress += n;
if (mData.getSize() != 0) {
updateProgress((int) (20 + (95 - 20) * progress / mData.getSize()), 100);
}
} }
literalGen.close();
} else if (enableAsciiArmor && enableSignature && !enableEncryption && !enableCompression) {
/* sign-only of ascii text */
updateProgress(R.string.progress_signing, 40, 100);
// write directly on armor output stream
armorOut.beginClearText(signatureHashAlgorithm);
InputStream in = mData.getInputStream();
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
final byte[] newline = "\r\n".getBytes("UTF-8");
if (signatureForceV3) {
processLine(reader.readLine(), armorOut, signatureV3Generator);
} else {
processLine(reader.readLine(), armorOut, signatureGenerator);
}
while (true) {
String line = reader.readLine();
if (line == null) {
armorOut.write(newline);
break;
}
armorOut.write(newline);
if (signatureForceV3) {
signatureV3Generator.update(newline);
processLine(line, armorOut, signatureV3Generator);
} else {
signatureGenerator.update(newline);
processLine(line, armorOut, signatureGenerator);
}
}
armorOut.endClearText();
pOut = new BCPGOutputStream(armorOut);
} else {
// TODO: implement sign-only for files!
pOut = null;
Log.e(Constants.TAG, "not supported!");
} }
literalGen.close(); if (enableSignature) {
if (signatureKeyId != Id.key.none) {
updateProgress(R.string.progress_generating_signature, 95, 100); updateProgress(R.string.progress_generating_signature, 95, 100);
if (signatureForceV3) { if (signatureForceV3) {
signatureV3Generator.generate().encode(pOut); signatureV3Generator.generate().encode(pOut);
@@ -276,11 +337,16 @@ public class PgpOperation {
signatureGenerator.generate().encode(pOut); signatureGenerator.generate().encode(pOut);
} }
} }
if (compressGen != null) {
compressGen.close(); // closing outputs...
if (enableEncryption) {
encryptionOut.close();
if (enableCompression) {
compressGen.close();
}
} }
encryptOut.close(); if (enableAsciiArmor) {
if (useAsciiArmor) {
armorOut.close(); armorOut.close();
} }
@@ -288,138 +354,38 @@ public class PgpOperation {
} }
public void signText(long signatureKeyId, String signaturePassphrase, public void signText(long signatureKeyId, String signaturePassphrase,
int signatureHashAlgorithm, boolean forceV3Signature) throws PgpGeneralException, int signatureHashAlgorithm, boolean forceV3Signature)
PGPException, IOException, NoSuchAlgorithmException, SignatureException {
ArmoredOutputStream armorOut = new ArmoredOutputStream(mOutStream);
armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
PGPSecretKey signingKey = null;
PGPSecretKeyRing signingKeyRing = null;
PGPPrivateKey signaturePrivateKey = null;
if (signatureKeyId == 0) {
armorOut.close();
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_key));
}
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, signatureKeyId);
signingKey = PgpKeyHelper.getSigningKey(mContext, signatureKeyId);
if (signingKey == null) {
armorOut.close();
throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
}
if (signaturePassphrase == null) {
armorOut.close();
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_passphrase));
}
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassphrase.toCharArray());
signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
if (signaturePrivateKey == null) {
armorOut.close();
throw new PgpGeneralException(
mContext.getString(R.string.error_could_not_extract_private_key));
}
updateProgress(R.string.progress_preparing_streams, 0, 100);
updateProgress(R.string.progress_preparing_signature, 30, 100);
PGPSignatureGenerator signatureGenerator = null;
PGPV3SignatureGenerator signatureV3Generator = null;
// content signer based on signing key algorithm and choosen hash algorithm
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
.getPublicKey().getAlgorithm(), signatureHashAlgorithm)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
if (forceV3Signature) {
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
signatureV3Generator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
} else {
signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
signatureGenerator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
String userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signingKeyRing));
spGen.setSignerUserID(false, userId);
signatureGenerator.setHashedSubpackets(spGen.generate());
}
updateProgress(R.string.progress_signing, 40, 100);
armorOut.beginClearText(signatureHashAlgorithm);
InputStream inStream = mData.getInputStream();
final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
final byte[] newline = "\r\n".getBytes("UTF-8");
if (forceV3Signature) {
processLine(reader.readLine(), armorOut, signatureV3Generator);
} else {
processLine(reader.readLine(), armorOut, signatureGenerator);
}
while (true) {
final String line = reader.readLine();
if (line == null) {
armorOut.write(newline);
break;
}
armorOut.write(newline);
if (forceV3Signature) {
signatureV3Generator.update(newline);
processLine(line, armorOut, signatureV3Generator);
} else {
signatureGenerator.update(newline);
processLine(line, armorOut, signatureGenerator);
}
}
armorOut.endClearText();
BCPGOutputStream bOut = new BCPGOutputStream(armorOut);
if (forceV3Signature) {
signatureV3Generator.generate().encode(bOut);
} else {
signatureGenerator.generate().encode(bOut);
}
armorOut.close();
updateProgress(R.string.progress_done, 100, 100);
}
public void generateSignature(boolean armored, boolean binary, long signatureKeyId,
String signaturePassPhrase, int hashAlgorithm, boolean forceV3Signature)
throws PgpGeneralException, PGPException, IOException, NoSuchAlgorithmException, throws PgpGeneralException, PGPException, IOException, NoSuchAlgorithmException,
SignatureException { SignatureException {
OutputStream out = null; try {
signAndEncrypt(true, 0, null, null, 0, signatureKeyId, signatureHashAlgorithm, forceV3Signature, signaturePassphrase);
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
}
// Ascii Armor (Base64) public void generateSignature(boolean armored, boolean binary, long signatureKeyId,
ArmoredOutputStream armorOut = null; String signaturePassPhrase, int hashAlgorithm, boolean forceV3Signature)
throws PgpGeneralException, PGPException, IOException, NoSuchAlgorithmException,
SignatureException {
OutputStream out;
if (armored) { if (armored) {
armorOut = new ArmoredOutputStream(mOutStream); // Ascii Armor (Radix-64)
ArmoredOutputStream armorOut = new ArmoredOutputStream(mOutStream);
armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext)); armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
out = armorOut; out = armorOut;
} else { } else {
out = mOutStream; out = mOutStream;
} }
PGPSecretKey signingKey = null;
PGPSecretKeyRing signingKeyRing = null;
PGPPrivateKey signaturePrivateKey = null;
if (signatureKeyId == 0) { if (signatureKeyId == 0) {
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_key)); throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_key));
} }
signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, signatureKeyId); PGPSecretKeyRing signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, signatureKeyId);
signingKey = PgpKeyHelper.getSigningKey(mContext, signatureKeyId); PGPSecretKey signingKey = PgpKeyHelper.getSigningKey(mContext, signatureKeyId);
if (signingKey == null) { if (signingKey == null) {
throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed)); throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
} }
@@ -430,7 +396,7 @@ public class PgpOperation {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray()); Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray());
signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
if (signaturePrivateKey == null) { if (signaturePrivateKey == null) {
throw new PgpGeneralException( throw new PgpGeneralException(
mContext.getString(R.string.error_could_not_extract_private_key)); mContext.getString(R.string.error_could_not_extract_private_key));
@@ -439,19 +405,18 @@ public class PgpOperation {
updateProgress(R.string.progress_preparing_signature, 30, 100); updateProgress(R.string.progress_preparing_signature, 30, 100);
PGPSignatureGenerator signatureGenerator = null;
PGPV3SignatureGenerator signatureV3Generator = null;
int type = PGPSignature.CANONICAL_TEXT_DOCUMENT; int type = PGPSignature.CANONICAL_TEXT_DOCUMENT;
if (binary) { if (binary) {
type = PGPSignature.BINARY_DOCUMENT; type = PGPSignature.BINARY_DOCUMENT;
} }
// content signer based on signing key algorithm and choosen hash algorithm // content signer based on signing key algorithm and chosen hash algorithm
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
.getPublicKey().getAlgorithm(), hashAlgorithm) .getPublicKey().getAlgorithm(), hashAlgorithm)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureGenerator signatureGenerator = null;
PGPV3SignatureGenerator signatureV3Generator = null;
if (forceV3Signature) { if (forceV3Signature) {
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder); signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
signatureV3Generator.init(type, signaturePrivateKey); signatureV3Generator.init(type, signaturePrivateKey);
@@ -482,13 +447,8 @@ public class PgpOperation {
final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream)); final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
final byte[] newline = "\r\n".getBytes("UTF-8"); final byte[] newline = "\r\n".getBytes("UTF-8");
while (true) { String line;
final String line = reader.readLine(); while ((line = reader.readLine()) != null) {
if (line == null) {
break;
}
if (forceV3Signature) { if (forceV3Signature) {
processLine(line, null, signatureV3Generator); processLine(line, null, signatureV3Generator);
signatureV3Generator.update(newline); signatureV3Generator.update(newline);
@@ -508,8 +468,7 @@ public class PgpOperation {
out.close(); out.close();
mOutStream.close(); mOutStream.close();
if (mProgress != null) updateProgress(R.string.progress_done, 100, 100);
mProgress.setProgress(R.string.progress_done, 100, 100);
} }
public static boolean hasSymmetricEncryption(Context context, InputStream inputStream) public static boolean hasSymmetricEncryption(Context context, InputStream inputStream)
@@ -548,11 +507,11 @@ public class PgpOperation {
} }
Bundle returnData = new Bundle(); Bundle returnData = new Bundle();
// automatically works with ascii armor input and binary
InputStream in = PGPUtil.getDecoderStream(mData.getInputStream()); InputStream in = PGPUtil.getDecoderStream(mData.getInputStream());
PGPObjectFactory pgpF = new PGPObjectFactory(in); PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc; PGPEncryptedDataList enc;
Object o = pgpF.nextObject(); Object o = pgpF.nextObject();
long signatureKeyId = 0;
int currentProgress = 0; int currentProgress = 0;
updateProgress(R.string.progress_reading_data, currentProgress, 100); updateProgress(R.string.progress_reading_data, currentProgress, 100);
@@ -669,6 +628,7 @@ public class PgpOperation {
currentProgress += 10; currentProgress += 10;
} }
long signatureKeyId = 0;
if (dataChunk instanceof PGPOnePassSignatureList) { if (dataChunk instanceof PGPOnePassSignatureList) {
updateProgress(R.string.progress_processing_signature, currentProgress, 100); updateProgress(R.string.progress_processing_signature, currentProgress, 100);
@@ -798,7 +758,7 @@ public class PgpOperation {
updateProgress(R.string.progress_done, 0, 100); updateProgress(R.string.progress_done, 0, 100);
// mostly taken from ClearSignedFileProcessor // mostly taken from pg/src/main/java/org/spongycastle/openpgp/examples/ClearSignedFileProcessor.java
ByteArrayOutputStream lineOut = new ByteArrayOutputStream(); ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
int lookAhead = readInputLine(lineOut, aIn); int lookAhead = readInputLine(lineOut, aIn);
byte[] lineSep = getLineSeparator(); byte[] lineSep = getLineSeparator();
@@ -895,8 +855,7 @@ public class PgpOperation {
return returnData; return returnData;
} }
public boolean verifyKeyBinding(Context mContext, PGPSignature signature, PGPPublicKey signatureKey) public boolean verifyKeyBinding(Context mContext, PGPSignature signature, PGPPublicKey signatureKey) {
{
long signatureKeyId = signature.getKeyID(); long signatureKeyId = signature.getKeyID();
boolean keyBinding_isok = false; boolean keyBinding_isok = false;
String userId = null; String userId = null;
@@ -914,8 +873,7 @@ public class PgpOperation {
return keyBinding_isok; return keyBinding_isok;
} }
public boolean verifyKeyBinding(PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) public boolean verifyKeyBinding(PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
{
boolean subkeyBinding_isok = false; boolean subkeyBinding_isok = false;
boolean tmp_subkeyBinding_isok = false; boolean tmp_subkeyBinding_isok = false;
boolean primkeyBinding_isok = false; boolean primkeyBinding_isok = false;
@@ -935,8 +893,8 @@ public class PgpOperation {
if (sig.getKeyID() == masterPublicKey.getKeyID() && sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) { if (sig.getKeyID() == masterPublicKey.getKeyID() && sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) {
//check and if ok, check primary key binding. //check and if ok, check primary key binding.
try { try {
sig.init(contentVerifierBuilderProvider, masterPublicKey); sig.init(contentVerifierBuilderProvider, masterPublicKey);
tmp_subkeyBinding_isok = sig.verifyCertification(masterPublicKey, signingPublicKey); tmp_subkeyBinding_isok = sig.verifyCertification(masterPublicKey, signingPublicKey);
} catch (PGPException e) { } catch (PGPException e) {
continue; continue;
} catch (SignatureException e) { } catch (SignatureException e) {
@@ -958,42 +916,41 @@ public class PgpOperation {
return (subkeyBinding_isok & primkeyBinding_isok); return (subkeyBinding_isok & primkeyBinding_isok);
} }
private boolean verifyPrimaryBinding(PGPSignatureSubpacketVector Pkts, PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) private boolean verifyPrimaryBinding(PGPSignatureSubpacketVector Pkts, PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
{
boolean primkeyBinding_isok = false; boolean primkeyBinding_isok = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureList eSigList; PGPSignatureList eSigList;
if (Pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) { if (Pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) {
try { try {
eSigList = Pkts.getEmbeddedSignatures(); eSigList = Pkts.getEmbeddedSignatures();
} catch (IOException e) { } catch (IOException e) {
return false; return false;
} catch (PGPException e) { } catch (PGPException e) {
return false; return false;
} }
for (int j = 0; j < eSigList.size(); ++j) { for (int j = 0; j < eSigList.size(); ++j) {
PGPSignature emSig = eSigList.get(j); PGPSignature emSig = eSigList.get(j);
if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) { if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) {
try { try {
emSig.init(contentVerifierBuilderProvider, signingPublicKey); emSig.init(contentVerifierBuilderProvider, signingPublicKey);
primkeyBinding_isok = emSig.verifyCertification(masterPublicKey, signingPublicKey); primkeyBinding_isok = emSig.verifyCertification(masterPublicKey, signingPublicKey);
if (primkeyBinding_isok) if (primkeyBinding_isok)
break; break;
} catch (PGPException e) { } catch (PGPException e) {
continue; continue;
} catch (SignatureException e) { } catch (SignatureException e) {
continue; continue;
} }
} }
} }
} }
return primkeyBinding_isok; return primkeyBinding_isok;
} }
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput, private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
final PGPSignatureGenerator pSignatureGenerator) throws IOException, SignatureException { final PGPSignatureGenerator pSignatureGenerator) throws IOException, SignatureException {
if (pLine == null) { if (pLine == null) {
return; return;
@@ -1018,7 +975,7 @@ public class PgpOperation {
} }
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput, private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
final PGPV3SignatureGenerator pSignatureGenerator) throws IOException, final PGPV3SignatureGenerator pSignatureGenerator) throws IOException,
SignatureException { SignatureException {
if (pLine == null) { if (pLine == null) {

View File

@@ -29,6 +29,7 @@ import org.openintents.openpgp.IOpenPgpService;
import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpConstants; import org.openintents.openpgp.util.OpenPgpConstants;
import org.spongycastle.openpgp.PGPUtil;
import org.spongycastle.util.Arrays; import org.spongycastle.util.Arrays;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.Id;
@@ -237,10 +238,12 @@ public class OpenPgpService extends RemoteService {
return passphraseBundle; return passphraseBundle;
} }
// sign and encrypt
operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null, operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null,
appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(), appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(),
appSettings.getHashAlgorithm(), true, passphrase); appSettings.getHashAlgorithm(), true, passphrase);
} else { } else {
// encrypt only
operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null, operation.signAndEncrypt(asciiArmor, appSettings.getCompression(), keyIds, null,
appSettings.getEncryptionAlgorithm(), Id.key.none, appSettings.getEncryptionAlgorithm(), Id.key.none,
appSettings.getHashAlgorithm(), true, null); appSettings.getHashAlgorithm(), true, null);
@@ -271,7 +274,7 @@ public class OpenPgpService extends RemoteService {
OpenPgpSignatureResult sigResult = null; OpenPgpSignatureResult sigResult = null;
try { try {
// PGPUtil.getDecoderStream(is)
// TODOs API 2.0: // TODOs API 2.0:
// implement verify-only! // implement verify-only!
// fix the mess: http://stackoverflow.com/questions/148130/how-do-i-peek-at-the-first-two-bytes-in-an-inputstream // fix the mess: http://stackoverflow.com/questions/148130/how-do-i-peek-at-the-first-two-bytes-in-an-inputstream
@@ -351,7 +354,7 @@ public class OpenPgpService extends RemoteService {
// //
// Log.d(Constants.TAG, "secretKeyId " + secretKeyId); // Log.d(Constants.TAG, "secretKeyId " + secretKeyId);
// NOTE: currently this only gets the passphrase for the saved key // NOTE: currently this only gets the passphrase for the key set for this client
String passphrase; String passphrase;
if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) { if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) {
passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE); passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE);
@@ -375,8 +378,10 @@ public class OpenPgpService extends RemoteService {
if (signedOnly) { if (signedOnly) {
outputBundle = operation.verifyText(); outputBundle = operation.verifyText();
} else { } else {
// BIG TODO: instead of trying to get the passphrase before // Do we want to do this: instead of trying to get the passphrase before
// pause stream when passphrase is missing and then resume // pause stream when passphrase is missing and then resume???
// TODO: this also decrypts with other secret keys without passphrase!!!
outputBundle = operation.decryptAndVerify(passphrase, false); outputBundle = operation.decryptAndVerify(passphrase, false);
} }

View File

@@ -116,7 +116,7 @@
<string name="label_passphrase_cache_ttl">Passphrase Cache</string> <string name="label_passphrase_cache_ttl">Passphrase Cache</string>
<string name="label_message_compression">Message Compression</string> <string name="label_message_compression">Message Compression</string>
<string name="label_file_compression">File Compression</string> <string name="label_file_compression">File Compression</string>
<string name="label_force_v3_signature">Force V3 Signatures</string> <string name="label_force_v3_signature">Force old OpenPGPv3 Signatures</string>
<string name="label_key_servers">Keyservers</string> <string name="label_key_servers">Keyservers</string>
<string name="label_key_id">Key ID</string> <string name="label_key_id">Key ID</string>
<string name="label_creation">Creation</string> <string name="label_creation">Creation</string>