mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-03-03 02:42:00 -05:00
PgpSignEncrypt: merge generateSignature() into main method
This commit is contained in:
parent
e39b081927
commit
5346d2e878
@ -56,6 +56,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
@ -82,6 +83,18 @@ public class PgpSignEncrypt {
|
|||||||
private boolean mSignatureForceV3;
|
private boolean mSignatureForceV3;
|
||||||
private String mSignaturePassphrase;
|
private String mSignaturePassphrase;
|
||||||
private boolean mEncryptToSigner;
|
private boolean mEncryptToSigner;
|
||||||
|
private boolean mBinaryInput;
|
||||||
|
|
||||||
|
private static byte[] NEW_LINE;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
NEW_LINE = "\r\n".getBytes("UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Log.e(Constants.TAG, "UnsupportedEncodingException", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private PgpSignEncrypt(Builder builder) {
|
private PgpSignEncrypt(Builder builder) {
|
||||||
// private Constructor can only be called from Builder
|
// private Constructor can only be called from Builder
|
||||||
@ -101,6 +114,7 @@ public class PgpSignEncrypt {
|
|||||||
this.mSignatureForceV3 = builder.mSignatureForceV3;
|
this.mSignatureForceV3 = builder.mSignatureForceV3;
|
||||||
this.mSignaturePassphrase = builder.mSignaturePassphrase;
|
this.mSignaturePassphrase = builder.mSignaturePassphrase;
|
||||||
this.mEncryptToSigner = builder.mEncryptToSigner;
|
this.mEncryptToSigner = builder.mEncryptToSigner;
|
||||||
|
this.mBinaryInput = builder.mBinaryInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
@ -121,6 +135,7 @@ public class PgpSignEncrypt {
|
|||||||
private boolean mSignatureForceV3 = false;
|
private boolean mSignatureForceV3 = false;
|
||||||
private String mSignaturePassphrase = null;
|
private String mSignaturePassphrase = null;
|
||||||
private boolean mEncryptToSigner = false;
|
private boolean mEncryptToSigner = false;
|
||||||
|
private boolean mBinaryInput = false;
|
||||||
|
|
||||||
public Builder(Context context, InputData data, OutputStream outStream) {
|
public Builder(Context context, InputData data, OutputStream outStream) {
|
||||||
this.mContext = context;
|
this.mContext = context;
|
||||||
@ -178,11 +193,28 @@ public class PgpSignEncrypt {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: test this option!
|
||||||
|
*
|
||||||
|
* @param encryptToSigner
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Builder encryptToSigner(boolean encryptToSigner) {
|
public Builder encryptToSigner(boolean encryptToSigner) {
|
||||||
this.mEncryptToSigner = encryptToSigner;
|
this.mEncryptToSigner = encryptToSigner;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: test this option!
|
||||||
|
*
|
||||||
|
* @param binaryInput
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Builder binaryInput(boolean binaryInput) {
|
||||||
|
this.mBinaryInput = binaryInput;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public PgpSignEncrypt build() {
|
public PgpSignEncrypt build() {
|
||||||
return new PgpSignEncrypt(this);
|
return new PgpSignEncrypt(this);
|
||||||
}
|
}
|
||||||
@ -394,21 +426,20 @@ public class PgpSignEncrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
literalGen.close();
|
literalGen.close();
|
||||||
} else if (mEnableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
} else if (!mBinaryInput && mEnableAsciiArmorOutput && enableSignature && !enableEncryption && !enableCompression) {
|
||||||
/* sign-only of ascii text */
|
/* cleartext signature: sign-only of ascii text */
|
||||||
|
|
||||||
updateProgress(R.string.progress_signing, 40, 100);
|
updateProgress(R.string.progress_signing, 40, 100);
|
||||||
|
|
||||||
// write directly on armor output stream
|
// write -----BEGIN PGP SIGNED MESSAGE-----
|
||||||
armorOut.beginClearText(mSignatureHashAlgorithm);
|
armorOut.beginClearText(mSignatureHashAlgorithm);
|
||||||
|
|
||||||
InputStream in = mData.getInputStream();
|
InputStream in = mData.getInputStream();
|
||||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||||
|
|
||||||
final byte[] newline = "\r\n".getBytes("UTF-8");
|
// update signature buffer with first line
|
||||||
|
|
||||||
if (mSignatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
processLine(reader.readLine(), armorOut, signatureV3Generator);
|
processLineV3(reader.readLine(), armorOut, signatureV3Generator);
|
||||||
} else {
|
} else {
|
||||||
processLine(reader.readLine(), armorOut, signatureGenerator);
|
processLine(reader.readLine(), armorOut, signatureGenerator);
|
||||||
}
|
}
|
||||||
@ -416,28 +447,62 @@ public class PgpSignEncrypt {
|
|||||||
while (true) {
|
while (true) {
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
|
|
||||||
|
// end cleartext signature with newline, see http://tools.ietf.org/html/rfc4880#section-7
|
||||||
if (line == null) {
|
if (line == null) {
|
||||||
armorOut.write(newline);
|
armorOut.write(NEW_LINE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
armorOut.write(newline);
|
armorOut.write(NEW_LINE);
|
||||||
|
|
||||||
// update signature buffer with input line
|
// update signature buffer with input line
|
||||||
if (mSignatureForceV3) {
|
if (mSignatureForceV3) {
|
||||||
signatureV3Generator.update(newline);
|
signatureV3Generator.update(NEW_LINE);
|
||||||
processLine(line, armorOut, signatureV3Generator);
|
processLineV3(line, armorOut, signatureV3Generator);
|
||||||
} else {
|
} else {
|
||||||
signatureGenerator.update(newline);
|
signatureGenerator.update(NEW_LINE);
|
||||||
processLine(line, armorOut, signatureGenerator);
|
processLine(line, armorOut, signatureGenerator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
armorOut.endClearText();
|
armorOut.endClearText();
|
||||||
|
|
||||||
|
|
||||||
pOut = new BCPGOutputStream(armorOut);
|
pOut = new BCPGOutputStream(armorOut);
|
||||||
|
} else if (mBinaryInput && enableSignature && !enableEncryption && !enableCompression) {
|
||||||
|
// TODO: This part of the code is not tested!!!
|
||||||
|
/* sign-only binaries (files) */
|
||||||
|
|
||||||
|
updateProgress(R.string.progress_signing, 40, 100);
|
||||||
|
|
||||||
|
InputStream in = mData.getInputStream();
|
||||||
|
if (mEnableAsciiArmorOutput) {
|
||||||
|
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
if (mSignatureForceV3) {
|
||||||
|
processLineV3(line, null, signatureV3Generator);
|
||||||
|
signatureV3Generator.update(NEW_LINE);
|
||||||
|
} else {
|
||||||
|
processLine(line, null, signatureGenerator);
|
||||||
|
signatureGenerator.update(NEW_LINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
byte[] buffer = new byte[1 << 16];
|
||||||
|
int n;
|
||||||
|
while ((n = in.read(buffer)) > 0) {
|
||||||
|
if (mSignatureForceV3) {
|
||||||
|
signatureV3Generator.update(buffer, 0, n);
|
||||||
|
} else {
|
||||||
|
signatureGenerator.update(buffer, 0, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pOut = new BCPGOutputStream(out);
|
||||||
} else {
|
} else {
|
||||||
// TODO: implement sign-only for files!
|
|
||||||
pOut = null;
|
pOut = null;
|
||||||
Log.e(Constants.TAG, "not supported!");
|
Log.e(Constants.TAG, "not supported!");
|
||||||
}
|
}
|
||||||
@ -471,119 +536,6 @@ public class PgpSignEncrypt {
|
|||||||
updateProgress(R.string.progress_done, 100, 100);
|
updateProgress(R.string.progress_done, 100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: merge this into execute method!
|
|
||||||
// TODO: allow binary input for this class
|
|
||||||
public void generateSignature()
|
|
||||||
throws PgpGeneralException, PGPException, IOException, NoSuchAlgorithmException,
|
|
||||||
SignatureException {
|
|
||||||
|
|
||||||
OutputStream out;
|
|
||||||
if (mEnableAsciiArmorOutput) {
|
|
||||||
// Ascii Armor (Radix-64)
|
|
||||||
ArmoredOutputStream armorOut = new ArmoredOutputStream(mOutStream);
|
|
||||||
armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
|
|
||||||
out = armorOut;
|
|
||||||
} else {
|
|
||||||
out = mOutStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSignatureMasterKeyId == 0) {
|
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_key));
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPSecretKeyRing signingKeyRing;
|
|
||||||
try {
|
|
||||||
signingKeyRing = mProviderHelper.getPGPSecretKeyRing(mSignatureMasterKeyId);
|
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
|
|
||||||
}
|
|
||||||
PGPSecretKey signingKey = PgpKeyHelper.getSigningKey(signingKeyRing);
|
|
||||||
if (signingKey == null) {
|
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSignaturePassphrase == null) {
|
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_signature_passphrase));
|
|
||||||
}
|
|
||||||
|
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mSignaturePassphrase.toCharArray());
|
|
||||||
PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
|
|
||||||
if (signaturePrivateKey == null) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
int type = PGPSignature.CANONICAL_TEXT_DOCUMENT;
|
|
||||||
// if (binary) {
|
|
||||||
// type = PGPSignature.BINARY_DOCUMENT;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// content signer based on signing key algorithm and chosen hash algorithm
|
|
||||||
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
|
|
||||||
.getPublicKey().getAlgorithm(), mSignatureHashAlgorithm)
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
|
|
||||||
PGPSignatureGenerator signatureGenerator = null;
|
|
||||||
PGPV3SignatureGenerator signatureV3Generator = null;
|
|
||||||
if (mSignatureForceV3) {
|
|
||||||
signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
|
|
||||||
signatureV3Generator.init(type, signaturePrivateKey);
|
|
||||||
} else {
|
|
||||||
signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
|
|
||||||
signatureGenerator.init(type, signaturePrivateKey);
|
|
||||||
|
|
||||||
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
|
|
||||||
String userId = PgpKeyHelper.getMainUserId(signingKeyRing.getSecretKey());
|
|
||||||
spGen.setSignerUserID(false, userId);
|
|
||||||
signatureGenerator.setHashedSubpackets(spGen.generate());
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProgress(R.string.progress_signing, 40, 100);
|
|
||||||
|
|
||||||
InputStream inStream = mData.getInputStream();
|
|
||||||
// if (binary) {
|
|
||||||
// byte[] buffer = new byte[1 << 16];
|
|
||||||
// int n = 0;
|
|
||||||
// while ((n = inStream.read(buffer)) > 0) {
|
|
||||||
// if (signatureForceV3) {
|
|
||||||
// signatureV3Generator.update(buffer, 0, n);
|
|
||||||
// } else {
|
|
||||||
// signatureGenerator.update(buffer, 0, n);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
|
|
||||||
final byte[] newline = "\r\n".getBytes("UTF-8");
|
|
||||||
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
if (mSignatureForceV3) {
|
|
||||||
processLine(line, null, signatureV3Generator);
|
|
||||||
signatureV3Generator.update(newline);
|
|
||||||
} else {
|
|
||||||
processLine(line, null, signatureGenerator);
|
|
||||||
signatureGenerator.update(newline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
|
|
||||||
BCPGOutputStream bOut = new BCPGOutputStream(out);
|
|
||||||
if (mSignatureForceV3) {
|
|
||||||
signatureV3Generator.generate().encode(bOut);
|
|
||||||
} else {
|
|
||||||
signatureGenerator.generate().encode(bOut);
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
mOutStream.close();
|
|
||||||
|
|
||||||
updateProgress(R.string.progress_done, 100, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
|
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
|
||||||
final PGPSignatureGenerator pSignatureGenerator)
|
final PGPSignatureGenerator pSignatureGenerator)
|
||||||
throws IOException, SignatureException {
|
throws IOException, SignatureException {
|
||||||
@ -610,8 +562,8 @@ public class PgpSignEncrypt {
|
|||||||
pSignatureGenerator.update(data);
|
pSignatureGenerator.update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
|
private static void processLineV3(final String pLine, final ArmoredOutputStream pArmoredOutput,
|
||||||
final PGPV3SignatureGenerator pSignatureGenerator)
|
final PGPV3SignatureGenerator pSignatureGenerator)
|
||||||
throws IOException, SignatureException {
|
throws IOException, SignatureException {
|
||||||
|
|
||||||
if (pLine == null) {
|
if (pLine == null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user