Experimental API support for detached signatures (not tested)
This commit is contained in:
@@ -247,7 +247,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
||||
|
||||
int signatureType;
|
||||
if (cleartext) {
|
||||
// for sign-only ascii text
|
||||
// for sign-only ascii text (cleartext signature)
|
||||
signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT;
|
||||
} else {
|
||||
signatureType = PGPSignature.BINARY_DOCUMENT;
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -78,7 +79,8 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
private int mSignatureHashAlgorithm;
|
||||
private String mSignaturePassphrase;
|
||||
private long mAdditionalEncryptId;
|
||||
private boolean mCleartextInput;
|
||||
private boolean mCleartextSignature;
|
||||
private boolean mDetachedSignature;
|
||||
private String mOriginalFilename;
|
||||
private boolean mFailOnMissingEncryptionKeyIds;
|
||||
|
||||
@@ -113,7 +115,8 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
this.mSignatureHashAlgorithm = builder.mSignatureHashAlgorithm;
|
||||
this.mSignaturePassphrase = builder.mSignaturePassphrase;
|
||||
this.mAdditionalEncryptId = builder.mAdditionalEncryptId;
|
||||
this.mCleartextInput = builder.mCleartextInput;
|
||||
this.mCleartextSignature = builder.mCleartextSignature;
|
||||
this.mDetachedSignature = builder.mDetachedSignature;
|
||||
this.mNfcSignedHash = builder.mNfcSignedHash;
|
||||
this.mNfcCreationTimestamp = builder.mNfcCreationTimestamp;
|
||||
this.mOriginalFilename = builder.mOriginalFilename;
|
||||
@@ -140,7 +143,8 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
private int mSignatureHashAlgorithm = 0;
|
||||
private String mSignaturePassphrase = null;
|
||||
private long mAdditionalEncryptId = Constants.key.none;
|
||||
private boolean mCleartextInput = false;
|
||||
private boolean mCleartextSignature = false;
|
||||
private boolean mDetachedSignature = false;
|
||||
private String mOriginalFilename = "";
|
||||
private byte[] mNfcSignedHash = null;
|
||||
private Date mNfcCreationTimestamp = null;
|
||||
@@ -222,14 +226,13 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: test this option!
|
||||
*
|
||||
* @param cleartextInput
|
||||
* @return
|
||||
*/
|
||||
public Builder setCleartextInput(boolean cleartextInput) {
|
||||
mCleartextInput = cleartextInput;
|
||||
public Builder setCleartextSignature(boolean cleartextSignature) {
|
||||
mCleartextSignature = cleartextSignature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDetachedSignature(boolean detachedSignature) {
|
||||
mDetachedSignature = detachedSignature;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -408,7 +411,7 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
updateProgress(R.string.progress_preparing_signature, 4, 100);
|
||||
|
||||
try {
|
||||
boolean cleartext = mCleartextInput && mEnableAsciiArmorOutput && !enableEncryption;
|
||||
boolean cleartext = mCleartextSignature && mEnableAsciiArmorOutput && !enableEncryption;
|
||||
signatureGenerator = signingKey.getSignatureGenerator(
|
||||
mSignatureHashAlgorithm, cleartext, mNfcSignedHash, mNfcCreationTimestamp);
|
||||
} catch (PgpGeneralException e) {
|
||||
@@ -424,6 +427,9 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
OutputStream encryptionOut = null;
|
||||
BCPGOutputStream bcpgOut;
|
||||
|
||||
ByteArrayOutputStream detachedByteOut = null;
|
||||
BCPGOutputStream detachedBcpgOut = null;
|
||||
|
||||
try {
|
||||
|
||||
if (enableEncryption) {
|
||||
@@ -452,7 +458,7 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
|
||||
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
|
||||
char literalDataFormatTag;
|
||||
if (mCleartextInput) {
|
||||
if (mCleartextSignature) {
|
||||
literalDataFormatTag = PGPLiteralData.UTF8;
|
||||
} else {
|
||||
literalDataFormatTag = PGPLiteralData.BINARY;
|
||||
@@ -482,7 +488,7 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
literalGen.close();
|
||||
indent -= 1;
|
||||
|
||||
} else if (enableSignature && mCleartextInput && mEnableAsciiArmorOutput) {
|
||||
} else if (enableSignature && mCleartextSignature && mEnableAsciiArmorOutput) {
|
||||
/* cleartext signature: sign-only of ascii text */
|
||||
|
||||
updateProgress(R.string.progress_signing, 8, 100);
|
||||
@@ -517,11 +523,44 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
armorOut.endClearText();
|
||||
|
||||
pOut = new BCPGOutputStream(armorOut);
|
||||
} else if (enableSignature && !mCleartextInput) {
|
||||
} else if (enableSignature && mDetachedSignature) {
|
||||
/* detached signature */
|
||||
|
||||
updateProgress(R.string.progress_signing, 8, 100);
|
||||
log.add(LogType.MSG_SE_SIGNING, indent);
|
||||
|
||||
InputStream in = mData.getInputStream();
|
||||
|
||||
// handle output stream separately for detached signatures
|
||||
detachedByteOut = new ByteArrayOutputStream();
|
||||
OutputStream detachedOut = detachedByteOut;
|
||||
if (mEnableAsciiArmorOutput) {
|
||||
detachedOut = new ArmoredOutputStream(detachedOut);
|
||||
}
|
||||
detachedBcpgOut = new BCPGOutputStream(detachedOut);
|
||||
|
||||
long alreadyWritten = 0;
|
||||
int length;
|
||||
byte[] buffer = new byte[1 << 16];
|
||||
while ((length = in.read(buffer)) > 0) {
|
||||
// pipe input stream directly into output stream, no changes to data
|
||||
mOutStream.write(buffer, 0, length);
|
||||
|
||||
signatureGenerator.update(buffer, 0, length);
|
||||
|
||||
alreadyWritten += length;
|
||||
if (mData.getSize() > 0) {
|
||||
long progress = 100 * alreadyWritten / mData.getSize();
|
||||
progressScaler.setProgress((int) progress, 100);
|
||||
}
|
||||
}
|
||||
|
||||
pOut = null;
|
||||
} else if (enableSignature && !mCleartextSignature && !mDetachedSignature) {
|
||||
/* sign-only binary (files/data stream) */
|
||||
|
||||
updateProgress(R.string.progress_signing, 8, 100);
|
||||
log.add(LogType.MSG_SE_ENCRYPTING, indent);
|
||||
log.add(LogType.MSG_SE_SIGNING, indent);
|
||||
|
||||
InputStream in = mData.getInputStream();
|
||||
|
||||
@@ -556,13 +595,18 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
literalGen.close();
|
||||
} else {
|
||||
pOut = null;
|
||||
// TODO: Is this log right?
|
||||
log.add(LogType.MSG_SE_CLEARSIGN_ONLY, indent);
|
||||
}
|
||||
|
||||
if (enableSignature) {
|
||||
updateProgress(R.string.progress_generating_signature, 95, 100);
|
||||
try {
|
||||
signatureGenerator.generate().encode(pOut);
|
||||
if (detachedBcpgOut != null) {
|
||||
signatureGenerator.generate().encode(detachedBcpgOut);
|
||||
} else {
|
||||
signatureGenerator.generate().encode(pOut);
|
||||
}
|
||||
} catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) {
|
||||
// this secret key diverts to a OpenPGP card, throw exception with hash that will be signed
|
||||
log.add(LogType.MSG_SE_PENDING_NFC, indent);
|
||||
@@ -607,10 +651,22 @@ public class PgpSignEncrypt extends BaseOperation {
|
||||
updateProgress(R.string.progress_done, 100, 100);
|
||||
|
||||
log.add(LogType.MSG_SE_OK, indent);
|
||||
return new SignEncryptResult(SignEncryptResult.RESULT_OK, log);
|
||||
|
||||
SignEncryptResult result = new SignEncryptResult(SignEncryptResult.RESULT_OK, log);
|
||||
if (detachedByteOut != null) {
|
||||
try {
|
||||
detachedByteOut.flush();
|
||||
detachedByteOut.close();
|
||||
} catch (IOException e) {
|
||||
// silently catch
|
||||
}
|
||||
result.setDetachedSignature(detachedByteOut.toByteArray());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove whitespaces on line endings
|
||||
*/
|
||||
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
|
||||
final PGPSignatureGenerator pSignatureGenerator)
|
||||
throws IOException, SignatureException {
|
||||
|
||||
Reference in New Issue
Block a user