mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-26 21:07:58 +01:00
Debug signature verification using debug build of bcpg
This commit is contained in:
parent
9fc4b0b42e
commit
4d6ca80e25
5 changed files with 59 additions and 77 deletions
|
@ -8,7 +8,12 @@ dependencies {
|
|||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||
|
||||
implementation "org.bouncycastle:bcprov-jdk15on:$bouncyCastleVersion"
|
||||
|
||||
//*
|
||||
api "org.bouncycastle:bcpg-jdk15on:$bouncyCastleVersion"
|
||||
/*/
|
||||
api files("libs/bcpg-jdk18on-1.70-SNAPSHOT.jar")
|
||||
// */
|
||||
|
||||
implementation 'org.slf4j:slf4j-api:1.7.32'
|
||||
testImplementation 'ch.qos.logback:logback-classic:1.2.5'
|
||||
|
|
|
@ -373,8 +373,21 @@ public final class SignatureVerifier {
|
|||
signature.init(ImplementationFactory.getInstance().getPGPContentVerifierBuilderProvider(), signingKey);
|
||||
int read;
|
||||
byte[] buf = new byte[8192];
|
||||
byte lastByte = -1;
|
||||
while ((read = signedData.read(buf)) != -1) {
|
||||
signature.update(buf, 0, read);
|
||||
// If we previously omitted a newline, but the stream is not yet empty, add it now
|
||||
if (lastByte == (byte) '\n') {
|
||||
signature.update(lastByte);
|
||||
}
|
||||
lastByte = buf[read - 1];
|
||||
|
||||
if (lastByte == (byte) '\n') {
|
||||
// if last byte in buffer is newline, omit it for now
|
||||
signature.update(buf, 0, read - 1);
|
||||
} else {
|
||||
// otherwise, write buffer as usual
|
||||
signature.update(buf, 0, read);
|
||||
}
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
throw new SignatureValidationException("Cannot init signature.", e);
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.pgpainless.signature.cleartext_signatures;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -23,11 +22,7 @@ import java.io.InputStream;
|
|||
import java.io.OutputStream;
|
||||
|
||||
import org.bouncycastle.bcpg.ArmoredInputStream;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPObjectFactory;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.bouncycastle.openpgp.PGPSignatureGenerator;
|
||||
import org.bouncycastle.openpgp.PGPSignatureList;
|
||||
import org.bouncycastle.util.Strings;
|
||||
import org.pgpainless.implementation.ImplementationFactory;
|
||||
|
@ -69,19 +64,17 @@ public final class ClearsignedMessageUtil {
|
|||
if (lookAhead != -1 && in.isClearText()) {
|
||||
byte[] line = lineOut.toByteArray();
|
||||
out.write(line, 0, getLengthWithoutSeparatorOrTrailingWhitespace(line));
|
||||
out.write(lineSep);
|
||||
|
||||
while (lookAhead != -1 && in.isClearText()) {
|
||||
lookAhead = readInputLine(lineOut, lookAhead, in);
|
||||
line = lineOut.toByteArray();
|
||||
out.write(line, 0, getLengthWithoutSeparatorOrTrailingWhitespace(line));
|
||||
out.write(lineSep);
|
||||
out.write(line, 0, getLengthWithoutSeparatorOrTrailingWhitespace(line));
|
||||
}
|
||||
} else {
|
||||
if (lookAhead != -1) {
|
||||
byte[] line = lineOut.toByteArray();
|
||||
out.write(line, 0, getLengthWithoutSeparatorOrTrailingWhitespace(line));
|
||||
out.write(lineSep);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -94,38 +87,6 @@ public final class ClearsignedMessageUtil {
|
|||
return signatures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the given signature by processing the data from the messageData input stream.
|
||||
*
|
||||
* @param signature uninitialized signature
|
||||
* @param signingKey public signing key
|
||||
* @param messageData input stream containing the data to which the signature belongs
|
||||
* @return initialized signature
|
||||
*
|
||||
* @throws PGPException if the signature cannot be initialized
|
||||
* @throws IOException if an IO error happens
|
||||
*/
|
||||
public static PGPSignature initializeSignature(PGPSignature signature, PGPPublicKey signingKey, InputStream messageData)
|
||||
throws PGPException, IOException {
|
||||
signature.init(ImplementationFactory.getInstance().getPGPContentVerifierBuilderProvider(), signingKey);
|
||||
|
||||
InputStream sigIn = new BufferedInputStream(messageData);
|
||||
ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
|
||||
int lookAhead = readInputLine(lineOut, sigIn);
|
||||
processLine(signature, lineOut.toByteArray());
|
||||
|
||||
if (lookAhead != -1) {
|
||||
do {
|
||||
lookAhead = readInputLine(lineOut, lookAhead, sigIn);
|
||||
signature.update((byte) '\r');
|
||||
signature.update((byte) '\n');
|
||||
processLine(signature, lineOut.toByteArray());
|
||||
} while (lookAhead != -1);
|
||||
}
|
||||
sigIn.close();
|
||||
return signature;
|
||||
}
|
||||
|
||||
public static int readInputLine(ByteArrayOutputStream bOut, InputStream fIn)
|
||||
throws IOException {
|
||||
bOut.reset();
|
||||
|
@ -190,25 +151,6 @@ public final class ClearsignedMessageUtil {
|
|||
return nlBytes;
|
||||
}
|
||||
|
||||
public static void processLine(PGPSignature sig, byte[] line) {
|
||||
int length = getLengthWithoutWhiteSpace(line);
|
||||
if (length > 0) {
|
||||
sig.update(line, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
public static void processLine(OutputStream aOut, PGPSignatureGenerator sGen, byte[] line)
|
||||
throws IOException {
|
||||
// note: trailing white space needs to be removed from the end of
|
||||
// each line for signature calculation RFC 4880 Section 7.1
|
||||
int length = getLengthWithoutWhiteSpace(line);
|
||||
if (length > 0) {
|
||||
sGen.update(line, 0, length);
|
||||
}
|
||||
|
||||
aOut.write(line, 0, line.length);
|
||||
}
|
||||
|
||||
private static int getLengthWithoutSeparatorOrTrailingWhitespace(byte[] line) {
|
||||
int end = line.length - 1;
|
||||
|
||||
|
@ -223,16 +165,6 @@ public final class ClearsignedMessageUtil {
|
|||
return b == '\r' || b == '\n';
|
||||
}
|
||||
|
||||
private static int getLengthWithoutWhiteSpace(byte[] line) {
|
||||
int end = line.length - 1;
|
||||
|
||||
while (end >= 0 && isWhiteSpace(line[end])) {
|
||||
end--;
|
||||
}
|
||||
|
||||
return end + 1;
|
||||
}
|
||||
|
||||
private static boolean isWhiteSpace(byte b) {
|
||||
return isLineEnding(b) || b == '\t' || b == ' ';
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.bouncycastle.openpgp.PGPSignatureList;
|
|||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.exception.SignatureValidationException;
|
||||
import org.pgpainless.signature.CertificateValidator;
|
||||
import org.pgpainless.signature.SignatureVerifier;
|
||||
import org.pgpainless.util.ArmoredInputStreamFactory;
|
||||
|
||||
/**
|
||||
|
@ -93,7 +94,7 @@ public class CleartextSignatureProcessor {
|
|||
}
|
||||
|
||||
try {
|
||||
ClearsignedMessageUtil.initializeSignature(signature, signingKey, multiPassStrategy.getMessageInputStream());
|
||||
SignatureVerifier.initializeSignatureAndUpdateWithSignedData(signature, multiPassStrategy.getMessageInputStream(), signingKey);
|
||||
CertificateValidator.validateCertificateAndVerifyInitializedSignature(signature, certificate, PGPainless.getPolicy());
|
||||
return signature;
|
||||
} catch (SignatureValidationException e) {
|
||||
|
|
|
@ -30,15 +30,17 @@ import org.bouncycastle.openpgp.PGPPublicKey;
|
|||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.key.TestKeys;
|
||||
import org.pgpainless.signature.CertificateValidator;
|
||||
import org.pgpainless.signature.SignatureUtils;
|
||||
import org.pgpainless.signature.cleartext_signatures.ClearsignedMessageUtil;
|
||||
import org.pgpainless.signature.SignatureVerifier;
|
||||
import org.pgpainless.signature.cleartext_signatures.CleartextSignatureProcessor;
|
||||
import org.pgpainless.signature.cleartext_signatures.InMemoryMultiPassStrategy;
|
||||
import org.pgpainless.signature.cleartext_signatures.MultiPassStrategy;
|
||||
import org.pgpainless.util.ArmorUtils;
|
||||
import org.pgpainless.util.TestUtils;
|
||||
|
||||
public class CleartextSignatureVerificationTest {
|
||||
|
@ -48,7 +50,7 @@ public class CleartextSignatureVerificationTest {
|
|||
"To blazon it, then sweeten with thy breath\n" +
|
||||
"This neighbor air, and let rich music’s tongue\n" +
|
||||
"Unfold the imagined happiness that both\n" +
|
||||
"Receive in either by this dear encounter.\n";
|
||||
"Receive in either by this dear encounter.";
|
||||
public static final String MESSAGE_SIGNED = "-----BEGIN PGP SIGNED MESSAGE-----\n" +
|
||||
"Hash: SHA512\n" +
|
||||
"\n" +
|
||||
|
@ -118,11 +120,40 @@ public class CleartextSignatureVerificationTest {
|
|||
PGPSignature signature = SignatureUtils.readSignatures(SIGNATURE).get(0);
|
||||
PGPPublicKey signingKey = signingKeys.getPublicKey(signature.getKeyID());
|
||||
|
||||
/*
|
||||
SignatureVerifier.initializeSignatureAndUpdateWithSignedData(signature, new ByteArrayInputStream(MESSAGE_BODY.getBytes(StandardCharsets.UTF_8)), signingKey);
|
||||
/*/
|
||||
ClearsignedMessageUtil.initializeSignature(signature, signingKey, new ByteArrayInputStream(MESSAGE_BODY.getBytes(StandardCharsets.UTF_8)));
|
||||
//*/
|
||||
|
||||
CertificateValidator.validateCertificateAndVerifyInitializedSignature(signature, signingKeys, PGPainless.getPolicy());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void print() throws IOException {
|
||||
// CHECKSTYLE:OFF
|
||||
PGPPublicKeyRing keys = TestKeys.getEmilPublicKeyRing();
|
||||
System.out.println(ArmorUtils.toAsciiArmoredString(keys));
|
||||
System.out.println(MESSAGE_SIGNED);
|
||||
System.out.println(MESSAGE_BODY);
|
||||
System.out.println(SIGNATURE);
|
||||
// CHECKSTYLE:ON
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutputOfSigVerification() throws IOException, PGPException {
|
||||
PGPSignature signature = SignatureUtils.readSignatures(SIGNATURE).get(0);
|
||||
|
||||
ConsumerOptions options = new ConsumerOptions()
|
||||
.addVerificationCert(TestKeys.getEmilPublicKeyRing())
|
||||
.addVerificationOfDetachedSignature(signature);
|
||||
|
||||
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
||||
.onInputStream(new ByteArrayInputStream(MESSAGE_BODY.getBytes(StandardCharsets.UTF_8)))
|
||||
.withOptions(options);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Streams.pipeAll(decryptionStream, out);
|
||||
decryptionStream.close();
|
||||
|
||||
OpenPgpMetadata metadata = decryptionStream.getResult();
|
||||
assertEquals(1, metadata.getVerifiedSignatures().size());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue