mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-22 19:08:00 +01:00
Fix signing and include strategies
This commit is contained in:
parent
719c467768
commit
debee9839e
15 changed files with 278 additions and 284 deletions
|
@ -1,166 +0,0 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.NoSuchProviderException;
|
|
||||||
import java.security.Security;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.RsaLength;
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
|
||||||
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
|
|
||||||
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
|
|
||||||
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
|
|
||||||
import org.bouncycastle.util.io.Streams;
|
|
||||||
|
|
||||||
public class Main {
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException,
|
|
||||||
IOException {
|
|
||||||
|
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
|
||||||
|
|
||||||
PGPSecretKeyRing a = PGPainless.generateKeyRing().simpleRsaKeyRing("a@b.c", RsaLength._2048);
|
|
||||||
PGPSecretKeyRing b = PGPainless.generateKeyRing().simpleRsaKeyRing("b@c.d", RsaLength._2048);
|
|
||||||
|
|
||||||
SecretKeyRingProtector secretKeyRingDecryptor = new SecretKeyRingProtector() {
|
|
||||||
@Override
|
|
||||||
public PBESecretKeyDecryptor getDecryptor(Long keyId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PBESecretKeyEncryptor getEncryptor(Long keyId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
byte[] m = "Dies ist ein verschlüsselter Text.".getBytes();
|
|
||||||
ByteArrayInputStream fromPlain = new ByteArrayInputStream(m);
|
|
||||||
ByteArrayOutputStream toEncrypted = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
OutputStream encryptor = PGPainless.createEncryptor().onOutputStream(toEncrypted)
|
|
||||||
.toRecipient(b.getPublicKey())
|
|
||||||
.usingAlgorithms(SymmetricKeyAlgorithm.AES_256, HashAlgorithm.SHA512, CompressionAlgorithm.UNCOMPRESSED)
|
|
||||||
.signWith(a, secretKeyRingDecryptor)
|
|
||||||
.asciiArmor();
|
|
||||||
|
|
||||||
Streams.pipeAll(fromPlain, encryptor);
|
|
||||||
fromPlain.close();
|
|
||||||
encryptor.close();
|
|
||||||
|
|
||||||
System.out.println(new String(toEncrypted.toByteArray()));
|
|
||||||
|
|
||||||
ByteArrayInputStream fromEncrypted = new ByteArrayInputStream(toEncrypted.toByteArray());
|
|
||||||
ByteArrayOutputStream toPlain = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
PainlessResult.ResultAndInputStream resultAndInputStream = PGPainless.createDecryptor()
|
|
||||||
.onInputStream(fromEncrypted)
|
|
||||||
.decryptWith(new PGPSecretKeyRingCollection(Collections.singleton(b)), secretKeyRingDecryptor)
|
|
||||||
.verifyWith(Collections.singleton(a.getPublicKey().getKeyID()),
|
|
||||||
Collections.singleton(new PGPPublicKeyRing(a.getPublicKey().getEncoded(), new BcKeyFingerprintCalculator())))
|
|
||||||
.ignoreMissingPublicKeys()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
InputStream decryptor = resultAndInputStream.getInputStream();
|
|
||||||
|
|
||||||
Streams.pipeAll(decryptor, toPlain);
|
|
||||||
decryptor.close();
|
|
||||||
toPlain.close();
|
|
||||||
|
|
||||||
PainlessResult result = resultAndInputStream.getResult();
|
|
||||||
|
|
||||||
System.out.println(b.getPublicKey().getKeyID() + " " + result.getDecryptionKeyId());
|
|
||||||
System.out.println(new String(toPlain.toByteArray()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void gpg(PGPSecretKeyRing a, PGPSecretKeyRing b, SecretKeyRingProtector secretKeyRingDecryptor)
|
|
||||||
throws IOException, PGPException {
|
|
||||||
String gpg = "-----BEGIN PGP MESSAGE-----\n" +
|
|
||||||
"\n" +
|
|
||||||
"hQGMAwAAAAAAAAAAAQv+JyovfiPxDiLe9XlgQAG6zD+YdRtZRuUJD+A+ZX4Sn0w0\n" +
|
|
||||||
"2Dl9Ehf7lKjIo0cIfVOUrgITnWIRWAyfrk5KiXdXcZ6dXxz/YJFnLSlgqUwq7GWi\n" +
|
|
||||||
"NYf3Uqg+/8f3Ucl0x6sr1oddwB9OI7zRJwDqEzTORjLBu1vtDlFPMPWwAeqDtZgz\n" +
|
|
||||||
"ikT6vSFfhVjVbgx4mztw7hatWNjXzNkl9+lojzo9IyiA+3SBsRe/2My3ZBjPx97f\n" +
|
|
||||||
"3YGMCvbggdX3C/MRV2iek2pFX7YTKasFeEy5Y1c09upqaEIpaJq8vi1Fu44dv0Rt\n" +
|
|
||||||
"gv4sdljaJXsFn9aoVFrp/xU4SyPiC1Z/KjqE3Zfyh+OMWKoWmtYH07/g8IGkkBCh\n" +
|
|
||||||
"xuDiyy813WS3xtCyX405Vd+rxYC3y1h1FtthdO/AIrYSWj6qI6hyK2tyYmwsg+oY\n" +
|
|
||||||
"1oaXhcTbWXsBO89v0YtmVK1bPVXq8ao/DQvrs84JsYsKzXA17gKyBLBUoTNn8h8A\n" +
|
|
||||||
"AXg455AN8iHi2u5pAKr7hQIMAwAAAAAAAAAAAQ/7Bg8SGEfMPmtDy/BazrYWaXvX\n" +
|
|
||||||
"1+WWRNM630ULPEq7LG4BKJJOOrhk0kNkjIsaXhgqn9bt3YxxuE1eOQksjn0sNOD7\n" +
|
|
||||||
"3NAOicHzQ7xOarvN9OUSGirc+EIn4ETRGKYF1TXHBSYnBeb+DLCbRZkBZhRrA5Lc\n" +
|
|
||||||
"z08kWrGRfq5Bz6eMatBTO1L8XTIxHPgc9/LNv7OqcIfT0udjOQMkA7oxCz5mLl2b\n" +
|
|
||||||
"dApsDEFNKNaGgRzSf2rDqw0SGkDxYsXI6IYrVSEm6uDt+ScybS0KkcEgg+I9l91n\n" +
|
|
||||||
"XgqQQaXpYnHgETqKYfcUOk5iEND5Lvik/XhHNViaL3CdOkxFLTa0wfy0y0IsV2Y3\n" +
|
|
||||||
"xGkMOWdDjXlY8UWRgoK61M91phgZ48zfSoVvXNDrjOJzm1jn8CFFFov4Gse7CtlM\n" +
|
|
||||||
"A+3ntVdjL94jkp+2mU3e9kzCOG+ChylLuqlGTvavbHt/rzuZooi/6g1VHy1r+v9I\n" +
|
|
||||||
"rWKX6q55H8JzZXZOrfED39QocK9b1BjtEca/Qnqw82+IVY/CufBmnmbOWUkHq1zP\n" +
|
|
||||||
"6nj840HxH1zV5vHf8vlXxV7/iBesAF94dLT/Hp0E7+Ilyp/pQaQjMS2RLycMUJQJ\n" +
|
|
||||||
"pQey81gpuOWD6YIbvgnrMBMrJLyJSk3r3sMdJ3DCPxHC+OyvHxddA5TdL2e4aP3L\n" +
|
|
||||||
"OzKql59v1w+9Doe3LEPSPgEVAdUUg0nEl5lg9LLqaepaYp8NfsEC1Rnk/MLxciJu\n" +
|
|
||||||
"9oNjqPqQxKTv4aQO/Qb8gHFb3O34OnNKz+CzrX5Q\n" +
|
|
||||||
"=sVVl\n" +
|
|
||||||
"-----END PGP MESSAGE-----";
|
|
||||||
|
|
||||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(gpg.getBytes());
|
|
||||||
|
|
||||||
InputStream decryptor = PGPainless.createDecryptor().onInputStream(inputStream)
|
|
||||||
.decryptWith(new PGPSecretKeyRingCollection(Collections.singleton(b)), secretKeyRingDecryptor)
|
|
||||||
.doNotVerify()
|
|
||||||
.build()
|
|
||||||
.getInputStream();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void symm(PGPSecretKeyRing a, PGPSecretKeyRing b, SecretKeyRingProtector secretKeyRingDecryptor)
|
|
||||||
throws IOException, PGPException {
|
|
||||||
byte[] bytes = "Diese Nachricht ist streng geheim!!!".getBytes(Charset.forName("UTF-8"));
|
|
||||||
ByteArrayInputStream fromPlain = new ByteArrayInputStream(bytes);
|
|
||||||
ByteArrayOutputStream toEncrypted = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
OutputStream encryptor = PGPainless.createEncryptor()
|
|
||||||
.onOutputStream(toEncrypted)
|
|
||||||
.toRecipient(b.getPublicKey())
|
|
||||||
.usingAlgorithms(SymmetricKeyAlgorithm.AES_256, HashAlgorithm.SHA512, CompressionAlgorithm.UNCOMPRESSED)
|
|
||||||
.signWith(a, secretKeyRingDecryptor)
|
|
||||||
.noArmor();
|
|
||||||
|
|
||||||
Streams.pipeAll(fromPlain, encryptor);
|
|
||||||
encryptor.close();
|
|
||||||
|
|
||||||
System.out.println(new String(toEncrypted.toByteArray(), Charset.forName("UTF-8")));
|
|
||||||
|
|
||||||
ByteArrayInputStream fromEncrypted = new ByteArrayInputStream(toEncrypted.toByteArray());
|
|
||||||
ByteArrayOutputStream toPlain = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
PainlessResult.ResultAndInputStream resultAndInputStream = PGPainless.createDecryptor()
|
|
||||||
.onInputStream(fromEncrypted)
|
|
||||||
.decryptWith(new PGPSecretKeyRingCollection(Collections.singleton(b)), secretKeyRingDecryptor)
|
|
||||||
.verifyWith(Collections.singleton(a.getPublicKey().getKeyID()),
|
|
||||||
Collections.singleton(new PGPPublicKeyRing(a.getPublicKey().getEncoded(), new BcKeyFingerprintCalculator())))
|
|
||||||
.ignoreMissingPublicKeys()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
InputStream decryptor = resultAndInputStream.getInputStream();
|
|
||||||
|
|
||||||
Streams.pipeAll(decryptor, toPlain);
|
|
||||||
decryptor.close();
|
|
||||||
|
|
||||||
PainlessResult result = resultAndInputStream.getResult();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@ import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.PainlessResult;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
@ -89,7 +88,7 @@ public class DecryptionBuilder implements DecryptionBuilderInterface {
|
||||||
class BuildImpl implements Build {
|
class BuildImpl implements Build {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PainlessResult.ResultAndInputStream build() throws IOException, PGPException {
|
public DecryptionStream build() throws IOException, PGPException {
|
||||||
return DecryptionStreamFactory.create(inputStream,
|
return DecryptionStreamFactory.create(inputStream,
|
||||||
decryptionKeys, decryptionKeyDecryptor, verificationKeys, trustedKeyIds, missingPublicKeyCallback);
|
decryptionKeys, decryptionKeyDecryptor, verificationKeys, trustedKeyIds, missingPublicKeyCallback);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.PainlessResult;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
@ -42,7 +41,7 @@ public interface DecryptionBuilderInterface {
|
||||||
|
|
||||||
interface Build {
|
interface Build {
|
||||||
|
|
||||||
PainlessResult.ResultAndInputStream build() throws IOException, PGPException;
|
DecryptionStream build() throws IOException, PGPException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package de.vanitasvitae.crypto.pgpainless.decryption_verification;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class DecryptionStream extends InputStream {
|
||||||
|
|
||||||
|
private final InputStream inputStream;
|
||||||
|
private final PainlessResult.Builder resultBuilder;
|
||||||
|
private boolean isClosed = false;
|
||||||
|
|
||||||
|
DecryptionStream(InputStream wrapped, PainlessResult.Builder resultBuilder) {
|
||||||
|
|
||||||
|
if (wrapped == null) {
|
||||||
|
throw new NullPointerException("Wrapped InputStream MUST NOT be null!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.inputStream = wrapped;
|
||||||
|
this.resultBuilder = resultBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
return inputStream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
inputStream.close();
|
||||||
|
this.isClosed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PainlessResult getResult() {
|
||||||
|
if (!isClosed) {
|
||||||
|
throw new IllegalStateException("DecryptionStream MUST be closed before the result can be accessed.");
|
||||||
|
}
|
||||||
|
return resultBuilder.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.PainlessResult;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.PainlessStream;
|
import de.vanitasvitae.crypto.pgpainless.PainlessStream;
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
|
@ -60,12 +59,12 @@ public class DecryptionStreamFactory {
|
||||||
this.missingPublicKeyCallback = missingPublicKeyCallback;
|
this.missingPublicKeyCallback = missingPublicKeyCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PainlessResult.ResultAndInputStream create(InputStream inputStream,
|
public static DecryptionStream create(InputStream inputStream,
|
||||||
PGPSecretKeyRingCollection decryptionKeys,
|
PGPSecretKeyRingCollection decryptionKeys,
|
||||||
SecretKeyRingProtector decryptor,
|
SecretKeyRingProtector decryptor,
|
||||||
Set<PGPPublicKeyRing> verificationKeys,
|
Set<PGPPublicKeyRing> verificationKeys,
|
||||||
Set<Long> trustedKeyIds,
|
Set<Long> trustedKeyIds,
|
||||||
MissingPublicKeyCallback missingPublicKeyCallback)
|
MissingPublicKeyCallback missingPublicKeyCallback)
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
|
|
||||||
DecryptionStreamFactory factory = new DecryptionStreamFactory(decryptionKeys,
|
DecryptionStreamFactory factory = new DecryptionStreamFactory(decryptionKeys,
|
||||||
|
@ -77,9 +76,7 @@ public class DecryptionStreamFactory {
|
||||||
PGPObjectFactory objectFactory = new PGPObjectFactory(
|
PGPObjectFactory objectFactory = new PGPObjectFactory(
|
||||||
PGPUtil.getDecoderStream(inputStream), new BcKeyFingerprintCalculator());
|
PGPUtil.getDecoderStream(inputStream), new BcKeyFingerprintCalculator());
|
||||||
|
|
||||||
return new PainlessResult.ResultAndInputStream(
|
return new DecryptionStream(factory.wrap(objectFactory), factory.resultBuilder);
|
||||||
factory.resultBuilder,
|
|
||||||
new PainlessStream.In(factory.wrap(objectFactory)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream wrap(PGPObjectFactory objectFactory) throws IOException, PGPException {
|
private InputStream wrap(PGPObjectFactory objectFactory) throws IOException, PGPException {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless;
|
package de.vanitasvitae.crypto.pgpainless.decryption_verification;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -86,11 +86,11 @@ public class PainlessResult {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder getBuilder() {
|
static Builder getBuilder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
static class Builder {
|
||||||
|
|
||||||
private final Set<Long> recipientKeyIds = new HashSet<>();
|
private final Set<Long> recipientKeyIds = new HashSet<>();
|
||||||
private Long decryptionKeyId;
|
private Long decryptionKeyId;
|
||||||
|
@ -139,25 +139,4 @@ public class PainlessResult {
|
||||||
return new PainlessResult(recipientKeyIds, decryptionKeyId, symmetricKeyAlgorithm, compressionAlgorithm, integrityProtected, signatureKeyIds, verifiedSignatureKeyIds);
|
return new PainlessResult(recipientKeyIds, decryptionKeyId, symmetricKeyAlgorithm, compressionAlgorithm, integrityProtected, signatureKeyIds, verifiedSignatureKeyIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResultAndInputStream {
|
|
||||||
private final PainlessResult.Builder resultBuilder;
|
|
||||||
private final PainlessStream.In inputStream;
|
|
||||||
|
|
||||||
public ResultAndInputStream(PainlessResult.Builder resultBuilder, PainlessStream.In inputStream) {
|
|
||||||
this.resultBuilder = resultBuilder;
|
|
||||||
this.inputStream = inputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PainlessResult getResult() {
|
|
||||||
if (!inputStream.isClosed()) {
|
|
||||||
throw new IllegalStateException("InputStream must be closed before the PainlessResult can be accessed.");
|
|
||||||
}
|
|
||||||
return resultBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PainlessStream.In getInputStream() {
|
|
||||||
return inputStream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -4,12 +4,10 @@ import java.io.FilterInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.PainlessResult;
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPObjectFactory;
|
import org.bouncycastle.openpgp.PGPObjectFactory;
|
||||||
import org.bouncycastle.openpgp.PGPOnePassSignature;
|
import org.bouncycastle.openpgp.PGPOnePassSignature;
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.decryption_verification;
|
|
||||||
|
|
||||||
public class VerificationFeedbackCallback {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,16 +3,25 @@ package de.vanitasvitae.crypto.pgpainless.encryption_signing;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.PublicKeyNotFoundException;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.SecretKeyNotFoundException;
|
import de.vanitasvitae.crypto.pgpainless.SecretKeyNotFoundException;
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.key.PublicKeySelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.key.SecretKeySelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.key.impl.And;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.key.impl.EncryptionKeySelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.key.impl.NoRevocation;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.key.impl.SignatureKeySelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.keyring.PublicKeyRingSelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.keyring.SecretKeyRingSelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.util.MultiMap;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPrivateKey;
|
import org.bouncycastle.openpgp.PGPPrivateKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
|
@ -42,19 +51,22 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
class ToRecipientsImpl implements ToRecipients {
|
class ToRecipientsImpl implements ToRecipients {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithAlgorithms toRecipient(PGPPublicKey key) {
|
public WithAlgorithms toRecipients(PGPPublicKey... keys) {
|
||||||
if (!key.isEncryptionKey()) {
|
for (PGPPublicKey k : keys) {
|
||||||
throw new IllegalStateException("Public Key " + Long.toHexString(key.getKeyID()) + " is not capable of encryption.");
|
if (encryptionKeySelector().accept(null, k)) {
|
||||||
|
EncryptionBuilder.this.encryptionKeys.add(k);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Key " + k.getKeyID() + " is not a valid encryption key.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EncryptionBuilder.this.encryptionKeys.add(key);
|
|
||||||
return new WithAlgorithmsImpl();
|
return new WithAlgorithmsImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithAlgorithms toRecipients(Set<PGPPublicKeyRing> keys) {
|
public WithAlgorithms toRecipients(PGPPublicKeyRing... keys) {
|
||||||
for (PGPPublicKeyRing ring : keys) {
|
for (PGPPublicKeyRing ring : keys) {
|
||||||
for (PGPPublicKey k : ring) {
|
for (PGPPublicKey k : ring) {
|
||||||
if (k.isEncryptionKey()) {
|
if (encryptionKeySelector().accept(null, k)) {
|
||||||
EncryptionBuilder.this.encryptionKeys.add(k);
|
EncryptionBuilder.this.encryptionKeys.add(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,25 +75,20 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithAlgorithms toRecipients(Set<Long> keyIds, Set<PGPPublicKeyRingCollection> keys)
|
public <O>WithAlgorithms toRecipients(PublicKeyRingSelectionStrategy<O> ringSelectionStrategy,
|
||||||
throws PublicKeyNotFoundException {
|
MultiMap<O, PGPPublicKeyRingCollection> keys) {
|
||||||
Set<PGPPublicKeyRing> rings = new HashSet<>();
|
MultiMap<O, PGPPublicKeyRing> acceptedKeyRings = ringSelectionStrategy.selectKeyRingsFromCollections(keys);
|
||||||
|
for (O identifier : acceptedKeyRings.keySet()) {
|
||||||
for (PGPPublicKeyRingCollection collection : keys) {
|
Set<PGPPublicKeyRing> acceptedSet = acceptedKeyRings.get(identifier);
|
||||||
for (long keyId : keyIds) {
|
for (PGPPublicKeyRing ring : acceptedSet) {
|
||||||
try {
|
for (PGPPublicKey k : ring) {
|
||||||
PGPPublicKeyRing ring = collection.getPublicKeyRing(keyId);
|
if (encryptionKeySelector().accept(null, k)) {
|
||||||
if (ring != null) {
|
EncryptionBuilder.this.encryptionKeys.add(k);
|
||||||
rings.add(ring);
|
|
||||||
keyIds.remove(keyId);
|
|
||||||
}
|
}
|
||||||
} catch (PGPException e) {
|
|
||||||
throw new PublicKeyNotFoundException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new WithAlgorithmsImpl();
|
||||||
return toRecipients(rings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,17 +100,23 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
class WithAlgorithmsImpl implements WithAlgorithms {
|
class WithAlgorithmsImpl implements WithAlgorithms {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithAlgorithms andToSelf(PGPPublicKey key) {
|
public WithAlgorithms andToSelf(PGPPublicKey... keys) {
|
||||||
EncryptionBuilder.this.encryptionKeys.add(key);
|
for (PGPPublicKey k : keys) {
|
||||||
|
if (encryptionKeySelector().accept(null, k)) {
|
||||||
|
EncryptionBuilder.this.encryptionKeys.add(k);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Key " + k.getKeyID() + " is not a valid encryption key.");
|
||||||
|
}
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithAlgorithms andToSelf(Set<PGPPublicKeyRing> keyRings) {
|
public WithAlgorithms andToSelf(PGPPublicKeyRing... keyRings) {
|
||||||
for (PGPPublicKeyRing ring : keyRings) {
|
for (PGPPublicKeyRing ring : keyRings) {
|
||||||
for (Iterator<PGPPublicKey> i = ring.getPublicKeys(); i.hasNext(); ) {
|
for (Iterator<PGPPublicKey> i = ring.getPublicKeys(); i.hasNext(); ) {
|
||||||
PGPPublicKey key = i.next();
|
PGPPublicKey key = i.next();
|
||||||
if (key.isEncryptionKey()) {
|
if (encryptionKeySelector().accept(null, key)) {
|
||||||
EncryptionBuilder.this.encryptionKeys.add(key);
|
EncryptionBuilder.this.encryptionKeys.add(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,6 +124,24 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <O>WithAlgorithms andToSelf(PublicKeyRingSelectionStrategy<O> ringSelectionStrategy,
|
||||||
|
MultiMap<O, PGPPublicKeyRingCollection> keyRingCollections) {
|
||||||
|
MultiMap<O, PGPPublicKeyRing> acceptedKeyRings =
|
||||||
|
ringSelectionStrategy.selectKeyRingsFromCollections(keyRingCollections);
|
||||||
|
for (O identifier : acceptedKeyRings.keySet()) {
|
||||||
|
Set<PGPPublicKeyRing> acceptedSet = acceptedKeyRings.get(identifier);
|
||||||
|
for (PGPPublicKeyRing k : acceptedSet) {
|
||||||
|
for (Iterator<PGPPublicKey> i = k.getPublicKeys(); i.hasNext(); ) {
|
||||||
|
PGPPublicKey key = i.next();
|
||||||
|
if (encryptionKeySelector().accept(null, key)) {
|
||||||
|
EncryptionBuilder.this.encryptionKeys.add(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SignWith usingAlgorithms(SymmetricKeyAlgorithm symmetricKeyAlgorithm,
|
public SignWith usingAlgorithms(SymmetricKeyAlgorithm symmetricKeyAlgorithm,
|
||||||
HashAlgorithm hashAlgorithm,
|
HashAlgorithm hashAlgorithm,
|
||||||
|
@ -136,16 +167,24 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
class SignWithImpl implements SignWith {
|
class SignWithImpl implements SignWith {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Armor signWith(PGPSecretKeyRing key, SecretKeyRingProtector decryptor) {
|
public <O> Armor signWith(SecretKeyRingProtector decryptor, PGPSecretKey... keys) {
|
||||||
return signWith(Collections.singleton(key), decryptor);
|
for (PGPSecretKey s : keys) {
|
||||||
|
if (EncryptionBuilder.this.<O>signingKeySelector().accept(null, s)) {
|
||||||
|
signingKeys.add(s);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Key " + s.getKeyID() + " is not a valid signing key.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EncryptionBuilder.this.signingKeysDecryptor = decryptor;
|
||||||
|
return new ArmorImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Armor signWith(Set<PGPSecretKeyRing> keys, SecretKeyRingProtector decryptor) {
|
public <O> Armor signWith(SecretKeyRingProtector decryptor, PGPSecretKeyRing... keys) {
|
||||||
for (PGPSecretKeyRing key : keys) {
|
for (PGPSecretKeyRing key : keys) {
|
||||||
for (Iterator<PGPSecretKey> i = key.getSecretKeys(); i.hasNext(); ) {
|
for (Iterator<PGPSecretKey> i = key.getSecretKeys(); i.hasNext(); ) {
|
||||||
PGPSecretKey s = i.next();
|
PGPSecretKey s = i.next();
|
||||||
if (s.isSigningKey()) {
|
if (EncryptionBuilder.this.<O>signingKeySelector().accept(null, s)) {
|
||||||
EncryptionBuilder.this.signingKeys.add(s);
|
EncryptionBuilder.this.signingKeys.add(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,23 +194,23 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Armor signWith(Set<Long> keyIds, Set<PGPSecretKeyRingCollection> keyRings, SecretKeyRingProtector decryptor)
|
public <O>Armor signWith(SecretKeyRingSelectionStrategy<O> ringSelectionStrategy,
|
||||||
throws SecretKeyNotFoundException {
|
SecretKeyRingProtector decryptor,
|
||||||
Set<PGPSecretKeyRing> rings = new HashSet<>();
|
MultiMap<O, PGPSecretKeyRingCollection> keyRingCollections) {
|
||||||
for (PGPSecretKeyRingCollection collection : keyRings) {
|
MultiMap<O, PGPSecretKeyRing> acceptedKeyRings =
|
||||||
for (long keyId : keyIds) {
|
ringSelectionStrategy.selectKeyRingsFromCollections(keyRingCollections);
|
||||||
try {
|
for (O identifier : acceptedKeyRings.keySet()) {
|
||||||
PGPSecretKeyRing ring = collection.getSecretKeyRing(keyId);
|
Set<PGPSecretKeyRing> acceptedSet = acceptedKeyRings.get(identifier);
|
||||||
if (ring != null) {
|
for (PGPSecretKeyRing k : acceptedSet) {
|
||||||
rings.add(ring);
|
for (Iterator<PGPSecretKey> i = k.getSecretKeys(); i.hasNext(); ) {
|
||||||
keyIds.remove(keyId);
|
PGPSecretKey s = i.next();
|
||||||
|
if (EncryptionBuilder.this.<O>signingKeySelector().accept(null, s)) {
|
||||||
|
EncryptionBuilder.this.signingKeys.add(s);
|
||||||
}
|
}
|
||||||
} catch (PGPException e) {
|
|
||||||
throw new SecretKeyNotFoundException(keyId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return signWith(rings, decryptor);
|
return new ArmorImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -211,4 +250,16 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
EncryptionBuilder.this.asciiArmor);
|
EncryptionBuilder.this.asciiArmor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<O> PublicKeySelectionStrategy<O> encryptionKeySelector() {
|
||||||
|
return new And.PubKeySelectionStrategy<>(
|
||||||
|
new NoRevocation.PubKeySelectionStrategy<>(),
|
||||||
|
new EncryptionKeySelectionStrategy<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
<O> SecretKeySelectionStrategy<O> signingKeySelector() {
|
||||||
|
return new And.SecKeySelectionStrategy<>(
|
||||||
|
new NoRevocation.SecKeySelectionStrategy<>(),
|
||||||
|
new SignatureKeySelectionStrategy<>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,14 @@ import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.keyring.PublicKeyRingSelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.keyring.SecretKeyRingSelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.util.MultiMap;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
|
|
||||||
|
@ -23,12 +27,12 @@ public interface EncryptionBuilderInterface {
|
||||||
|
|
||||||
interface ToRecipients {
|
interface ToRecipients {
|
||||||
|
|
||||||
WithAlgorithms toRecipient(PGPPublicKey key);
|
WithAlgorithms toRecipients(PGPPublicKey... keys);
|
||||||
|
|
||||||
WithAlgorithms toRecipients(Set<PGPPublicKeyRing> keys);
|
WithAlgorithms toRecipients(PGPPublicKeyRing... keys);
|
||||||
|
|
||||||
WithAlgorithms toRecipients(Set<Long> keyIds, Set<PGPPublicKeyRingCollection> keys)
|
<O> WithAlgorithms toRecipients(PublicKeyRingSelectionStrategy<O> selectionStrategy,
|
||||||
throws PublicKeyNotFoundException;
|
MultiMap<O, PGPPublicKeyRingCollection> keys);
|
||||||
|
|
||||||
SignWith doNotEncrypt();
|
SignWith doNotEncrypt();
|
||||||
|
|
||||||
|
@ -36,9 +40,12 @@ public interface EncryptionBuilderInterface {
|
||||||
|
|
||||||
interface WithAlgorithms {
|
interface WithAlgorithms {
|
||||||
|
|
||||||
WithAlgorithms andToSelf(PGPPublicKey key);
|
WithAlgorithms andToSelf(PGPPublicKey... keys);
|
||||||
|
|
||||||
WithAlgorithms andToSelf(Set<PGPPublicKeyRing> keys);
|
WithAlgorithms andToSelf(PGPPublicKeyRing... keys);
|
||||||
|
|
||||||
|
<O> WithAlgorithms andToSelf(PublicKeyRingSelectionStrategy<O> selectionStrategy,
|
||||||
|
MultiMap<O, PGPPublicKeyRingCollection> keys);
|
||||||
|
|
||||||
SignWith usingAlgorithms(SymmetricKeyAlgorithm symmetricKeyAlgorithm,
|
SignWith usingAlgorithms(SymmetricKeyAlgorithm symmetricKeyAlgorithm,
|
||||||
HashAlgorithm hashAlgorithm,
|
HashAlgorithm hashAlgorithm,
|
||||||
|
@ -50,12 +57,13 @@ public interface EncryptionBuilderInterface {
|
||||||
|
|
||||||
interface SignWith {
|
interface SignWith {
|
||||||
|
|
||||||
Armor signWith(PGPSecretKeyRing key, SecretKeyRingProtector decryptor);
|
<O> Armor signWith(SecretKeyRingProtector decryptor, PGPSecretKey... keys);
|
||||||
|
|
||||||
Armor signWith(Set<PGPSecretKeyRing> keyRings, SecretKeyRingProtector decryptor)
|
<O> Armor signWith(SecretKeyRingProtector decryptor, PGPSecretKeyRing... keyRings);
|
||||||
throws SecretKeyNotFoundException;
|
|
||||||
|
|
||||||
Armor signWith(Set<Long> keyIds, Set<PGPSecretKeyRingCollection> keys, SecretKeyRingProtector decryptor)
|
<O> Armor signWith(SecretKeyRingSelectionStrategy<O> selectionStrategy,
|
||||||
|
SecretKeyRingProtector decryptor,
|
||||||
|
MultiMap<O, PGPSecretKeyRingCollection> keys)
|
||||||
throws SecretKeyNotFoundException;
|
throws SecretKeyNotFoundException;
|
||||||
|
|
||||||
Armor doNotSign();
|
Armor doNotSign();
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package de.vanitasvitae.crypto.pgpainless.key.selection.key.impl;
|
||||||
|
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.key.PublicKeySelectionStrategy;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.key.selection.key.SecretKeySelectionStrategy;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
|
|
||||||
|
public class And {
|
||||||
|
|
||||||
|
public static class PubKeySelectionStrategy<O> extends PublicKeySelectionStrategy<O> {
|
||||||
|
|
||||||
|
private final PublicKeySelectionStrategy<O> left;
|
||||||
|
private final PublicKeySelectionStrategy<O> right;
|
||||||
|
|
||||||
|
public PubKeySelectionStrategy(PublicKeySelectionStrategy<O> left,
|
||||||
|
PublicKeySelectionStrategy<O> right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(O identifier, PGPPublicKey key) {
|
||||||
|
return left.accept(identifier, key) && right.accept(identifier, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SecKeySelectionStrategy<O> extends SecretKeySelectionStrategy<O> {
|
||||||
|
|
||||||
|
private final SecretKeySelectionStrategy<O> left;
|
||||||
|
private final SecretKeySelectionStrategy<O> right;
|
||||||
|
|
||||||
|
public SecKeySelectionStrategy(SecretKeySelectionStrategy<O> left,
|
||||||
|
SecretKeySelectionStrategy<O> right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(O identifier, PGPSecretKey key) {
|
||||||
|
return left.accept(identifier, key) && right.accept(identifier, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.util;
|
package de.vanitasvitae.crypto.pgpainless.util;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
|
@ -12,7 +14,6 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
|
|
||||||
|
|
||||||
public class BCUtil {
|
public class BCUtil {
|
||||||
|
|
||||||
|
@ -26,14 +27,23 @@ public class BCUtil {
|
||||||
return new PGPSecretKeyRingCollection(Arrays.asList(rings));
|
return new PGPSecretKeyRingCollection(Arrays.asList(rings));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PGPPublicKeyRing publicKeyRingFromSecretKeyRing(PGPSecretKeyRing ring) throws IOException {
|
public static PGPPublicKeyRing publicKeyRingFromSecretKeyRing(PGPSecretKeyRing secring) {
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
List<PGPPublicKey> list = new ArrayList<>();
|
||||||
for (Iterator<PGPPublicKey> i = ring.getPublicKeys(); i.hasNext(); ) {
|
for (Iterator<PGPPublicKey> i = secring.getPublicKeys(); i.hasNext(); ) {
|
||||||
PGPPublicKey k = i.next();
|
PGPPublicKey k = i.next();
|
||||||
k.encode(buffer);
|
list.add(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Change to simply using the List constructor once BC 1.60 gets released.
|
||||||
|
try {
|
||||||
|
Constructor<PGPPublicKeyRing> constructor;
|
||||||
|
constructor = PGPPublicKeyRing.class.getDeclaredConstructor(List.class);
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
PGPPublicKeyRing pubring = constructor.newInstance(list);
|
||||||
|
return pubring;
|
||||||
|
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
buffer.close();
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(buffer.toByteArray());
|
|
||||||
return new PGPPublicKeyRing(in, new BcKeyFingerprintCalculator());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package de.vanitasvitae.crypto.pgpainless;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.NoSuchProviderException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.util.BCUtil;
|
||||||
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class BCUtilTest extends AbstractPGPainlessTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test()
|
||||||
|
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException,
|
||||||
|
IOException {
|
||||||
|
PGPSecretKeyRing sec = PGPainless.generateKeyRing().simpleEcKeyRing("Hallo Welt");
|
||||||
|
PGPPublicKeyRing pub = BCUtil.publicKeyRingFromSecretKeyRing(sec);
|
||||||
|
|
||||||
|
int secSize = 0;
|
||||||
|
Iterator<PGPPublicKey> secPubIt = sec.getPublicKeys();
|
||||||
|
while (secPubIt.hasNext()) {
|
||||||
|
secPubIt.next();
|
||||||
|
secSize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pubSize = 0;
|
||||||
|
Iterator<PGPPublicKey> pubPubIt = pub.getPublicKeys();
|
||||||
|
while (pubPubIt.hasNext()) {
|
||||||
|
pubPubIt.next();
|
||||||
|
pubSize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(secSize, pubSize);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ import static junit.framework.TestCase.assertTrue;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
@ -16,6 +15,8 @@ import java.util.Collections;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.decryption_verification.DecryptionStream;
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.decryption_verification.PainlessResult;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
import de.vanitasvitae.crypto.pgpainless.key.SecretKeyRingProtector;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.UnprotectedKeysProtector;
|
import de.vanitasvitae.crypto.pgpainless.key.UnprotectedKeysProtector;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.RsaLength;
|
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.RsaLength;
|
||||||
|
@ -90,9 +91,9 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest {
|
||||||
|
|
||||||
OutputStream encryptor = PGPainless.createEncryptor()
|
OutputStream encryptor = PGPainless.createEncryptor()
|
||||||
.onOutputStream(envelope)
|
.onOutputStream(envelope)
|
||||||
.toRecipients(Collections.singleton(recipientPub))
|
.toRecipients(recipientPub)
|
||||||
.usingSecureAlgorithms()
|
.usingSecureAlgorithms()
|
||||||
.signWith(sender, keyDecryptor)
|
.signWith(keyDecryptor, sender)
|
||||||
.noArmor();
|
.noArmor();
|
||||||
|
|
||||||
Streams.pipeAll(new ByteArrayInputStream(secretMessage), encryptor);
|
Streams.pipeAll(new ByteArrayInputStream(secretMessage), encryptor);
|
||||||
|
@ -102,21 +103,20 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest {
|
||||||
// Juliet trieth to comprehend Romeos words
|
// Juliet trieth to comprehend Romeos words
|
||||||
|
|
||||||
ByteArrayInputStream envelopeIn = new ByteArrayInputStream(encryptedSecretMessage);
|
ByteArrayInputStream envelopeIn = new ByteArrayInputStream(encryptedSecretMessage);
|
||||||
PainlessResult.ResultAndInputStream resultAndInputStream = PGPainless.createDecryptor()
|
DecryptionStream decryptor = PGPainless.createDecryptor()
|
||||||
.onInputStream(envelopeIn)
|
.onInputStream(envelopeIn)
|
||||||
.decryptWith(BCUtil.keyRingsToKeyRingCollection(recipient), keyDecryptor)
|
.decryptWith(BCUtil.keyRingsToKeyRingCollection(recipient), keyDecryptor)
|
||||||
.verifyWith(Collections.singleton(TestKeys.ROMEO_KEY_ID), BCUtil.keyRingsToKeyRingCollection(senderPub))
|
.verifyWith(Collections.singleton(TestKeys.ROMEO_KEY_ID), BCUtil.keyRingsToKeyRingCollection(senderPub))
|
||||||
.ignoreMissingPublicKeys()
|
.ignoreMissingPublicKeys()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
InputStream decryptor = resultAndInputStream.getInputStream();
|
|
||||||
OutputStream decryptedSecretMessage = new ByteArrayOutputStream();
|
OutputStream decryptedSecretMessage = new ByteArrayOutputStream();
|
||||||
|
|
||||||
Streams.pipeAll(decryptor, decryptedSecretMessage);
|
Streams.pipeAll(decryptor, decryptedSecretMessage);
|
||||||
decryptor.close();
|
decryptor.close();
|
||||||
|
|
||||||
assertTrue(Arrays.equals(secretMessage, ((ByteArrayOutputStream) decryptedSecretMessage).toByteArray()));
|
assertTrue(Arrays.equals(secretMessage, ((ByteArrayOutputStream) decryptedSecretMessage).toByteArray()));
|
||||||
PainlessResult result = resultAndInputStream.getResult();
|
PainlessResult result = decryptor.getResult();
|
||||||
assertTrue(result.containsVerifiedSignatureFrom(senderPub));
|
assertTrue(result.containsVerifiedSignatureFrom(senderPub));
|
||||||
assertTrue(result.isIntegrityProtected());
|
assertTrue(result.isIntegrityProtected());
|
||||||
assertTrue(result.isSigned());
|
assertTrue(result.isSigned());
|
||||||
|
|
|
@ -6,11 +6,11 @@ import static junit.framework.TestCase.assertTrue;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import de.vanitasvitae.crypto.pgpainless.decryption_verification.DecryptionStream;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.UnprotectedKeysProtector;
|
import de.vanitasvitae.crypto.pgpainless.key.UnprotectedKeysProtector;
|
||||||
import de.vanitasvitae.crypto.pgpainless.util.BCUtil;
|
import de.vanitasvitae.crypto.pgpainless.util.BCUtil;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
@ -39,7 +39,7 @@ public class TestKeysTest extends AbstractPGPainlessTest {
|
||||||
public void decryptVerifyTest() throws Exception {
|
public void decryptVerifyTest() throws Exception {
|
||||||
String encryptedMessage = TestKeys.TEST_MESSAGE_01;
|
String encryptedMessage = TestKeys.TEST_MESSAGE_01;
|
||||||
|
|
||||||
PainlessResult.ResultAndInputStream resultAndInputStream = PGPainless.createDecryptor()
|
DecryptionStream decryptor = PGPainless.createDecryptor()
|
||||||
.onInputStream(new ByteArrayInputStream(encryptedMessage.getBytes()))
|
.onInputStream(new ByteArrayInputStream(encryptedMessage.getBytes()))
|
||||||
.decryptWith(new PGPSecretKeyRingCollection(Collections.singleton(juliet)), new UnprotectedKeysProtector())
|
.decryptWith(new PGPSecretKeyRingCollection(Collections.singleton(juliet)), new UnprotectedKeysProtector())
|
||||||
.verifyWith(
|
.verifyWith(
|
||||||
|
@ -48,7 +48,6 @@ public class TestKeysTest extends AbstractPGPainlessTest {
|
||||||
.ignoreMissingPublicKeys()
|
.ignoreMissingPublicKeys()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
InputStream decryptor = resultAndInputStream.getInputStream();
|
|
||||||
ByteArrayOutputStream toPlain = new ByteArrayOutputStream();
|
ByteArrayOutputStream toPlain = new ByteArrayOutputStream();
|
||||||
Streams.pipeAll(decryptor, toPlain);
|
Streams.pipeAll(decryptor, toPlain);
|
||||||
decryptor.close();
|
decryptor.close();
|
||||||
|
|
Loading…
Reference in a new issue